RelativeLayout, as the
name suggests, lays out widgets based on their relationship to other
widgets in the container and the parent container. You can place widget X
below and to the left of widget Y, have widget Z's bottom edge align
with the bottom of the container, and so on. This is reminiscent of
James Elliot's RelativeLayout for use with Java/Swing.
1. RelativeLayout Concepts and Properties
To make all this work, we
need ways to reference other widgets within an XML layout file, plus
ways to indicate the relative positions of those widgets.
1.1. Positions Relative to Container
The easiest relationships to set
up are those that tie a widget's position to that of its container,
using the following properties:
android:layout_alignParentTop: Aligns the widget's top with the top of the container
android:layout_alignParentBottom: Aligns the widget's bottom with the bottom of the container
android:layout_alignParentLeft: Aligns the widget's left side with the left side of the container
android:layout_alignParentRight: Aligns the widget's right side with the right side of the container
android:layout_centerHorizontal: Positions the widget horizontally at the center of the container
android:layout_centerVertical: Positions the widget vertically at the center of the container
android:layout_centerInParent: Positions the widget both horizontally and vertically at the center of the container
All of these properties take a simple Boolean value (true or false).
Note that the padding of the
widget is taken into account when performing these various alignments.
The alignments are based on the widget's overall cell (combination of
its natural space plus the padding).
1.2. Relative Notation in Properties
The remaining properties of relevance to RelativeLayout take as a value the identity of a widget in the container. To do this:
Put identifiers (android:id attributes) on all elements that you will need to address.
Reference other widgets using the same identifier value.
The first occurrence of an id value should include the plus sign (@+id/widget_a); the second and subsequent times that id value is used in the layout file, the plus sign should be omitted (@id/widget_a). This allows the build tools to better help you catch typos in your widget id values—if you do not have a plus sign for a widget id value that has not been seen before, that will be caught at compile time.
For example, if widget A is identified as @+id/widget_a, widget B can refer to widget A in one of its own properties via the identifier @id/widget_a.
1.3. Positions Relative to Other Widgets
The following four properties control the position of a widget relative to other widgets:
android:layout_above: Indicates that the widget should be placed above the widget referenced in the property
android:layout_below: Indicates that the widget should be placed below the widget referenced in the property
android:layout_toLeftOf: Indicates that the widget should be placed to the left of the widget referenced in the property
android:layout_toRightOf: Indicates that the widget should be placed to the right of the widget referenced in the property
Beyond those four properties, five additional properties can be used to control one widget's alignment relative to another:
android:layout_alignTop: Indicates that the widget's top should be aligned with the top of the widget referenced in the property
android:layout_alignBottom: Indicates that the widget's bottom should be aligned with the bottom of the widget referenced in the property
android:layout_alignLeft: Indicates that the widget's left should be aligned with the left of the widget referenced in the property
android:layout_alignRight: Indicates that the widget's right should be aligned with the right of the widget referenced in the property
android:layout_alignBaseline:
Indicates that the baseline of the two widgets should be aligned (where
the baseline is the invisible line that text appears to sit on)
The android:layout_alignBaseline
property is useful for aligning labels and fields so that the text
appears natural. Since fields have a box around them and labels do not, android:layout_alignTop
would align the top of the field's box with the top of the label,
causing the text of the label to be higher on the screen than the text
entered into the field.
So, if we want widget B to be positioned to the right of widget A, in the XML element for widget B, we need to include android:layout_toRightOf = "@id/widget_a" (assuming @id/widget_a is the identity of widget A).
1.4. Order of Evaluation
Android formerly used a single pass to process RelativeLayout-defined rules. That meant you could not reference a widget (e.g., via android:layout_above)
until it had been declared in the XML. This made defining some layouts a
bit complicated. Starting in Android 1.6, Android uses two passes to
process the rules, so you can now safely have forward references to
as-yet-undefined widgets.
2. RelativeLayout Example
With all that in mind, let's
examine a typical form with a field, a label, and a pair of buttons
labeled OK and Cancel. Here is the XML layout, pulled from the Containers/Relative sample project:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView android:id="@+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="URL:"
android:layout_alignBaseline="@+id/entry"
android:layout_alignParentLeft="true"/>
<EditText
android:id="@id/entry"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/label"
android:layout_alignParentTop="true"/>
<Button
android:id="@+id/ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/entry"
android:layout_alignRight="@id/entry"
android:text="OK" />
<Button
android:id="@+id/cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="@id/ok"
android:layout_alignTop="@id/ok"
android:text="Cancel" />
</RelativeLayout>
First, we open the RelativeLayout. In this case, we want to use the full width of the screen (android:layout_width = "fill_parent") and only as much height as we need (android:layout_height = "wrap_content").
Next, we define the label as a TextView. We indicate that we want its left edge aligned with the left edge of the RelativeLayout (android:layout_alignParentLeft="true") and its baseline aligned with the baseline of the yet-to-be-defined EditText. Since the EditText has not been declared yet, we use the + sign in the ID (android:layout_alignBaseline="@+id/entry").
After that, we add in the field as an EditText. We want the field to be to the right of the label, have the field be aligned with the top of the RelativeLayout,
and have the field take up the rest of this "row" in the layout. These
requirements are handled by the following three properties,
respectively:
android:layout_toRightOf = "@id/label"
android:layout_alignParentTop = "true"
android:layout_width = "fill_parent"
Then, the OK button is set to be below the field (android:layout_below = "@id/entry") and have its right side align with the right side of the field (android:layout_alignRight = "@id/entry"). The Cancel button is set to be to the left of the OK button (android:layout_toLeft = "@id/ok") and have its top aligned with the OK button (android:layout_alignTop = "@id/ok").
With no changes to the autogenerated Java code, the emulator gives us the result shown in Figure 1.