Layout Types Part 2: TableLayout

In the previous article we looked at LinearLayout but ran in to a problem when we tried to get the columns of nested LinearLayouts to align. In this article we’ll explore TableLayout and look at how it can solve that particular problem.

For those familiar with HTML, TableLayout is analogous with the HTML

. While tables have something of a bad reputation in HTML terms, this is largely because they were used as an overarching tool for managing layout in HTML. For web designers, many of whom came from a design rather than development background, the concept of a
and which represented a logical object rather than a physical one were somewhat abstract, whereas the concept of a table was much easier to understand and quickly became the building block for layouts. In recent years, the trend has been to completely avoid tables at all costs, and to always use
and instead. I personally feel that tables do have a valid function within HTML, but the key is knowing when and where they are appropriate.

In Android, it is a little more obvious when a table is required as we saw in the first article. Where we want our columns to align, then we need to use a table rather than nesting LinearLayouts. If you haven’t read the previous article, I would suggest that you do so now because the concept of nesting layouts is intrinsic to TableLayout and how it works.

In essence, a TableLayout is a nested layout where Android takes care of managing the column widths for us. Each row in the table is represented by a TableRow element. This TableRow can be thought of as having the same functionality as a horizontal LinearLayout (it actually extends LinearLayout), and we can simply add children as we would with a LinearLayout:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<TableLayout android:layout_height="wrap_content"
    android:layout_width="match_parent">
    <TableRow android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        <TextView android:text="1,1"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content" />
        <TextView android:text="1,2"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content" />
        <TextView android:text="1,3"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content" />
        <TextView android:text="1,4"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content" />
    </TableRow>
    <TableRow android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        <TextView android:text="2,1"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content" />
        <TextView android:text="2,2"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content" />
        <TextView android:text="2,3"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content" />
        <TextView android:text="2,4"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content" />
    </TableRow>
    <TableRow android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        <TextView android:text="3,1"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content" />
        <TextView android:text="3,2"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content" />
        <TextView android:text="3,3 longer"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content" />
        <TextView android:text="3,4"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content" />
    </TableRow>
    <TableRow android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        <TextView android:text="4,1"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content" />
        <TextView android:text="4,2"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content" />
        <TextView android:text="4,3"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content" />
        <TextView android:text="4,4"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content" />
    </TableRow>
</TableLayout>

This produces the following:

Basic Table

Basic Table

Looking at the 3rd column, we can see that our columns are being automatically sized to fit the widest text in each column. But what about if we want the table to fit the width of the display let’s try using a layout_weight to try and force one column to fill the parent:

This doesn’t do quiet what we expected:

Table with layout_weight

Table with layout_weight

While it has done what we want on the first row, the others have ignored the layout_weight of the second TextView in the first TableRow. This is because layout_weight require two measurement passes, and the column width is calculated after the first has been completed, so doesn’t account for the layout_weight. One solution would be to include the layout_weight in each of the TextView widgets in the second column, but TableLayout gives us an easier solution: It supports an attribute named android:stretchColumns which takes a zero-based, comma-delimited array of integers. Each of these integers identifies a column that will be expanded to fit the available space. You can specify multiple columns, and the available space will be divided equally between them.

Let’s modify our table to expand the second column. Remember that, because the column numbering is zero-based, we must use “1″ to identify the second column.

This gives us:

Expanded TableLayout

Expanded TableLayout

As well as android:stretchColumns, TableLayout also has a couple of other useful attributes:

  • android:shrinkColumns is the opposite of android:stretchColumns as it defines which columns can be made smaller than their content in order to fit the table within its parent
  • android:collapseColumns specifies columns which can be completely hidden, and their space distributed among the other columns. To be useful, it is necessary to toggle this state programatically at runtime but you can declare some columns as collapsed by default in XML using this attribute.

The final thing that we’ll look at is the ability to make a cell span multiple columns (the equivalent of the HTML colspan). This is achieved by adding android:layout_span to the TextView (or whatever the child view is):

We apply a column span to the cell at 2,3 and remove the cell at 2,4 which gives us:

TableView with column span

TableView with column span

In the next article we’ll have a look at RelativeLayout.

The source code for this article can be found here.

© 2011, Mark Allison. All rights reserved. This article originally appeared on Styling Android.

Portions of this page are modifications based on work created and shared by Google and used according to terms described in the Creative Commons 3.0 Attribution License

Creative Commons License
Layout Types Part 2: TableLayout by Styling Android, unless otherwise expressly stated, is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. Terms and conditions beyond the scope of this license may be available at blog.stylingandroid.com.

Tags: ,

2 Responses to “Layout Types Part 2: TableLayout”

  1. taher says:

    i want to create space between two raw. how can i achieve this?

  2. Shanti says:

    Very Useful! thanks…

Leave a Reply