Also, XML as a GUI definition format is becoming more commonplace. Microsoft’s XAML[9], Adobe’s Flex[10], and Mozilla’s XUL[11] all take a similar approach to that of Android: put layout details in an XML file and put programming smarts in source files (e.g., JavaScript for XUL). Many less-well-known GUI frameworks, such as ZK[12], also use XML for view definition. While “following the herd” is not necessarily the best policy, it does have the advantage of helping to ease the transition into Android from any other XML-centered view description language.
OK, So What Does It Look Like?
Here is the Button
from the previous chapter’s sample application, converted into an XML layout file, found in the Layouts/NowRedux
sample project. This code sample along with all others in this chapter can be found in the Source Code area of http://apress.com.
<?xml version="1.0" encoding="utf-8"?>
<Button xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/button"
android:text=""
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
The class name of the widget — Button
— forms the name of the XML element. Since Button
is an Android-supplied widget, we can just use the bare class name. If you create your own
widgets as subclasses of android.view.View
, you would need to provide a full package declaration as well (e.g., com.commonsware.android.MyWidget
).
The root element needs to declare the Android XML namespace:
xmlns:android="http://schemas.android.com/apk/res/android"
All other elements will be children of the root and will inherit that namespace declaration.
Because we want to reference this button from our Java code, we need to give it an identifier via the android:id
attribute. We will cover this concept in greater detail later in this chapter.
The remaining attributes are properties of this Button
instance:
• android:text
indicates the initial text to be displayed on the button face (in this case, an empty string)
• android:layout_width
and android:layout_height
tell Android to have the button’s width and height fill the “parent”, in this case the entire screen — these attributes will be covered in greater detail in Chapter 7.
Since this single widget is the only content in our activity, we only need this single element. Complex UIs will require a whole tree of elements, representing the widgets and containers that control their positioning. All the remaining chapters of this book will use the XML layout form whenever practical, so there are dozens of other examples of more complex layouts for you to peruse from Chapter 7 onward.
What’s with the @ Signs?
Many widgets and containers only need to appear in the XML layout file and do not need to be referenced in your Java code. For example, a static label (TextView
) frequently only needs to be in the layout file to indicate where it should appear. These sorts of elements in the XML file do not need to have the android:id
attribute to give them a name.
Anything you do want to use in your Java source, though, needs an android:id
.
The convention is to use @+id/...
as the id value, where the ...
represents your locally-unique name for the widget in question. In the XML layout example in the preceding section, @+id/button
is the identifier for the Button
widget.
Android provides a few special android:id
values, of the form @android:id/...
. We will see some of these in various chapters of this book, such as Chapters 8 and 10.
We Attach These to the Java… How?
Given that you have painstakingly set up the widgets and containers in an XML layout file named main.xml
stored in res/layout
, all you need is one statement in your activity’s onCreate()
callback to use that layout:
setContentView(R.layout.main);
This is the same setContentView()
we used earlier, passing it an instance of a View
subclass (in that case, a Button
). The Android-built view, constructed from our layout, is accessed from that code-generated R
class. All of the layouts are accessible under R.layout, keyed by the base name of the layout file — main.xml
results in R.layout.main
.
To access our identified widgets, use findViewById()
, passing in the numeric identifier of the widget in question. That numeric identifier was generated by Android in the R
class as R.id.something
(where something is the specific widget you are seeking). Those widgets are simply subclasses of View
, just like the Button
instance we created in Chapter 4.
The Rest of the Story
In the original Now
demo, the button’s face would show the current time, which would reflect when the button was last pushed (or when the activity was first shown, if the button had not yet been pushed).
Most of that logic still works, even in this revised demo (NowRedux
). However, rather than instantiating the Button in our activity’s onCreate()
callback, we can reference the one from the XML layout:
package com.commonsware.android.layouts;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import java.util.Date;
public class NowRedux extends Activity
implements View.OnClickListener {
Button btn;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
btn=(Button)findViewById(R.id.button);
btn.setOnClickListener(this);
updateTime();
}
public void onClick(View view) {