How to span wide tables across multiple pages horizontally? - java

I am looking for a method to split wide tables so that they span across multiple pages. The goal is to make tables with large number of columns readable. I found one discussion thread where this topic is covered; however, the example referenced in there is not available. Manning's "iText in Action" (2006) doesn't cover this topic.
Can this be done in version 1.4.8, if not, to which version of iText should I upgrade to?

Please take a look at the examples of chapter 4 of my book, more specifically at the Zhang example. In this example, I have a table with four columns: (1) year, (2) movie title in English, (3) movie title in Chinese, and (4) run length. If you look at the resulting PDF, you will see that this table is split vertically.
Achieving this requires more work then simply adding a table and allowing iText to decide how to split it in between rows. When you want to split in between columns, you need to organize the layout in your code. This is done using the writeSelectedRows()) method.
In my simple book example, I use these lines:
// draw the first two columns on one page
table.writeSelectedRows(0, 2, 0, -1, 236, 806, canvas);
document.newPage();
// draw the remaining two columns on the next page
table.writeSelectedRows(2, -1, 0, -1, 36, 806, canvas);
First I draw the columns from index 0 to index 2. The column with index 0 is the first column, the column with index 2 is the first column that isn't included, namely the third column. I draw the rows from index 0 (first row) until -1. Minus one means: draw all the remaining rows.
You also see minus one on the next page, where I draw the column with index 2 (the third column) until the column with index -1 (meaning: the rest of the columns).
The values (236, 806) and (36, 806) are coordinates: that's where you want the table to start. You can't define "end coordinates". If the table doesn't fit on the page, iText will just continue drawing the table, even if that means that some content exceeds the visible area of the page. This means that you'll have to be very careful when using this method: you'll need to calculate widths and heights of rows and columns before adding the table, otherwise you may end up with parts of the table that aren't visible.

This is the source code of a class that splits your table over multiple pages when your columns don't fit in a single page
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfPTable;
import com.lowagie.text.pdf.PdfWriter;
/**
* Class that writes a <code>PdfPTable</code>, and spans it across multiple
* pages if the columns won't fit on one page
*/
public class PdfPTableWriter {
// Instance variables
private PdfPTable table;
private PdfWriter writer;
private Document document;
// List of how many columns per horizontal page
private List numberOfColumnsPerPage;
// List of how many rows per vertical page
private List numberOfRowsPerPage;
// Offsets if given
private float widthOffset = 20;
private float heightOffset = 70;
/**
* Class Constructor
*/
public PdfPTableWriter(Document document, PdfWriter writer, PdfPTable table) {
this.document = document;
this.writer = writer;
this.table = table;
calculateColumns();
calculateRows();
}
/**
* Writes the table to the document
*/
public void writeTable() throws DocumentException {
// Begin at row 1 (row after the header)
int rowBegin = 1;
int rowEnd = 0;
// Note the size of numberOfRowsPerPage is how many vertical
// pages there are.
Iterator rowsIter = numberOfRowsPerPage.iterator();
while (rowsIter.hasNext()) {
rowEnd = ((Integer) rowsIter.next()).intValue();
writeSelectedRows(rowBegin, rowEnd);
rowBegin = rowEnd;
}
}
/**
* Prints the Report's columns (splitting horizontally if necessary) and
* subsequent rows
*
* #param rowBegin
* #param rowEnd
* #throws DocumentException
*/
private void writeSelectedRows(int rowBegin, int rowEnd) throws DocumentException {
int colBegin = 0;
int colEnd = 0;
float pageHeight = document.getPageSize().getHeight() - heightOffset;
PdfContentByte contentByte = writer.getDirectContent();
Iterator columnsIter = numberOfColumnsPerPage.iterator();
while (columnsIter.hasNext()) {
colEnd = colBegin + ((Integer) columnsIter.next()).intValue();
// Writer table header
writeSelectedRows(colBegin, colEnd, 0, 1, widthOffset, pageHeight);
// Writes selected rows to the document
writeSelectedRows(colBegin, colEnd, rowBegin, rowEnd, widthOffset, pageHeight - table.getRowHeight(0) /*table.getHeaderHeight()*/);
// Add a new page
document.newPage();
colBegin = colEnd;
}
}
public int getTotalPages() {
return numberOfColumnsPerPage.size() * numberOfRowsPerPage.size();
}
public void setHeightOffset(float heightOffset) {
this.heightOffset = heightOffset;
}
public void setWidthOffset(float widthOffset) {
this.widthOffset = widthOffset;
}
private void writeSelectedRows(int colBegin, int colEnd, int rowBegin, int rowEnd, float x, float y) {
PdfContentByte cb = writer.getDirectContent();
table.writeSelectedRows(colBegin, colEnd, rowBegin, rowEnd, x, y, cb);
}
private void calculateColumns() {
numberOfColumnsPerPage = new ArrayList();
float pageWidth = document.getPageSize().getWidth() - widthOffset;
float[] widths = table.getAbsoluteWidths();
if (table.getTotalWidth() > pageWidth) {
// tmp variable for amount of total width thus far
float tmp = 0f;
// How many columns for this page
int columnCount = 0;
// Current page we're on
int currentPage = 0;
// Iterate through the column widths
for (int i = 0; i < widths.length; i++) {
// Add to the temporary total
tmp += widths[i];
// If this column will not fit on the page
if (tmp > pageWidth) {
// Add the current column count to this page
numberOfColumnsPerPage.add(new Integer(columnCount));
// Since this column won't fit, the tmp variable should
// start off the next iteration
// as this column's width
tmp = widths[i];
// Set column count to 1, since we have moved this column to
// the next page
columnCount = 1;
}
// If this is will fit on the page
else {
// Increase the column count
columnCount++;
}
}
// Save the remaining columns
numberOfColumnsPerPage.add(new Integer(columnCount));
}
// All the columns will fit on one horizontal page
// Note: -1 means all the columns
else {
numberOfColumnsPerPage.add(new Integer(-1));
}
}
private void calculateRows() {
numberOfRowsPerPage = new ArrayList();
float pageHeight = document.getPageSize().getHeight() - heightOffset - table.getRowHeight(0) /*table.getHeaderHeight()*/;
// If the table won't fit on the first page
if (table.getTotalHeight() > pageHeight /*table.getHeaderHeight()*/) {
// Temp variables
float tmp = 0f;
// Determine the start and end rows for each page
for (int i = 1; i < table.size(); i++) {
// Add this row's height to the tmp total
tmp += table.getRowHeight(i);
if (tmp > pageHeight - (heightOffset/2)) {
// This row won't fit so end at previous row
numberOfRowsPerPage.add(new Integer(i - 1));
// Since this row won't fit, the tmp variable should start
// off the next iteration
// as this row's height
tmp = table.getRowHeight(i);
}
}
// Last page always ends on totalRows
numberOfRowsPerPage.add(new Integer(table.size()));
}
// All the rows will fit on one vertical page
// Note: -1 means all the rows
else {
numberOfRowsPerPage.add(new Integer(-1));
}
}
}

Well, I'll try to give you some kind of response. First at all, as #mkl says, 1.4.8 is ancient version. Look at http://sourceforge.net/projects/itext/files/iText/ to get something better, the last version is 5.4.5. And as I know, there is no way to split wide table in two pages. If the document is "a bit" wider than the page - rotate the page, but if you have many columns that don't fit - you have to do it your way and this could be painful. There is no automatic function that can check if your columns have too much text and don't fit the page.
Hope this helps you.

Related

Java iText7 get Table height [duplicate]

In iText5, we can get the PdfPTable's height when we need "public float calculateHeights(boolean firsttime)".
But in iText7, how can we get current table height value (especially before adding the table to its parent element)?
I already tested "table.getHeight()" method, but it returns null.
And I also found that in a table render object I can get this value, but the limitation is that the render need to be triggered when the table is adding into its parent element, so the time is not my need.
Cause sometimes we need this value for calculation to decide the "y-axis" value.
In iText5, elements and information about their position/size were a bit mixed together, which allowed you to call calculateWidths on a PdfPTable element.
In iText7, this functionality is separated, which allows different kind of flexibility for rendering/layouting elements.
Thus, model elements, which a Table instance is an example of, do not know anything about their position or size. And calling table.getHeight results in null because table did not have HEIGHT property previously set to it.
To calculate table height, one would have to make use of the rendering functionality.
For a model element, you can get the subtree of renderers representing this model element and all its children, and layout it in any given area. To really know the height of a table, you would want to create an area which knowingly will be sufficient to place the whole contents of the element.
PdfDocument pdfDoc = ...
Document doc = ...
Table table = new Table(2)
.addCell(new Cell().add(new Paragraph("cell 1, 1")))
.addCell(new Cell().add(new Paragraph("cell 1, 2")));
LayoutResult result = table.createRendererSubTree().setParent(doc.getRenderer()).layout(
new LayoutContext(new LayoutArea(1, new Rectangle(0, 0, 400, 1e4f))));
System.out.println(result.getOccupiedArea().getBBox().getHeight());
The code above prints 22.982422O for me, but the results may vary depending on the configuration and properties of elements.
I would like to point out two important parts of the code:
We pass 1e4f as the height of the LayoutArea, considering that this will be sufficient to place the whole table. Note that if the table cannot be placed into that height, the result will never exceed this given height and thus it will not be correct for your usecase (know the total height of the table). So make sure to pass the height which will be sufficient for placement of the whole table.
.setParent(doc.getRenderer()) part is important here and is used for retrieving inheritant properties. Note that we did not set a lot of properties to table element, even font, but this information is essential to know the area this element would occupy. So this information will be inherited from the parent chain during layout. You can test this by changing the document's font: document.setFont(newFont);, or font size: document.setFontSize(24); and watching the resultant height change
Well, due to the way the renderer framework is written in iText7, there isn't a way (yet) to calculate the height of a layout object before it is added to a parent document, since the actual calculation of the height for the layout objects happens when they are added to the a Document object.
You can however relayout a Document, allowing you to change the content of previously added elements. Using this, you can simulate the rendering of tables and get a hold of their heights when you add new elements. The table.getHeight() still won't work, since it retrieves the height property, and that property is currently not set anywhere in the table rendering process.
In the example below, I've written a convenience method that iterates over the renderer-tree and prints out the area each table occupies in the document, to show you how you can get the calculated heights.
The example itself adds some tables to the document, displays the occupied areas, adds some cells to each table, displays the occupied areas (they're the same since adding to an element that has been added before doesn't trigger a layout), and finally, manually triggers a relayout and displays the final occupied areas.
public class DelayedLayout {
public static String DEST = "target/output/StackOverflow/DelayedLayout/delayed.pdf";
public static void main(String[] args)throws IOException, FileNotFoundException{
File file = new File(DEST);
file.getParentFile().mkdirs();
new DelayedLayout().createPdf(DEST);
}
public void createPdf(String dest) throws IOException, FileNotFoundException{
PdfWriter writer = new PdfWriter(dest);
PdfDocument pdfDoc = new PdfDocument(writer);
boolean immediateFlush = false;
boolean relayout = true;
//Set immediate layout to false, so the document doesn't immediatly write render-results to its outputstream
Document doc = new Document(pdfDoc, PageSize.A4,immediateFlush);
Table tOne = createSimpleTable();
for(int i= 0; i< 5; i++) {
//Add a table and some whitespace
doc.add(tOne);
doc.add(new Paragraph(""));
}
System.out.println("\nInitial layout results");
printOccupiedAreasOfTableRenderers(doc.getRenderer());
System.out.println("\nAdding extra cells to the table");
addToTable(tOne);
printOccupiedAreasOfTableRenderers(doc.getRenderer());
System.out.println("\nForcing the document to redo the layout");
if(relayout)doc.relayout();
printOccupiedAreasOfTableRenderers(doc.getRenderer());
doc.close();
}
/**
* Create a very simple table
* #return simple table
*/
private Table createSimpleTable(){
int nrOfCols = 3;
int nrOfRows = 5;
Table res = new Table(nrOfCols);
for(int i= 0; i<nrOfRows;i++){
for(int j = 0; j<nrOfCols;j++){
Cell c = new Cell();
c.add(new Paragraph("["+i+", "+j+"]"));
res.addCell(c);
}
}
return res;
}
/**
* Add some extra cells to an exisiting table
* #param tab table to add cells to
*/
private void addToTable(Table tab){
int nrOfRows = 5;
int nrOfCols = tab.getNumberOfColumns();
for(int i=0; i<nrOfRows*nrOfCols;i++){
Cell c = new Cell();
c.add(new Paragraph("Extra cell"+ i));
tab.addCell(c);
}
}
/**
* Recursively iterate over the renderer tree, writing the occupied area to the console
* #param currentNode current renderer-node to check
*/
private void printOccupiedAreasOfTableRenderers(IRenderer currentNode){
if(currentNode.getClass().equals(TableRenderer.class)){
System.out.println("Table renderer with occupied area: " + currentNode.getOccupiedArea());
}
for (IRenderer child:currentNode.getChildRenderers()) {
printOccupiedAreasOfTableRenderers(child);
}
}

How can I fill the remaining blank portion of the page in Itext5?

As seen above,i used pdfTable as the body part of the page. Now i want to fill the entire body with the border,column,row of the table, if the table does not fill the entire body part.As shown in the picture below.
Thanks very much!
You can sort of cheat to accomplish this if you do it while you are creating the table.
I'll offer a partial solution that takes advantage of one of the complexities tables in PDFs: Tables are just lines in PDFs. They aren't structured content.
You can take advantage of this though- keep track of where you are are drawing vertical lines while rendering the table and simply continue them to the bottom of the page.
Let's create a new cell event. It keeps track of 4 things: left which is the far left x coordinate of the table, right which is the far right x coordinate of the table, xCoordinates which is a set of all the x coordinates we draw vertical lines, and finally cellHeights which is a list off all the cell heights.
class CellMarginEvent implements PdfPCellEvent {
Set<Float> xCoordinates = new HashSet<Float>();
Set<Float> cellHeights = new HashSet<Float>();
Float left = Float.MAX_VALUE;
Float right = Float.MIN_VALUE;
public void cellLayout(PdfPCell pdfPCell, Rectangle rectangle, PdfContentByte[] pdfContentBytes) {
this.xCoordinates.add(rectangle.getLeft());
this.xCoordinates.add(rectangle.getRight());
this.cellHeights.add(rectangle.getHeight());
left = Math.min(left,rectangle.getLeft());
right = Math.max(right, rectangle.getRight());
}
public Set<Float> getxCoordinates() {
return xCoordinates;
}
}
We'll then add all of our cells to the table, but not add the table to the document just yet
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(OUTPUT_FILE));
document.open();
PdfPTable table = new PdfPTable(4);
CellMarginEvent cellMarginEvent = new CellMarginEvent();
for (int aw = 0; aw < 320; aw++) {
PdfPCell cell = new PdfPCell();
cell.addElement(new Paragraph("Cell: " + aw));
cell.setCellEvent(cellMarginEvent);
table.addCell(cell);
}
No we add get top- the top position of our table, and add the table to the document.
float top = writer.getVerticalPosition(false);
document.add(table);
Then we draw the vertical and horizontal lines of the completed table. For the height of each cell I just used the first element in cellHeights.
Set<Float> xCoordinates = cellMarginEvent.getxCoordinates();
//Draw the column lines
PdfContentByte canvas = writer.getDirectContent();
for (Float x : xCoordinates) {
canvas.moveTo(x, top);
canvas.lineTo(x, 0 + document.bottomMargin());
canvas.closePathStroke();
}
Set<Float> cellHeights = cellMarginEvent.cellHeights;
Float cellHeight = (Float)cellHeights.toArray()[0];
float currentPosition = writer.getVerticalPosition(false);
//Draw the row lines
while (currentPosition >= document.bottomMargin()) {
canvas.moveTo(cellMarginEvent.left,currentPosition);
canvas.lineTo(cellMarginEvent.right,currentPosition);
canvas.closePathStroke();
currentPosition -= cellHeight;
}
And finally close the document:
document.close()
Example output:
Note that the only reason I say this is an incomplete examples is because there may be some adjustments you need to make to top in the case of header cells, or there may be custom cell styling (background color, line color, etc) you need to account for yourself.
I'll also note another downfall that I just thought of- in the case of tagged PDFs this solution fails to add tagged table cells, and thus would break compliance if you have that requirement.

JavaFX - Stop Table Column from Resizing with Parent

I have table with 3 columns. The table is using a CONSTRAINED_RESIZE_POLICY.
All three columns can be resized by the user.
When the table's width increases or decreases, I would like for the middle column to stay the same width as it was (in pixels) and for the excess space be distributed (or taken) from the other columns in the same basic way that it's happening now.
Basically, I would the SplitPane.setResizableWithParent( <child>, false ) functionality for a table column.
Any idea how to accomplish this?
How about to reset min and max width only when the column is dragged. This is a example as a inner class.
class CustomResizePolicy implements Callback<TableView.ResizeFeatures, Boolean> {
static final double DEFAULT_MIN_WIDTH = 10.0F, DEFAULT_MAX_WIDTH = 5000.0F;
#Override
public Boolean call(TableView.ResizeFeatures feature) {
final TableColumn<?,?> c = feature.getColumn();
if (c == column2) {
c.setMinWidth(DEFAULT_MIN_WIDTH);
c.setMaxWidth(DEFAULT_MAX_WIDTH);
}
boolean result = TableView.CONSTRAINED_RESIZE_POLICY.call(feature);
if (c == column2) {
c.setMinWidth(c.getWidth());
c.setMaxWidth(c.getWidth());
}
return result;
}
}
and
tableView.setColumnResizePolicy(new CustomResizePolicy());
column2.setMaxWidth(200); // Need to fix column2's width in this case
column2.setMinWidth(200);
column1.setMaxWidth(5000); // Divide left margin with a ratio of 1:2
column3.setMaxWidth(10000);

Java JTable header word wrap

I am trying to get the header on a table to have word wrap. I have managed to do this but the first data row is expanding. The code for the table is:
public class GenerateTable extends JTable {
private JCheckBox boxSelect = new JCheckBox();
private JTableHeader hdGen;
public class LineWrapCellRenderer extends JTextArea implements TableCellRenderer {
private static final long serialVersionUID = 1L;
int rowHeight = 0; // current max row height for this scan
#Override
public Component getTableCellRendererComponent(
JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column)
{
/*
* row < 0 means header
*/
if(row >= 0) {
setWrapStyleWord(false);
return this;
}
setText((String) value);
setWrapStyleWord(true);
setLineWrap(true);
// current table column width in pixels
int colWidth = table.getColumnModel().getColumn(column).getWidth();
// set the text area width (height doesn't matter here)
setSize(new Dimension(colWidth, 1));
// get the text area preferred height and add the row margin
int height = getPreferredSize().height + table.getRowMargin();
// ensure the row height fits the cell with most lines, row = -1 for header
if (column == 2 || height > rowHeight) {
table.setRowHeight(row, height);
rowHeight = height;
}
return this;
}
}
LineWrapCellRenderer lwHeader = new LineWrapCellRenderer();
public GenerateTable(GenerateTableModel model) {
super(model);
this.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
/*
* Select
*/
TableColumn colSelect = this.getColumnModel().getColumn(0);
colSelect.setCellEditor(new DefaultCellEditor(boxSelect));
colSelect.setPreferredWidth(60);
/*
* category
*/
this.getColumnModel().getColumn(1).setResizable(false);
this.getColumnModel().getColumn(1).setPreferredWidth(200);
/*
* Amount values
*/
for (int i=2;i<model.getColumnCount();i++) {
colSelect = this.getColumnModel().getColumn(i);
colSelect.setPreferredWidth(100);
colSelect.setResizable(false);
colSelect.setHeaderRenderer(lwHeader);
}
}
}
The output is:
I have followed the code through in debug and LineWrapCellRenderer is not being called for the data lines. If I take the code out I get a normal table but no wrap on the header. Is this a recognised problem or am I missing something?
Any help appreciated
You can achieve multi-line headers much easier.
As with many Swing components you can use HTML code. In HTML specify <br> elements to indicate where line breaks / new lines should occur.
For example if you use the following header values (column names):
String[] columnNames = {
"<html>First<br>column</html>",
"<html>Second<br>column</html>",
"<html>Third<br>column</html>"
};
Then the headers will be properly rendered in 2 lines. You don't even need to create/use a custom header renderer, the default header renderer properly handles HTML code.
Note: The header height will be determined by the height of the first column. So you have to use a 2-line HTML value for the first column too. If you only have 1 word for the first column, you may additionally add an empty second line like this: "<html>Select<br> </html>"

Displaying empty rows in Android listview

So I'm wondering how to go about filling a ListView with empty rows. The ListView is populated via SQLite db so say for instance there is only 3 items in the list I want to fill the rest of the screen with empty rows. Here is a screenshot of what I mean. Yes I know it's from iPhone but it demonstrates what I mean:
The cheap way is to add extra "rows" in your layout xml. Any extra rows will be cut off by the screen. This can get messy: a higher-res screen might require you add many extra TextViews. Since they get cut off, I suppose you could add as many as you'd like. It would look something like this:
<LinearLayout>
<ListView></ListView>
<TextView/>
<TextView/>
<TextView/>
...
</LinearLayout>
Another option is to add extra rows to your ListView, as mentioned previously. If you are bound to an array, add extra blank rows to the array and handle it appropriately. Coincidentally, if you are using a Cursor you can use a MaxtrixCursor & MergeCursor as described in this answer
I ended up using a combination of these methods. I try my best to calculate the number of rows I want to add to my ListView, but I error on the side of caution and have a couple TextViews underneath my ListView that make it all come together.
When you create the Array the is going to be bound to the ListView you just need to add a few rows at the end of the Array with empty strings.
Using a textview below the listview seems to give the illusion of what I was going for.
#kabir's solution works. Now if you are like me (wanted to have two alternate colors in background, this is his dispached method rewritten (or let's say edited)
#Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
int caseLastChildBottom = -1;
int caselastChildHeight = -1;
int caseNrOfLines = -1;
//makes the colors follow the order (alternateColor1 - alternateColor2 - alternateColor1 - etc.)
int plusIndex = 1;
if (this.getChildCount() % 2 == 0)
plusIndex = 0;
// ListView's height
final int currentHeight = getMeasuredHeight();
// this will let you know the status for the ListView, fitting/not fitting content
final int scrolledHeight = computeVerticalScrollRange();
//empty listview (no item)
if (scrolledHeight == 0) {
//no childs exist so we take the top
caseLastChildBottom = 0;
//last child doesn't exist, so we set a default height (took the value in dp in the item row's height)
caselastChildHeight = convertDpToPx(DEFAULT_CHILD_ROW_S_HEIGHT);
// determine the number of lines required to fill the ListView
caseNrOfLines = currentHeight / caselastChildHeight;
}
//there is a remaining gap to fill
else {
final View lastChild = getChildAt(getChildCount() - 1);
if (lastChild == null) return;
// values used to know where to start drawing lines
caseLastChildBottom = lastChild.getBottom();
// last child's height(use this to determine an appropriate value for the row height)
caselastChildHeight = lastChild.getMeasuredHeight();
// determine the number of lines required to fill the ListView
caseNrOfLines = (currentHeight - caseLastChildBottom) / caselastChildHeight;
}
// values used to know where to start drawing lines
final int lastChildBottom = caseLastChildBottom;
// last child's height(use this to determine an appropriate value for the row height)
final int lastChildHeight = caselastChildHeight;
// determine the number of lines required to fill the ListView
final int nrOfLines = caseNrOfLines;
int i = 0;
for (i = 0; i < nrOfLines; i++) {
Rect r = new Rect(0, lastChildBottom + i * lastChildHeight, getMeasuredWidth(), lastChildBottom + (i + 1) * lastChildHeight);
canvas.drawRect(r, (i + plusIndex) % 2 == 0 ? alternateColorView1 : alternateColorView2);
}
//is there a gap at the bottom of the list
if(currentHeight - (nrOfLines *lastChildHeight) > 0){
Rect r = new Rect(0, lastChildBottom + i * lastChildHeight,getMeasuredWidth(), currentHeight);
canvas.drawRect(r, (i + plusIndex) % 2 == 0 ? alternateColorView1 : alternateColorView2);
}
return;
}
I forgot these two Paint colors (just as #kabir declared the colors):
alternateColorView1.setColor(....);
alternateColorView1.setStyle(Paint.Style.FILL);
alternateColorView2.setColor(....);
alternateColorView2.setStyle(Paint.Style.FILL);

Categories