Tutorial 32: How to use Table Layout

This tutorial describes how the table layout can be used to design screens in Formspider. Formspider mainframes, dialogs and panels can be designed using table layout. Formspider tableLayout elements consist of rows and cells. Each row may contain a different number of cells.

Open Formspider IDE and click “New Application” under the “File” menu. The “New Application” dialog will show up. Enter “tableLayout” as the name of the application and “HR” as its datasource schema name. Leave other fields empty and click “OK”. This creates the “tableLayout” application with a default mainframe (called “mainFrame”) and a default panel (called “mainPanel”).

Double click the “mainPanel” under the “Panels” node of the “Containers” navigation tree to open it in the editor. The example below places six buttons to the “mainPanel” using table layout:

<panel backgroundColor="Yellow" borderType="TitledBorder" borderTitle="my layout type is tableLayout!">
  <tableLayout>
    <row>
      <cell>
        <button name="btn1-1" label="1.1"/>
      </cell>
      <cell>
        <button name="btn1-2" label="1.2"/>
      </cell>
    </row>
    <row>
      <cell>
        <button name="btn2-1" label="2.1"/>
      </cell>
      <cell>
        <button name="btn2-2" label="2.2"/>
      </cell>
    </row>
    <row>
      <cell>
        <button name="btn3-1" label="3.1"/>
      </cell>
      <cell>
        <button name="btn3-2" label="3.2"/>
      </cell>
    </row>
  </tableLayout>
</panel>

The screenshot below shows how the buttons are displayed once the application containing the “mainFrame”, is executed. Note that the labels on buttons indicate the row and column that the button is placed in.For example, the button with the label 3.2 is located in the second column of the third row in the panel.

Figure 1: Example TableLayout with default alignment

Component Alignment

A component in a cell is by default aligned to the center of the cell (Figure 1). This behavior can be changed using the hAlign and vAlign attributes for horizontal and vertical alignment respectively.

The valid values for these two attributes are listed below;
hAlign: Left Center Right Full
vAlign: Top Center Bottom Full

The XML below expands the button “btn1-1” so that it fills its cell completely.

<panel backgroundColor="Yellow" borderType="TitledBorder" borderTitle="my layout type is tableLayout!">
  <tableLayout>
    <row>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn1-1" label="1.1"/>
      </cell>
      <cell>
        <button name="btn1-2" label="1.2"/>
      </cell>
    </row>
    <row>
      <cell>
        <button name="btn2-1" label="2.1"/>
      </cell>
      <cell>
        <button name="btn2-2" label="2.2"/>
      </cell>
    </row>
    <row>
      <cell>
        <button name="btn3-1" label="3.1"/>
      </cell>
      <cell>
        <button name="btn3-2" label="3.2"/>
      </cell>
    </row>
  </tableLayout>
</panel>

Figure 2: Example TableLayout with full alignment

The XML below aligns the button “btn1-1” to the top-left of its cell.

<panel backgroundColor="Yellow" borderType="TitledBorder" borderTitle="my layout type is tableLayout!">
  <tableLayout>
    <row>
      <cell hAlign="Left" vAlign="Top">
        <button name="btn1-1" label="1.1"/>
      </cell>
      <cell>
        <button name="btn1-2" label="1.2"/>
      </cell>
    </row>
    <row>
      <cell>
        <button name="btn2-1" label="2.1"/>
      </cell>
      <cell>
        <button name="btn2-2" label="2.2"/>
      </cell>
    </row>
    <row>
      <cell>
        <button name="btn3-1" label="3.1"/>
      </cell>
      <cell>
        <button name="btn3-2" label="3.2"/>
      </cell>
    </row>
  </tableLayout>
</panel>

Figure 3: Example TableLayout with Top-Left alignment

Cell / Row / Component Sizes

If the sample application shown above is resized, the columns and rows in the table layout resize themselves automatically to share the available space. Developers can control the area that a row or a cell occupies using the height and width attributes respectively.

Cell Width

Cell width can be set as pixel or percentage. In the example below, the cell width for the button named “btn1-2” is set to 100 pixels. All alignment values are specified as “Full” to show the effect of the cell width change clearly (Figure 4).

<panel backgroundColor="Yellow" borderType="TitledBorder" borderTitle="my layout type is tableLayout!">
  <tableLayout>
    <row>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn1-1" label="1.1"/>
      </cell>
      <cell width="100" hAlign="Full" vAlign="Full">
        <button name="btn1-2" label="1.2"/>
      </cell>
    </row>
    <row>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn2-1" label="2.1"/>
      </cell>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn2-2" label="2.2"/>
      </cell>
    </row>
    <row>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn3-1" label="3.1"/>
      </cell>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn3-2" label="3.2"/>
      </cell>
    </row>
  </tableLayout>
</panel>

Figure 4: Cell width specified in pixels

Setting the width attribute value to 100 pixels effects cells 2.2 and 3.2 as well. This happens because, when the application runs the table layout manager places the logical cells 1.2, 2.2 and 3.2 to the same physical column.

The layout manager determines the width of physical columns by processing logical cells starting from the first cell in the first row moving to the next cell in the first row and ending with the last cell in the last row. Hence the physical column width is determined by the cell in the physical column that has the biggest width value.

The XML below specifies cell width values for cells 1.2 and 2.2. (See Figure 5 for the rendered screen)

<panel backgroundColor="Yellow" borderType="TitledBorder" borderTitle="my layout type is tableLayout!">
  <tableLayout>
    <row>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn1-1" label="1.1"/>
      </cell>
      <cell width="300" hAlign="Full" vAlign="Full">
        <button name="btn1-2" label="1.2"/>
      </cell>
    </row>
    <row>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn2-1" label="2.1"/>
      </cell>
      <cell width="100" hAlign="Full" vAlign="Full">
        <button name="btn2-2" label="2.2"/>
      </cell>
    </row>
    <row>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn3-1" label="3.1"/>
      </cell>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn3-2" label="3.2"/>
      </cell>
    </row>
  </tableLayout>
</panel>

Figure 5: Cell width specified in pixels

The cell width can also be specified using a percentage as shown in the XML below(See Figure 6 for the rendered screen). The first and second cell widths are set to 25% and 75% respectively. The table layout manager will preserve this ratio between the areas the two columns cover when the mainframe is resized.

<panel backgroundColor="Yellow" borderType="TitledBorder" borderTitle="my layout type is tableLayout!">
  <tableLayout>
    <row>
      <cell width="25%" hAlign="Full" vAlign="Full">
        <button name="btn1-1" label="1.1"/>
      </cell>
      <cell width="75%" hAlign="Full" vAlign="Full">
        <button name="btn1-2" label="1.2"/>
      </cell>
    </row>
    <row>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn2-1" label="2.1"/>
      </cell>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn2-2" label="2.2"/>
      </cell>
    </row>
    <row>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn3-1" label="3.1"/>
      </cell>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn3-2" label="3.2"/>
      </cell>
    </row>
  </tableLayout>
</panel>

Figure 6: Cell width specified as percentage

The XML below uses both pixel and percentage to specify the cell width.(See Figure 7 for the rendered screen)

<panel backgroundColor="Yellow" borderType="TitledBorder" borderTitle="my layout type is tableLayout!">
  <tableLayout>
    <row>
      <cell width="100" hAlign="Full" vAlign="Full">
        <button name="btn1-1" label="1.1"/>
      </cell>
      <cell width="50%" hAlign="Full" vAlign="Full">
        <button name="btn1-2" label="1.2"/>
      </cell>
    </row>
    <row>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn2-1" label="2.1"/>
      </cell>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn2-2" label="2.2"/>
      </cell>
    </row>
    <row>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn3-1" label="3.1"/>
      </cell>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn3-2" label="3.2"/>
      </cell>
    </row>
  </tableLayout>
</panel>

Figure 7: Cell width specified both as percentage and in pixels

As seen in the example above, the table layout manager sets first physical column width to 100 pixels. Then, 50% of the remaining space in the panel is designated for the second physical column.

In some cases, the width of the component should dynamically increase following its content where the width of the physical column containing this component should also dynamically increase. The best example of this state could be a textLabel where the label content changes dynamically at runtime. In such cases where setting a fixed percentage or pixel width is insufficient, cell width can be set as “auto” to let the layout manager decide and adjust cell width dynamically. In fact this is a special value which can be used only for cells containing textLabel component.

In the XML below “auto” is specified as cell width of “label1-1”.(See Figure 8 for the rendered screen)

<panel backgroundColor="Yellow" borderType="TitledBorder" borderTitle="my layout type is tableLayout!">
  <tableLayout>
    <row>
      <cell width="auto" hAlign="Full" vAlign="Full">
        <textLabel name="label1-1" label="width of the cell is automatically adjusted following textLabel's content"/>
      </cell>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn1-2" label="1.2"/>
      </cell>
    </row>
    <row>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn2-1" label="2.1"/>
      </cell>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn2-2" label="2.2"/>
      </cell>
    </row>
    <row>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn3-1" label="3.1"/>
      </cell>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn3-2" label="3.2"/>
      </cell>
    </row>
  </tableLayout>
</panel>

Figure 8: Cell width specified as “auto”

As seen in the example above, the table layout manager sets first physical column width dynamically following the content length of the “label1-1” textLabel.

Row Height

height attribute operates similar to the width attribute. Unlike cell width, row height can only be specified in pixels. If no height attribute is specified, rows will cover all the available area.

The XML example below specifies the first row height as 100 pixels(See Figure 9 for the rendered screen). When mainframe is resized the first row will preserve its height of 100 pixels, while the height of the other two rows changes.

<panel backgroundColor="Yellow" borderType="TitledBorder" borderTitle="my layout type is tableLayout!">
  <tableLayout>
    <row height="100">
      <cell hAlign="Full" vAlign="Full">
        <button name="btn1-1" label="1.1"/>
      </cell>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn1-2" label="1.2"/>
      </cell>
    </row>
    <row>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn2-1" label="2.1"/>
      </cell>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn2-2" label="2.2"/>
      </cell>
    </row>
    <row>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn3-1" label="3.1"/>
      </cell>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn3-2" label="3.2"/>
      </cell>
    </row>
  </tableLayout>
</panel>

Figure 9: Row height

The XML example below shows a panel with a table layout manager that has pixel value for all of its cell widths and row heights(See Figure 10 for rendered screen). The layout manager of this panel will not adjust the contents of the panel when the panel is resized.

<panel backgroundColor="Yellow" borderType="TitledBorder" borderTitle="my layout type is tableLayout!">
  <tableLayout>
    <row height="100">
      <cell hAlign="Full" vAlign="Full" width="100">
        <button name="btn1-1" label="1.1"/>
      </cell>
      <cell hAlign="Full" vAlign="Full" width="100">
        <button name="btn1-2" label="1.2"/>
      </cell>
    </row>
    <row height="100">
      <cell hAlign="Full" vAlign="Full">
        <button name="btn2-1" label="2.1"/>
      </cell>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn2-2" label="2.2"/>
      </cell>
    </row>
    <row height="100">
      <cell hAlign="Full" vAlign="Full">
        <button name="btn3-1" label="3.1"/>
      </cell>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn3-2" label="3.2"/>
      </cell>
    </row>
  </tableLayout>
</panel>

Figure 10: Row height and cell width

Row Height Policy

Similarly to cell width, there can be some cases where the height of the component contained by a row is unknown and should extend its content. Again the best example to this case is a textLabel where the label content changes dynamically at runtime. In such cases, to let the layout manager decide and adjust row height dynamically, heightPolicy attribute can be set as “Dynamic”(the default value of this attribute is “Static”, indicating that the layout manager won’t extend row height dynamically).

Note 1: “Dynamic” heightPolicy usage should be limited as much as possible since too much usage of “Dynamic” heightPolicy may slow down the application performance.
Note 2: If any row height value is set, heightPolicy cannot be set as “Dynamic” for this same row anymore.

In the XML below “Dynamic” is specified as heightPolicy of the first row in the panel.(See Figure 11 for the rendered screen)

<panel backgroundColor="Yellow" borderType="TitledBorder" borderTitle="my layout type is tableLayout!">
  <tableLayout>
    <row heightPolicy="Dynamic">
      <cell hAlign="Full" vAlign="Full">
        <textLabel name="label1-1" label="height of the row is automatically adjusted following textLabel's content"/>
      </cell>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn1-2" label="1.2"/>
      </cell>
    </row>
    <row>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn2-1" label="2.1"/>
      </cell>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn2-2" label="2.2"/>
      </cell>
    </row>
    <row>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn3-1" label="3.1"/>
      </cell>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn3-2" label="3.2"/>
      </cell>
    </row>
  </tableLayout>
</panel>

Figure 11: “Dynamic” heightPolicy

Cell Spacing

cellSpacing attribute is used to create a blank area between table layout cells.

The XML below sets cellSpacing to 5(See Figure 12 for the rendered screen).

<panel backgroundColor="Yellow" borderType="TitledBorder" borderTitle="my layout type is tableLayout!">
  <tableLayout cellSpacing="5">
    <row>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn1-1" label="1.1"/>
      </cell>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn1-2" label="1.2"/>
      </cell>
    </row>
    <row>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn2-1" label="2.1"/>
      </cell>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn2-2" label="2.2"/>
      </cell>
    </row>
    <row>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn3-1" label="3.1"/>
      </cell>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn3-2" label="3.2"/>
      </cell>
    </row>
  </tableLayout>
</panel>

Figure 12: Cell Spacing

Component Size

When alignment is set to a value other than “Full”, cell‘s childWidth and childHeight attributes can be used to determine the size of the component in it as shown in the sample XML below(See Figure 13 for the rendered screen).

<panel backgroundColor="Yellow" borderType="TitledBorder" borderTitle="my layout type is tableLayout!">
  <tableLayout>
    <row>
      <cell hAlign="Left" vAlign="Top" childWidth="100" childHeight="100">
        <button name="btn1-1" label="1.1"/>
      </cell>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn1-2" label="1.2"/>
      </cell>
    </row>
    <row>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn2-1" label="2.1"/>
      </cell>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn2-2" label="2.2"/>
      </cell>
    </row>
    <row>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn3-1" label="3.1"/>
      </cell>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn3-2" label="3.2"/>
      </cell>
    </row>
  </tableLayout>
</panel>

Figure 13: Component size

Span Values

Column Span

In the XML below the cell 1.2 is deleted and cell 1.1 is extended to cover two physical columns using the columnSpan attribute(See Figure 14 for the rendered screen).

<panel backgroundColor="Yellow" borderType="TitledBorder" borderTitle="my layout type is tableLayout!">
  <tableLayout>
    <row>
      <cell hAlign="Full" vAlign="Full" columnSpan="2">
        <button name="btn1-1" label="1.1"/>
      </cell>
    </row>
    <row>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn2-1" label="2.1"/>
      </cell>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn2-2" label="2.2"/>
      </cell>
    </row>
    <row>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn3-1" label="3.1"/>
      </cell>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn3-2" label="3.2"/>
      </cell>
    </row>
  </tableLayout>
</panel>

Figure 14: Column spans values

The XML below uses columnSpan for a more complex display(See figure 15 for the rendered screen).

<panel backgroundColor="Yellow" borderType="TitledBorder" borderTitle="my layout type is tableLayout!">
  <tableLayout>
    <row height="300">
      <cell hAlign="Full" vAlign="Full">
        <button name="btn1-1" label="1.1"/>
      </cell>
      <cell hAlign="Full" vAlign="Full" width="100">
        <button name="btn1-2" label="1.2"/>
      </cell>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn1-3" label="1.3"/>
      </cell>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn1-4" label="1.4"/>
      </cell>
    </row>
    <row height="50">
      <cell hAlign="Full" vAlign="Full" columnSpan="3" width="400">
        <button name="btn2-1" label="2.1"/>
      </cell>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn2-2" label="2.2"/>
      </cell>
    </row>
  </tableLayout>
</panel>

Figure 15: Column Spans values

The XML above defines two rows. The first row has four cells and a height of 300 pixels. The second row has two cells and a height of 50 pixels. Cell 1.2 width is specified as 100 and cell 2.1 has its columnSpan and width attributes set to 3 and 400 respectively.

Note that resizing the mainframe will only cause the cell 1.4 and cell 2.2 to resize.

Row Span

In the XML below, the cell 3.2 is deleted and the cell 2.1 is extended vertically using the rowSpan attribute(See Figure 16 for the rendered screen).

<panel backgroundColor="Yellow" borderType="TitledBorder" borderTitle="my layout type is tableLayout!">
  <tableLayout>
    <row>
      <cell hAlign="Full" vAlign="Full" columnSpan="2">
        <button name="btn1-1" label="1.1"/>
      </cell>
    </row>
    <row>
      <cell hAlign="Full" vAlign="Full" rowSpan="2">
        <button name="btn2-1" label="2.1"/>
      </cell>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn2-2" label="2.2"/>
      </cell>
    </row>
    <row>
      <cell hAlign="Full" vAlign="Full">
        <button name="btn3-1" label="3.1"/>
      </cell>
    </row>
  </tableLayout>
</panel>

Figure 16: Row spans values

Note that, even though the cell 3.1 is defined as the first column in its row, when the panel is rendered, it is displayed in the second physical column due to the rowSpan attribute in cell 2.1