Adding a dynamic TableLayout with borders in a Android App

yams picture yams · Mar 15, 2013 · Viewed 8.2k times · Source

I am creating a Android app. This Android App will have objects that are dynamic. These objects are Places with a Address or Lat/Long, and distance from current location, and a ETA. What I would like to do is add with objects on a TableLayout with borders, but I need to be able to dynamically add rows as the number of places increase.

I understand somewhat how to do this for a fixed hardcoded number of items on the xml, but what would be the best way when the number of objects is coming from the Activity.java file?

Below is a screenshot of the TableLayout I would like:

Table Layout

So the object would be a place with a address, distance and direction.

Answer

user picture user · Mar 18, 2013

but I need to be able to dynamically add rows as the number of places increase.

This isn't difficult, when you have a new object append a TableRow with the data to the TableLayout.

I understand somewhat how to do this for a fixed hardcoded number of items on the xml, but what would be the best way when the number of objects is coming from the Activity.java file?

I don't think there is a best way (or what you consider best way). You either:

  • Insert fake views to act as dividers. This would be easier to implement visually but it will also increase the memory consumption of your app, with bad consequences if the number of rows is big. (1)
  • Or use drawables for the backgrounds to simulate the borders (like nine-patch images). This would be simpler then inserting additional views but you need a bit more talent to make it look well. (2)

Some examples for your image:

(1)

private static final int DIVIDER_SIZE = 2;

// rowsCount the number of rows to add to the TableLayout
private void buildOldSchool(TableLayout table, int rowsCount) {
    View divider;
    for (int i = 0; i < rowsCount; i++) {
        TableRow row = new TableRow(this);
        for (int j = 0; j < 7; j++) {
            if (j % 2 == 0) {
                divider = new View(this);
                divider.setLayoutParams(new TableLayout.LayoutParams(
                        DIVIDER_SIZE, TableLayout.LayoutParams.MATCH_PARENT));
                divider.setBackgroundColor(Color.GREEN);
                row.addView(divider, new TableRow.LayoutParams(
                        DIVIDER_SIZE, TableRow.LayoutParams.MATCH_PARENT));
                continue;
            }
            TextView tv = new TextView(this);
            tv.setText("DX"); // dummy data
            row.addView(tv, new TableRow.LayoutParams(
                    TableRow.LayoutParams.MATCH_PARENT,
                    TableRow.LayoutParams.WRAP_CONTENT));
        }
        divider = new View(this);
        divider.setLayoutParams(new TableLayout.LayoutParams(
                TableLayout.LayoutParams.MATCH_PARENT, DIVIDER_SIZE));
        divider.setBackgroundColor(Color.GREEN);
        if (i == 0) {
            table.addView(divider);
            divider = new View(this);
            divider.setLayoutParams(new TableLayout.LayoutParams(
                    TableLayout.LayoutParams.MATCH_PARENT, DIVIDER_SIZE));
            divider.setBackgroundColor(Color.GREEN);
        }
        table.addView(row);
        table.addView(divider);
    }
}

(2) or with images:

private void buildWithDrawables(TableLayout table, int rowsCount) {
    for (int i = 0; i < rowsCount; i++) {
        TableRow row = new TableRow(this);
        row.setBackgroundResource(i == 0 ? R.drawable.firstrow
                : R.drawable.normalrow);
        for (int j = 0; j < 3; j++) {
            TextView tv = new TextView(this);
            tv.setBackgroundResource(j == 2 ? R.drawable.extra
                    : R.drawable.cell);
            tv.setText("DX");
            row.addView(tv, new TableRow.LayoutParams(
                    TableRow.LayoutParams.MATCH_PARENT,
                    TableRow.LayoutParams.WRAP_CONTENT));
        }
        table.addView(row);
    }
}

Where the images are:

  • R.drawable.cell:

  • R.drawable.extra (a visually transparent drawable which replicates the nine-patch above):

  • R.drawable.normalrow:

  • R.drawable.firstrow:

Ignore my design skills.

If your foresee a large number of rows I would advise you to use a ListView, which you could pretty easy make it to look like a table with borders.