站内搜索: 请输入搜索关键词
当前页面: 图书首页 > Programming Wireless Devices with the Java2 Platform

Programming Wireless Devices with the Java2 Platform

[ directory ] Previous Section Next Section

10.9 Form Layout

The Form class has a layout policy that is organized around rows. A Form grows vertically and scrolls vertically as necessary. The height of a Form varies depending upon the number of rows and the height of each row. The height of each row is determined by the items that are positioned on that row.

graphics/new_icon.gif

In MIDP 2.0, the Form layout algorithm considers each Item in turn, starting at Item zero and proceeding in order through each Item until the last Item in the Form has been processed. Items are laid out at the beginning of each row, proceeding across each row in the chosen layout direction, packing as many Items onto each row as will fit, unless a condition occurs that causes the packing of a row to be terminated early. A new row is then added, and Items are packed onto it as described above. Items are packed onto rows, and new rows are added below existing rows as necessary until all Items have been processed by the layout algorithm. This general principle of Form layout is illustrated in Figure 10.1.

Figure 10.1. General principle of Form layout

graphics/10fig01.gif

An application can influence the layout of the Items using the following layout directives:

  • LAYOUT_LEFT, LAYOUT_RIGHT, and LAYOUT_CENTER define the horizontal alignment of an items in a row.

  • LAYOUT_TOP, LAYOUT_BOTTOM, and LAYOUT_VCENTER define the vertical alignment of an item in a row.

  • LAYOUT_NEWLINE_BEFORE and LAYOUT_NEWLINE_AFTER force row breaks after and before an item.

  • LAYOUT_SHRINK, LAYOUT_VSHRINK, LAYOUT_EXPAND, and LAYOUT_VEXPAND affect the way an item is sized.

  • LAYOUT_2 indicates that new MIDP 2.0 layout rules are in effect for an item. LAYOUT_2 has no effect for StringItem, CustomItem, or Spacer.

These layout directives can be combined using the bitwise OR operator (|) to compose a layout directive value. The horizontal alignment directives are mutually exclusive. Similarly, multiple vertical alignment directives cannot be combined. All the other directives can be combined in any way with the other directives. Such a value is used as the parameter for the setLayout method and is the return value from the getLayout method.

The following example uses the setLayout method to set a combined layout directive value for a TextField. A LAYOUT_2 setting for TextField has the effect that other Items may also be placed in the same row. LAYOUT_SHRINK and LAYOUT_VSHRINK indicate that TextField should have the smallest possible size. LAYOUT_RIGHT and LAYOUT_TOP indicate that the TextField is aligned to the top or right side of the row.

TextField textField = new TextField(...);
textField.setLayout(Item.LAYOUT_2      |
                    Item.LAYOUT_SHRINK | Item.LAYOUT_VSHRINK |
                    Item.LAYOUT_RIGHT  | Item.LAYOUT_TOP);

The following sections describe the behavior of these layout directives more thoroughly.

10.9.1 Row Breaks

The layout algorithm generally attempts to place an Item in a Form on the same row as the previous Item, unless certain conditions occur that cause a "row break." A row break should be distinguished from a line break. When there is a row break, the next Item is placed at the beginning of a new row in the Form instead of being placed in the same line as the previous Item. In contrast, a line break occurs inside an Item and usually causes the Item to be taller in size.

Applications can add forced row breaks by using line feed characters ('\n'; U+000A) in an unlocked StringItem (these are discussed below) or by adding layout directives LAYOUT_NEWLINE_BEFORE or LAYOUT_NEWLINE_AFTER to Items. The presence of a newline directive does not cause an additional row break if there is one already present, but a line feed character always creates a row break.

By default, ChoiceGroup, DateField, Gauge, and TextField Items are presented on their own rows. An application must set the LAYOUT_2 directive in these Items to remove the automatic row breaks from them and to allow several Items on the same row. Still, the device may dictate that the item is always presented on a row by itself.

graphics/10fig01a.gif
// textField1 and dateField1 do not have
// LAYOUT_2 set. They are presented
// in their own lines.

textField2.setLayout(Item.LAYOUT_2);
dateField2.setLayout(Item.LAYOUT_2);

Line breaks occur inside the Item area. For example, text in a TextField can be wrapped to multiple lines causing the TextField to consume more vertical space from Form. This kind of automatic content wrapping is done by the device. An application can also add manual line breaks to a TextField by placing a line feed character ("\n") in the String that is given as a parameter to the TextField. Thus, it depends on the context in which the text is used whether line feed characters will cause a row break in a Form or just a line break inside an Item.

10.9.2 Label Layout

Label positioning is dictated by the device. Labels can be presented in the same line with the Item or on a line before the Item. A device implementation may, for example, have a break (row or line) before every Item that has a label. Also, a label may be restricted to one line only. If this is the case, labels that contain line breaks might be truncated at the line break and cause the rest of the label not to be shown.

The label is counted as part of an Item size whenever the label is presented within the same content area as the Item. On the other hand, if the device dictates that a label be presented in the margin of a Form, then the label is not counted as part of the size of the Item.

10.9.3 Current Alignment

The layout algorithm has a concept of current alignment. Current alignment can have the value left, center, or right. The current alignment changes when the layout algorithm encounters an Item that has one of the layout alignment directives LAYOUT_LEFT, LAYOUT_CENTER, or LAYOUT_RIGHT. If none of these directives is present in any Item, the current layout directive does not change. This rule has the effect of grouping the contents of the Form into sequences of consecutive Items sharing an alignment value. When the layout algorithm encounters an Item with a differing layout alignment directive, then there is an automatic row break before the Item. The current alignment is maintained internally in the Form and does not affect the layout value as reported by the getLayout method.

graphics/10fig01b.gif
item1.setLayout(Item.LAYOUT_LEFT);
// item2 uses current alignment
item3.setLayout(Item.LAYOUT_RIGHT);
// item4 uses current alignment
item5.setLayout(Item.LAYOUT_CENTER);
// item6 uses current alignment

Form also has an initial value for current alignment that is dictated by the device implementation. This initial value is used until an Item is laid out that explicitly defines any horizontal layout alignment directives. The initial value of current alignment can be LAYOUT_LEFT or LAYOUT_RIGHT. It is LAYOUT_LEFT if left-to-right item layout policy is used in a device and LAYOUT_RIGHT for right-to-left layout. Since the device implementation dictates the layout policy of a Form, this policy cannot change within the same Form. The device may, for example, choose the policy based on the natural language used in the user interface of a device. For example, English devices use left-to-right, and Arabic devices use right-to-left (see Figure 10.2.)

Figure 10.2. Item layout policy dictated by the device implementation

graphics/10fig02.gif

Since the initial value of current alignment is based on the Form layout policy, the current alignment at the start of the layout algorithm is based on the default alignment value of the given layout policy. For example, in Arabic user interfaces, right-to-left aligned content is most common.

10.9.4 Item Sizing

Items have two explicit size concepts: the minimum size and preferred size. Both refer to the total size (height and width) that an item requires when it is presented on the display. The size includes the Item's content and the necessary internal margins. Also, the label for the Item is included in these sizes if the device implementation renders the label so that it affects the layout. The Form layout algorithm decides which of the sizes are used when the Item is laid out.

The sizes can be dynamic since they are dependent on the contents of the Item. The minimum size is the smallest size at which the Item can function and display its contents, though perhaps not optimally. The preferred size is the size that allows an item to fully present its contents. Both of the sizes are defined by the device implementation for each built-in Item and by the application for each CustomItem and Spacer.

An application can also lock the preferred size of each Item by calling the method setPreferredSize. The minimum size cannot be locked, so the implementation can enforce certain minimum dimensions for Items.

When an Item is created, its preferred size is unlocked, and its size is calculated by the device implementation as described above.

The application can also lock one dimension of the preferred size and leave the other dimension unlocked. If the content changes, the size on the unlocked dimension is recomputed to reflect the new contents, but the size on the locked dimension remains unchanged. For example, if the application calls setPreferredSize(50, -1), the preferred width will be locked at 50 pixels and the preferred height would be computed based on the content of the Item. Similarly, if the application calls setPreferredSize(-1, 60), the preferred height will be locked at 60 pixels and the preferred width would be computed based on the contents of the Item. This feature is particularly useful for Items with textual content that can be line-wrapped; examples of such Items include StringItem and TextField.

Items also have an implicit maximum size provided by the implementation. The maximum width is typically based on the width of the screen space available to a Form. Since Forms can scroll vertically, the maximum height should typically not be limited by the height of the available screen space.

10.9.5 Row Filling

If the device implementation has not dictated otherwise, and if space permits two adjacent Form Items, they are placed on the same row. When packing multiple Items onto a single row, the width of each Item is compared with the remaining space on the row. The preferred width of the Item is used for this unless LAYOUT_SHRINK directive has been defined for the Item. If the LAYOUT_SHRINK directive is in place, the minimum size is used instead. If the size is wider than the remaining space, then a row break occurs and the Item is placed on the next row.

After a row is detected to be full of Items, there may be leftover horizontal space that is not allocated to any Items. This remaining space of the row is proportionally distributed to the Items in that row by expanding the Item widths. The space is first allocated for Items that have LAYOUT_SHRINK (in other words, to the Items that had been sized to their minimum widths.) These Items are expanded at most to their preferred sizes. If there is still leftover horizontal space after this, the rest of the space is distributed equally to those Items that use the LAYOUT_EXPAND directive. If there are no such Items, then the free space is left to the row and the Items in the row are horizontally aligned based on the horizontal alignment value shared by the Items.

The row height is determined by the tallest Item in a row. The tallest Item is found by checking the heights of all the Items in the row. If an Item has LAYOUT_VSHRINK, its minimum height is used; otherwise, the Item's preferred height is used in this check. After the row height is known, some of the Items in the row are expanded based on their vertical layout directives. Items that use the LAYOUT_VSHRINK directive are expanded to their preferred height or to the height of the row, whichever is smaller. Items that are still shorter than the row height and that use the LAYOUT_VEXPAND directive are expanded to the height of the row. The LAYOUT_VEXPAND directive on an Item will never increase the height of a row.

Remaining Items shorter than the row height are positioned vertically within the row using the LAYOUT_TOP, LAYOUT_BOTTOM, and LAYOUT_VCENTER directives. If no vertical layout directive is specified, then the Item is aligned along the bottom of the row.

The sample code below illustrates the use of the LAYOUT_EXPAND, LAYOUT_VEXPAND, and LAYOUT_TOP directives. Figure 10.3 shows how the Items are sized using these directives. The left part of the figure indicates the state before the directives have been applied and right part indicates the result of the directives. These Items have been set using the following directives:

item1.setLayout(Item.LAYOUT_EXPAND);
item2.setLayout(Item.LAYOUT_DEFAULT);
item3.setLayout(Item.LAYOUT_EXPAND);
item4.setLayout(Item.LAYOUT_TOP);
item5.setLayout(Item.LAYOUT_DEFAULT)
item6.setLayout(Item.LAYOUT_VEXPAND);
Figure 10.3. Applying vertical and horizontal layout directives

graphics/10fig03.gif

On the first Form row, item1 and item3 are horizontally expanded so that all empty space in the row is divided between these items. On the second row, item6 is first vertically expanded to the entire row height, and then item4 is aligned to the top of the row.

10.9.6 Spacer

graphics/new_icon.gif

Spacer is an Item whose only purpose is to add empty space to the Form layout. This can be done because Spacer allows its minimum size to be set. The minimum width is useful for allocating flexible amounts of space between Items in the same row of a Form.

The example below illustrates the use of a horizontal Spacer.

graphics/10fig03a.gif
StringItem left = StringItem(null,
                             "left");
Spacer spacer = new Spacer(10, 2);
StringItem right = StringItem(null,
                             "right");

// Have spacer expand horizontally
spacer.setLayout(Item.LAYOUT_EXPAND);

Note that the minimum height can be used for enforcing a particular minimum height in a row. For an unlocked Spacer, the preferred width is also the same as the minimum width set by the application.

    [ directory ] Previous Section Next Section