Mobile Phone Handheld Hardware Hardware Rick Rogers John Lombardo O'Reilly Media, Inc. O'Reilly Media Android Application Development, 1st Edition10.2. Assembling a Graphical InterfaceThe Android UI framework provides both a complete set of
drawing tools with which to build a UI and a rich collection of prebuilt
components based on these tools. As we will see in Chapter 12, the framework graphics tools provide
plenty of support for applications that need to create their own controls
or render special views. On the other hand, many applications may work
very well using only canned widgets from the toolkit. In fact, as we saw
in Chapter 9, the MapActivity and MyLocationOverlay classes make it possible to
create extremely sophisticated applications without doing any custom
drawing at all. We've already used the term "widget" once or twice, without
explicitly defining it. Recall that the screen is a rendered by a tree of
components. In the Android UI framework, these components are all
subclasses of android.view.View. The
components that are leaves or nearly leaves do most of the actual drawing
and are, in the context of an application UI, commonly called
widgets. The internal nodes, sometimes called Container
Views, are special components that can have other components as
children. In the Android UI framework, Container Views are subclasses of
android.view.ViewGroup,
which, of course, is in turn a subclass of View. Typically, they do very little drawing.
Instead, they are responsible for arranging their child components on the
screen and keeping them arranged as the display changes shape,
orientation, and so on. Doing this can be quite complex. You have already seen a very simple View coded up in Section 2.2.3. That application created a trivial
TextView and displayed it. There is no
way to add anything to that application, because the root
View is a TextView,
which cannot be a container for other components. To create more complex
displays, it is necessary to assemble a tree of containers. Example 10-1 shows an application with a view
tree that is three layers deep. A vertical linear layout contains two
horizontal linear layouts. Each of the horizontal layouts, in turn,
contains two widgets. Example 10-1. A complex view treepackage com.oreilly.android.intro;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.Gravity;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
public class AndroidDemo extends Activity {
private LinearLayout root;
@Override
public void onCreate(Bundle state) {
super.onCreate(state);
LinearLayout.LayoutParams containerParams
= new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
0.0F);
LinearLayout.LayoutParams widgetParams
= new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.FILL_PARENT,
1.0F);
root = new LinearLayout(this);
root.setOrientation(LinearLayout.VERTICAL);
root.setBackgroundColor(Color.LTGRAY);
root.setLayoutParams(containerParams);
LinearLayout ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.HORIZONTAL);
ll.setBackgroundColor(Color.GRAY);
ll.setLayoutParams(containerParams);
root.addView(ll);
EditText tb = new EditText(this);
tb.setText(R.string.defaultLeftText);
tb.setFocusable(false);
tb.setLayoutParams(widgetParams);
ll.addView(tb);
tb = new EditText(this);
tb.setText(R.string.defaultRightText);
tb.setFocusable(false);
tb.setLayoutParams(widgetParams);
ll.addView(tb);
ll = new LinearLayout(this);
ll.setOrientation(LinearLayout.HORIZONTAL);
ll.setBackgroundColor(Color.DKGRAY);
ll.setLayoutParams(containerParams);
root.addView(ll);
Button b = new Button(this);
b.setText(R.string.labelRed);
b.setTextColor(Color.RED);
b.setLayoutParams(widgetParams);
ll.addView(b);
b = new Button(this);
b.setText(R.string.labelGreen);
b.setTextColor(Color.GREEN);
b.setLayoutParams(widgetParams);
ll.addView(b);
setContentView(root);
}
} |
Note that the code preserves a reference to the root of the View
tree for later use. This example uses three LinearLayout widgets. A LinearLayout, just as
its name implies, is a View that displays its children
in a row or column, as determined by its orientation property. The child
views are displayed in the order in which they are
added to the LinearLayout (regardless of the order in which
they were created), in the directions familiar to
Western readers: left to right and top to bottom. The button labeled
"Green", for instance, is in the lower righthand corner of this layout,
because it is the second thing added to the horizontal LinearLayout View, which was, in turn, the
second thing added to the vertical LinearLayout (the root). Figure 10-2 shows what the
results might look like to the user. The seven Views in
the tree are structured as shown in Figure 10-3. 

Chapter 8 explained that the
Android framework provides a convenient capability for separating data
resources from code. This is particularly useful in building view
component layouts. The previous example can be replaced with the dramatically
simpler code in Example 10-2 and the
XML definition of the layout in Example 10-3. Example 10-2. Complex View using a layout resourcepackage com.oreilly.android.intro;
import android.app.Activity;
import android.os.Bundle;
/**
* Android UI demo program
*/
public class AndroidDemo extends Activity {
private LinearLayout root;
@Override public void onCreate(Bundle state) {
super.onCreate(state);
setContentView(R.layout.main);
root = (LinearLayout) findViewById(R.id.root);
}
} |
Example 10-3. Complex View layout resource<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root"
android:orientation="vertical"
android:background="@drawable/lt_gray"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<LinearLayout
android:orientation="horizontal"
android:background="@drawable/gray"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/text1"
android:text="@string/defaultLeftText"
android:focusable="false"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"/>
<EditText
android:id="@+id/text2"
android:text="@string/defaultRightText"
android:focusable="false"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:background="@drawable/dk_gray"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/button1"
android:text="@string/labelRed"
android:textColor="@drawable/red"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"/>
<Button
android:id="@+id/button2"
android:text="@string/labelGreen"
android:textColor="@drawable/green"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"/>
</LinearLayout>
</LinearLayout> |
This version of the code, like the first one, also preserves a
reference to the root of the View tree. It does this by tagging a widget
in the XML layout (the root LinearLayout, in this case) with an android:id tag, and then using the findViewById method from the Activity class
to recover the reference. It is a very good idea to get into the habit of using a resource to
define your View tree layout. Doing so allows you to separate the visual
layout from the code that brings it to life. This way, you can tinker with
the layout of a screen without recompiling. Further, if the history of
other UI frameworks is any indication, there will eventually be tools for
Android that allow you to compose screens, creating their XML definitions,
using a visual UI editor.
 |