Fields are the fundamental UI components that you'll use when you create UIs for your applications.
A field is a rectangular region that is contained by a manager and can be drawn on the screen of a BlackBerry device. A field contains content, such as the text label of a button or items in a drop-down list, and a border that surrounds the content. A field also contains padding, which is the area of space between the content and the border.
A field is represented by the Field class, which is included in the net.rim.device.api.ui package. All UI components in the BlackBerry Java SDK are derived from Field. For example, prebuilt UI components such as the ButtonField, CheckboxField, LabelField, and TextField classes all extend Field. Managers, which are represented by the Manager class, and screens, which are represented by the Screen class, also extend Field.
Constructors for the various field classes can accept style bits as parameters. Style bits are constants in Field that specify the visual properties of the field. These properties include the alignment of the field within its manager, how much space the field is allowed to use within its manager, and whether the field can be edited or accept the focus. For example, you can specify the Field.FIELD_HCENTER style bit to center a field horizontally within its manager, and you can specify the Field.USE_ALL_WIDTH style bit to direct a field to use all of the available width of its manager when it is drawn. A field is responsible for sizing itself when it is drawn, but the manager that contains the field is responsible for scrolling. The Manager class extends the ScrollView class, which implements the scrolling functionality.
The Field class is an abstract class, meaning that you cannot create Field objects directly. Instead, you can use the UI components that are included in the net.rim.device.api.ui package in your applications, or you can extend Field to create your own custom field. If you choose to create a custom field, you must implement the layout() and paint() abstract methods to specify how to arrange and draw the field.
The layout() method arranges the contents of the field. You can override this method to provide custom layout instructions for your field. For example, you might use this method to specify the size and positioning of the content in your field. This method is invoked when events occur that might change the arrangement of fields on a screen, such as when fields are added to or removed from a screen or when the device is rotated. If you choose to override this method, you must invoke setExtent() within layout() to specify the size of the field.
The paint() method draws the content area of the field. The content area might include text or graphics, and this method determines how this content appears when it is drawn. For example, you can override this method to draw text in a specific color in your field. This method is invoked when events occur that might change the visual appearance of a field, such as when the screen scrolls or when the field gains or loses the focus. If you need to force a field to repaint itself, you can invoke invalidate() on the field. A Graphics object is passed into paint() when the method is invoked, and you can use this object to draw on the screen.
The BlackBerry Java SDK uses a box model that is similar to the HTML or CSS box model to draw and arrange UI components on a screen. Every field is composed of four elements:
- Content: The content to display in the field, such as text or graphics.
- Padding: The area of space between the padding and the border.
- Border: The visual boundary that surrounds the field.
- Margin: The area of space that is outside of the border.
You can apply padding, border, and margin values to all classes that extend the Field class, including prebuilt UI components, screens, managers, and custom fields.
The padding of a field is the area of space between the content of the field and the field's border. You can invoke getPadding(XYEdges) to retrieve an XYEdges object that represents the coordinates of a field's padding. Alternatively, you can invoke getPaddingBottom(), getPaddingLeft(), getPaddingRight(), and getPaddingTop() to retrieve the padding coordinates individually. You can invoke setPadding(int, int, int, int) and setPadding(XYEdges) to set the padding for a field.
If padding has been applied to a field, the origin points that are used by paintBackground() and paint() are different. The paintBackground() method uses an origin that represents the upper-left corner of the padding area, on the inside edge of the border. The paint() method uses an origin that represents the upper-left corner of the content area of the field.
The border of a field is the visual area that surrounds the content and padding of the field. A border is typically represented by the Border class, which is included in the net.rim.device.api.ui.decor package.
The Border class is an abstract class. To create Border objects, you can use methods that are provided in the BorderFactory class, including the following:
- createSimpleBorder(XYEdges): Creates a solid, single-line border with sharp corners
- createRoundedBorder(XYEdges): Creates a solid, single-line border with rounded corners
- createBevelBorder(XYEdges): Creates a 3-D bevel border
The BorderFactory class contains different versions of these methods that you can use to create borders with specific sizes, styles, and colors. You can also extend the Border class to create a custom border. If you choose to create a custom border, you must implement paint(Graphics, XYRect) to specify how the border is drawn on the screen, and isTransparent() to specify whether the border is transparent.
You can invoke Field.getBorder() to retrieve a Border object that represents the border of a field, based on the current visual state of the field. You can also invoke Field.getBorder(int) to retrieve a border that is associated with a particular visual state. You can specify a visual state by using constants in Field, such as Field.VISUAL_STATE_ACTIVE, Field.VISUAL_STATE_FOCUS, Field.VISUAL_STATE_DISABLED, and so on. You can invoke Field.setBorder(Border) and its variations to set the border for a field.
The margin of a field is the area that is outside of the field's border. You cannot paint in the margin of a field. Margins are used to control the space between fields in a manager, and it is the responsibility of the manager to respect margins correctly.
When two fields that have margins are positioned next to each other on a screen, the margins collapse into each other. For example, consider two fields that both have margins of five pixels. If these fields are placed next to each other on a screen, you might expect that the space between them would be 10 pixels (five pixels for each field). Instead, the space between them is only five pixels, because the margins collapse by five pixels.
When two fields that have unequal margins are positioned next to each other, the margins collapse by the smaller of the two margins. For example, consider a field with a margin of four pixels and a field with a margin of eight pixels. If these fields are placed next to each other, the space between them is eight pixels.
Determining the dimensions of a field
When you draw fields on the screen of your application, there are several methods in the Field class that you can use to determine the dimensions of a field. Depending on which method you use, you might receive different values for the width and height of the field. It's important to use the method that is most appropriate in a particular situation to make sure that your fields are drawn properly.
The getWidth() and getHeight() methods retrieve the amount of space that the field uses within the manager that contains the field. The values that are returned from these methods include any area that is required for the padding and border of the field. A field cannot use the padding area or border area when it draws its own content, but it is important for the field's manager to retrieve the width and height of the field with these areas included so that the manager can arrange the fields without overlapping.
The getContentWidth() and getContentHeight() methods retrieve the amount of space that the content area of the field uses. The values that are returned from these methods do not include the space that is used by the padding and border. When a field paints itself using paint(), the Graphics object that the field receives is configured with the origin in the upper-left corner of the content area. The clip area, which is the area that the field is allowed to draw in, is specified as the width and height of the content area. The field can draw only in this area.
The getPreferredWidth() and getPreferredHeight() methods are designed to retrieve the space that a custom field should use if the field has an unlimited amount of space available. By default, these methods return 0. When you create a custom field, you should override these methods to return the preferred width and height of the custom field. These values are considered suggestions, and may not be used by a manager when it lays out the fields that it contains.
When you are using any of the methods that are listed above to determine the dimensions of a field, you should not assume that the values that are returned from getWidth() and getHeight() are the same as those returned from getContentWidth() and getContentHeight(). If padding or a border is added to a field, these values will be different. Similarly, you should not assume that the values that are returned from getWidth() and getHeight() are the same as those returned from getPreferredWidth() and getPreferredHeight().