The Android User Interface

The project you created in an earlier tutorial was just the default files generated by the Android build tools — you did not write any Java code yourself. In this chapter, we will examine the basic Java code and resources that make up an Android activity.

The Activity

The Java source code that you maintain will be in a standard Java-style tree of directories based upon the Java package you chose when you created the project (e.g., com.commonsware.android results in com/commonsware/android/). Android Studio will have that source, by default, in app/src/main/java/ off of the top-level project root.

If, in the new-project wizard, you elected to create an activity, you will have, in the innermost directory, a Java source file representing an activity class.

A very simple activity looks like:

package com.commonsware.empublite;

import android.app.Activity;
import android.os.Bundle;

public class EmPubLiteActivity extends Activity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
  }
}
(from EmPubLite-AndroidStudio/T2-Project/EmPubLite/app/src/main/java/com/commonsware/empublite/EmPubLiteActivity.java)

Dissecting the Activity

Let’s examine this Java code piece by piece:

package com.commonsware.empublite;

import android.app.Activity;
import android.os.Bundle;
(from EmPubLite-AndroidStudio/T2-Project/EmPubLite/app/src/main/java/com/commonsware/empublite/EmPubLiteActivity.java)

By default, the package declaration is the same as the one you used when creating the project. And, like any other Java project, you need to import any classes you reference. Most of the Android-specific classes are in the android package.

Remember that not every Java SE class is available to Android programs! Visit the Android class reference to see what is and is not available.

public class EmPubLiteActivity extends Activity {
(from EmPubLite-AndroidStudio/T2-Project/EmPubLite/app/src/main/java/com/commonsware/empublite/EmPubLiteActivity.java)

Activities are public classes, inheriting from the android.app.Activity base class (or, possibly, from some other class that itself inherits from Activity). You can have whatever data members you decide that you need, though the initial code has none.


  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
(from EmPubLite-AndroidStudio/T2-Project/EmPubLite/app/src/main/java/com/commonsware/empublite/EmPubLiteActivity.java)

The onCreate() method is invoked when the activity is started. We will discuss the Bundle parameter to onCreate() in a later chapter. For the moment, consider it an opaque handle that all activities receive upon creation.

The first thing you normally should do in onCreate() is chain upward to the superclass, so the stock Android activity initialization can be done. The only other statement in our stub project’s onCreate() is a call to setContentView(). This is where we tell Android what the user interface is supposed to be for our activity.

This raises the question: what does R.layout.main mean? Where did this R come from?

To explain that, we need to start thinking about layout resources and how resources are referenced from within Java code.

Using XML-Based Layouts

As noted in the previous chapter, Android uses a series of widgets and containers to describe your typical user interface. These all inherit from an android.view.View base class, for things that can be rendered into a standard widget-based activity.

While it is technically possible to create and attach widgets and containers to our activity purely through Java code, the more common approach is to use an XML-based layout file. Dynamic instantiation of widgets is reserved for more complicated scenarios, where the widgets are not known at compile-time (e.g., populating a column of radio buttons based on data retrieved off the Internet).

With that in mind, it’s time to break out the XML and learn how to lay out Android activity contents that way.

What Is an XML-Based Layout?

As the name suggests, an XML-based layout is a specification of its widgets’ relationships to each other — and to containers — encoded in XML format. Specifically, Android considers XML-based layouts to be resources, and as such layout files are stored in the res/layout/ directory inside your Android project (or, as we will see later, other layout resource sets, like res/layout-land/ for layouts to use when the device is held in landscape). As has been noted elsewhere in this book, the initial location of res/ is in app/src/main/ for Android Studio.

Each XML file contains a tree of elements specifying a layout of widgets and containers that make up one View. The attributes of the XML elements are properties, describing how a widget should look or how a container should behave. For example, if a Button element has an attribute value of android:textStyle = "bold", that means that the text appearing on the face of the button should be rendered in a boldface font style.

For example, here is a res/layout/main.xml file that could be used with the aforementioned activity:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:id="@+id/main"
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:paddingBottom="@dimen/activity_vertical_margin"
  android:paddingLeft="@dimen/activity_horizontal_margin"
  android:paddingRight="@dimen/activity_horizontal_margin"
  android:paddingTop="@dimen/activity_vertical_margin"
  tools:context="com.commonsware.empublite.EmPubLiteActivity">

  <TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Hello World!" />
</RelativeLayout>
(from EmPubLite-AndroidStudio/T2-Project/EmPubLite/app/src/main/res/layout/main.xml)

The class name of a widget or container — such as RelativeLayout or TextView – forms the name of the XML element. Since TextView 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.

The attributes are properties of the widget or container, describing what it should look and work like. For example, the android:layout_width and android:layout_height attributes on the TextView element make a request from the child (TextView) to its parent (a RelativeLayout) for what size the child should be.

We will get into details about these attributes, their possible values, and their uses, in upcoming chapters. Note that those attributes in the tools namespace (e.g., tools:context) are there solely to support the Android build tools, and do not affect the runtime execution of your project.

Android’s SDK ships with a tool (aapt) which uses the layouts. This tool will be automatically invoked by your Android tool chain (e.g., Android Studio). Of particular importance to you as a developer is that aapt generates an R.java source file, allowing you to access layouts and widgets within those layouts directly from your Java code. In other words, this is where that magic R value used in setContentView() comes from. We will discuss that a bit more later in this chapter.

XML Layouts and Your IDE

If you are using Android Studio, and you double-click on the res/layout/main.xml file in your project, you will not initially see that XML. Instead, you will be taken to the graphical layout editor:

Android Studio Graphical Layout Editor
Figure 70: Android Studio Graphical Layout Editor

We will go into much more detail about using the graphical layout editor in an upcoming chapter, as we start to work more with specific widgets and containers.

Why Use XML-Based Layouts?

Almost everything you do using XML layout files can be achieved through Java code. For example, you could use setText() to have a button display a certain caption, instead of using a property in an XML layout. Since XML layouts are yet another file for you to keep track of, we need good reasons for using such files.

Perhaps the biggest reason is to assist in the creation of tools for view definition, such as the aforementioned graphical layout editors in Android Studio. Such GUI builders could, in principle, generate Java code instead of XML. The challenge is re-reading the definition in to support edits — that is far simpler if the data is in a structured format like XML than in a programming language. Moreover, keeping the generated bits separated out from hand-written code makes it less likely that somebody’s custom-crafted source will get clobbered by accident when the generated bits get re-generated. XML forms a nice middle ground between something that is easy for tool-writers to use and easy for programmers to work with by hand as needed.

Also, XML as a GUI definition format is becoming more commonplace. Microsoft’s XAML, Adobe’s Flex, Google’s GWT, and Mozilla’s XUL 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, 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.

Using Layouts from Java

Given that you have painstakingly set up the widgets and containers for your view 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, as we saw in our stub project’s activity:


setContentView(R.layout.main);

Here, R.layout.main tells Android to load in the layout (layout) resource (R) named main.xml (main).