Order of Evaluation

What makes this even more complicated is the order of evaluation. Android makes a single pass through your XML layout and computes the size and position of each widget in sequence. This has a couple of ramifications:

• You cannot reference a widget that has not yet been defined in the file.

• You must be careful that any uses of fill parent in android:layout width or android: layout height do not "eat up" all the space before subsequent widgets have been defined.

RelativeLayout Example

With all that in mind, let's examine a typical "form" with a field, a label, plus 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" android:padding="5px">

<TextView android:id="@+id/label" android:layout width="wrap content" android:layout height="wrap content" android:text="URL:" android:paddingTop="15px"/> <EditText android:id="@+id/entry" android:layout width="fill parent" android:layout height="wrap content" android:layout toRightOf="@id/label" android:layout alignBaseline="@id/label"/> <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 up the RelativeLayout. In this case, we want to use the full width of the screen (android:layout width = "fill parent"), use only as much height as we need (android: layout height = "wrap content"), and have a 5-pixel pad between the boundaries of the container and its contents (android:padding = "5px").

Next we define the label, which is fairly basic, except for its own 15-pixel padding (android:padding = "15px"). More on that in a moment.

After that we add in the field. We want the field to be to the right of the label, have both the field and label text aligned along the baseline, and for the field to take up the rest of this "row" in the layout. Those components are handled by three properties:

• android:layout toRight = "@id/label"

• android:layout alignBaseline = "@id/label"

• android:layout width = "fill parent"

If we were to skip the 15-pixel padding on the label, we would find that the top of the field is clipped off. That's because of the 5-pixel padding on the container itself. The android: layout alignBaseline = "@id/label" property simply aligns the baselines of the label and field. The label, by default, has its top aligned with the top of the parent. But the label is shorter than the field because of the field's box. Since the field is dependent on the label's position and the label's position is already defined (because it appeared first in the XML), the field winds up being too high and has the top of its box clipped off by the container's padding.

You may find yourself running into these sorts of problems as you try to get your RelativeLayout to behave the way you want it to.

The solution to this conundrum, used in the XML layout shown earlier in this section, is to give the label 15 pixels' worth of padding on the top. This pushes the label down far enough that the field will not get clipped.

Here are some points of note:

• You cannot use android:layout alignParentTop on the field, because you cannot have two properties that both attempt to set the vertical position of the field. In this case, android:layout alignParentTop conflicts with the later android:layout alignBaseline = "@id/label" property, and the last one in wins. So, you either have the top aligned properly or the baselines aligned properly, but not both.

• You cannot define the field first, then put the label to the left of the field, because you cannot "forward-reference" labeled widgets—you must define the widget before you can reference it by its ID.

Going back to the example, 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 auto-generated Java code, the emulator gives us the result shown in Figure 7-6.

SfflD® 12:34 AM I



Figure 7-6. The RelativeLayoutDemo sample application

0 0

Post a comment