Android App Development – Layouts Part Two: Table and Absolute Layouts

By
On November 24, 2010

Table Layout:

Organizing widgets in a table is a famous approach in HTML design where you construct a table of a number of rows and cells and distribute the controls over the cells to achieve a consistent look for your UI. Android provides a similar technique.

In android you define the number of rows by your own and android determines the number of cells in each row according to the number of widgets in each row.

<TABLELAYOUT xmlns:android="https://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent">
    <TABLEROW>
 <TEXTVIEW android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Enter your name">
    <EDITTEXT android:layout_width="150px" android:layout_height="wrap_content">
    <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Submit"
    />
    </TABLEROW>
</TABLELAYOUT>

You can define a table and add rows and views to it programmatically like this:

TableLayout tl=new TableLayout(this);
TableRow tr=new TableRow(this);
Button btn=new Button(this);
btn.setText("Hello");
tr.addView(btn);
tl.addView(tr);
setContentView(tl);

Spanning Multiple Columns:

A table cell can span multiple columns like this:

<TABLELAYOUT xmlns:android="https://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent">
    <TABLEROW>
 <TEXTVIEW android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Enter your name">
    <EDITTEXT android:layout_width="150px" android:layout_height="wrap_content">
    <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Submit"
    />
    </TABLEROW>

 <TABLEROW>
 <TEXTVIEW android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Spanning Two columns" android:layout_span="2">
    <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Cancel"
    />
 </TABLEROW>
</TABLELAYOUT>

Or programmatically like this:

TableRow.LayoutParams trParams = new TableRow.LayoutParams();
trParams.span = 5;

TableRow titleRow = new TableRow(this);

TextView title = new TextView(this);
title.setLayoutParams(trlp);
titleRow.addView(title);

Also you can choose which column to put your widget by using android:layout_column property, you define the Zero-based index of the column where you want your widget to be:

<TABLELAYOUT xmlns:android="https://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent">
    <TABLEROW>
 <TEXTVIEW android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Enter your name">
    <EDITTEXT android:layout_width="150px" android:layout_height="wrap_content">
    <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Submit"
    />
    </TABLEROW>

 <TABLEROW>
 <TEXTVIEW android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Spanning Two columns" android:layout_span="2">
    <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Cancel"
    />
 </TABLEROW>

 <TABLEROW>
 <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Help"
    android:layout_column="1"
    />
 </TABLEROW>

</TABLELAYOUT>

Note:

if you specify an index greater than the actual cells count, the widget won’t appear. For example in the previous example if android:layout_column had a value greater than 2 the widget wouldn’t appear.

Using Separators:

Table layout also allows you to put widgets directly under <TableRow> the tag to act as a separator between rows:

<TABLELAYOUT xmlns:android="https://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent">
    <TABLEROW>
 <TEXTVIEW android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Enter your name">
    <EDITTEXT android:layout_width="150px" android:layout_height="wrap_content">
    <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Submit"
    />
    </TABLEROW>

 <TABLEROW>
 <TEXTVIEW android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Spanning Two columns" android:layout_span="2">
    <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Cancel"
    />
 </TABLEROW>
 <VIEW android:layout_height="5px" android:background="#f00">
 <TABLEROW>
 <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Help"
    android:layout_column="5"
    />
 </TABLEROW>
 <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Separator"
    />
</TABLELAYOUT>

Stretching Columns:

In table layout each column occupies space equal to the size of the largest widget in it. But you can set the width of any column to take the largest available space, just like setting the width to 100 % in HTML. This is done by setting the property android:stretchColumns to the index of the column, also you can set multiple columns by separating them with a comma.

Look at the layout below:

<TABLELAYOUT xmlns:android="https://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent">
    <TABLEROW>
 <TEXTVIEW android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Enter your name">
    <EDITTEXT android:layout_width="100px" android:layout_height="wrap_content">
    </TABLEROW>
</TABLELAYOUT>

Now we gonna to add android:stretchColumns=”0″ to the table layout and see what it’s gonna look like:

<TABLELAYOUT xmlns:android="https://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:stretchcolumns="0">
    <TABLEROW>
 <TEXTVIEW android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Enter your name">
    <EDITTEXT android:layout_width="100px" android:layout_height="wrap_content">
    </TABLEROW>
</TABLELAYOUT>

Column 0 occupied the largest available space.

You can set this property from code like this:

TableLayout tl=new TableLayout(this);
tl.setColumnStretchable(0, true);

the setColumnStretchable(ColumnIndex, IsStretchable) method parameters are the column index and a Boolean value to indicate it is going to be stretched.

Shrinking Columns:

Now what if we have a column that have a large content. Android columns by default do not wrap their content. Look at this layout:

<TABLELAYOUT xmlns:android="https://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent">
    <TABLEROW>
 <TEXTVIEW android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Please enter your name and some very very long info as a test for this property">
    <EDITTEXT android:layout_width="100px" android:layout_height="wrap_content">
    </TABLEROW>
</TABLELAYOUT>

See column zero occupies large space that column 1 is not visible.

We can use android:shrinkColumns property to wrap content of a certain column or for multiple columns by assigning column numbers separeted by commas.

When we use the property with column zero it will be like this:

<TABLELAYOUT xmlns:android="https://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:shrinkcolumns="0">
    <TABLEROW>
 <TEXTVIEW android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Please enter your name and some very very long info as a test for this property">
    <EDITTEXT android:layout_width="100px" android:layout_height="wrap_content">
    </TABLEROW>
</TABLELAYOUT>

Its like using style=”white-space:wrap;” style in HTML
You can set the property from code like this:

TableLayout tl=new TableLayout(this);
tl.setColumnShrinkable(0, true);

The setColumnShrinkable(columnIndex, isShrinkable) method parameters are the column index and a Boolean to indicate it si going to be shrinked.

Hiding Columns:

Finally if you want to make some columns invisible you can use the property android:collapseColumns the same way we used the last two properties.

<TABLELAYOUT xmlns:android="https://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:collapsecolumns="0">
    <TABLEROW>
 <TEXTVIEW android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Please enter your name and some very very long info as a test for this property">
    <EDITTEXT android:layout_width="100px" android:layout_height="wrap_content">
    </TABLEROW>
</TABLELAYOUT>

See that column zero is invisible.
You can use this property from code like this:

TableLayout tl=new TableLayout(this);
tl.setColumnCollapsed(0, true);

The method setColumnCollapsed(columnIndex, isCollapsed) parameters are the column index and a Boolean to indicate that it’s going to be collapsed

This is just like using the style=”display:none;” in HTML

Other functions can be called from code:

  • TableLayout.setShrinkAllColumns(Boolean shrinkAllColumns) : shrinks all colums
  • TableLayout.setStretchAllColumns(Boolean stretchAllColumns): stretches all columns

Absolute layout:

Note:

the absolute layout class is deprecated, you are encouraged to use Frame Layout or Relative layout.

The reason of that is that it won’t be compatible with all the android phones as they have different screen sizes and resolutions.

absolute layout lays widgets by specifying their exact X and Y positions. In android the origin (0,0) coordinate is located at the top left of the screen.

you can use Absolute Layout only if your application is targeted for a certain phone type so that you can be sure that it will display properly.

absolute layout is defiend in XML as <AbsoluteLayout>
by default, if you define any control in absolute layout without defining it’s x,y coordinates, it will be placed in the origin point at (x,y)=(0,0)

if you define x,y values that are too large, the widget will not appear on the screen

you can specify the values of x and y by many units as shown:

<ABSOLUTELAYOUT xmlns:android="https://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/mainlayout">
    <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="placed at 100,130 pixels (px)"
    android:layout_x="100px"
    android:layout_y="130px"
    />
    <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="placed at 0,150 points (pt)"
    android:layout_x="0pt"
    android:layout_y="150pt"
    />
    <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="placed at 0.7,0.5 inches (in)"
    android:layout_x="0.7in"
    android:layout_y="0.5in"
    />
    <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="placed at 3,3 millimeters (mm)"
    android:layout_x="3mm"
    android:layout_y="3mm"
    />
    <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="placed at 0,270 density independant pixels (dp)"
    android:layout_x="0dp"
    android:layout_y="270dp"
    />
    <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="placed at 0,180 scale independant pixels (sp)"
    android:layout_x="0sp"
    android:layout_y="180sp"
    />
</ABSOLUTELAYOUT>


To define absolute layout from the code you can use the following code:

AbsoluteLayout abslay=new AbsoluteLayout(this);
Button btn=new Button(this);
btn.setText("Hello");
abslay.addView(btn, new AbsoluteLayout.LayoutParams(AbsoluteLayout.LayoutParams.WRAP_CONTENT,AbsoluteLayout.LayoutParams.WRAP_CONTENT,10,100));
setContentView(abslay);

the absolutelayout.layoutparams function has the following constructor:
AbsoluteLayout.LayoutParams(width,height,position X,position Y).