Android Tutorial (4) – Procedural vs. Declarative Design of User Interfaces

Android mobile applications are relying on user interfaces composed on dialog windows, visual controls, 2D graphics and other multimedia elements for efficiency and usability. The Android platforms allows programmers to use two methods to design user interfaces: procedural or declarative.

In this post we develop a simple Android mobile applications that will help to make an analysis on procedural vs. declarative design of user interfaces.

Procedural means to use only Java code to design the user interface. This is something usual in designing Swing interfaces on JSE platform or designing user interfaces in J2ME MIDlets. Because every element of the user interface is managed by different classes instance, designing means to create them and to manage them.

Declarative means to use a descriptive markup language, as XHTML or XML, to describe the user interface. This is similar to how simple HTML pages are done. The designer describes the page look and the browser interprets and generates the user interface.

Some topics used in this post have been described in detail in:

Other topics that are part of this Android tutorial are accessible through Android Tutorial – Overview and contents.

The Android mobile application developed in this procedural vs. declarative analysis looks like this:

Example of simple Android mobile application
Example of simple Android mobile application

The user interface of the sample application its simple and it is based on a single Activity that has a linear layout with 2 controls: a TextView and a Button.

How to design the user interface of an Android mobile application using View and ViewGroup instances

The user interface of the Android application is defined by one or multiple forms/windows/displays. Each window is controlled by an Activity object that has a complex lifecycle (Android Tutorial – Applications key concepts, activities and resources). The visual elements of the Activity instance are constructed  using ViewGroup and View objects.

The View class is the parent for a large hierarchy of visual controls, widgets, like textboxes, checkboxes, buttons, ….

The ViewGroup class is the base for a hierarchy of layouts, used to manage collections of widgets and to define the layout architecture (linear, relative, tabular) of the window.

Important !
Widgets are displayed only if they are added to the display layout. For the procedural manner you must add them to the View components collection using addView() method. For the declarative manner, you must define them inside they layout XML node.

The next diagram describes part of the Android widget framework that has as root the <strongview< strong=””> class.</strongview<>

Classes from Android View Hierarchy
Classes from Android View Hierarchy

These two classes and their subclasses represent the core elements for developing Android user interfaces. The display of the Activity instance is defined by:

  • a ViewGroup subclass like LinearLayout, RelativeLayout, TableLayout, FrameLayout that will define the layout and help you design the interface and the position of controls; it is possible to nest layouts and to define complex interfaces but keel in mind that the user interface is limited by the screen size and most of the times, simplicity equal efficiency and usability;
  • one or more View or ViewGroup (some visual controls, like Calendar View or Date Picker, are subclasses of ViewGroup) components.

If we take a look at a sample Android user interface

User Interface elements of Android mobile application
User Interface elements of Android mobile application

we can see that there is a relation between ViewGroup and View instances that defines a tree like architecture for the user interface that has as root a ViewGroup node:

Architecture of Android User Interface Components Architecture
Architecture of Android User Interface Components Architecture

How to design the Android user interface in a procedural manner

As specified earlier, designing the user interface programmatically means to use Java code. This was and is the only way for some development platforms and is possible because everything on the user interface represents a resource managed by an object.

In order to design programmatically or procedural the user interface you must understand the framework and to know the relation between user interface elements and their corresponding classes. Also the parent-child relation between elements is important, as some controls have containers or collections used to manage other child controls.

As seen in the first section of this post and in Android Tutorial – Applications key concepts, activities and resources, the window/form of an Android application is managed by an Activity class. This is what we get when we create an Android project in Eclipse with the next properties:

  • Project name: HelloWorldAndroid
  • Create new project in workspace: checked (default value)
  • Use default location: by default in the Eclipse workspace or you can change it
  • Build target: select Android 2.3.3 (Gingerbread);
  • Application name: Hello World Android (name in the application title bar)
  • Package name: eu.itcsolutions.tutorial.android
  • Create Activity: HelloActivity (leave the option checked and set the Activity name)
  • Min SDK Version: 10
package eu.itcsolutions.tutorial.android;

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

public class HelloActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
    	//call to the base class method
        super.onCreate(savedInstanceState);
        //set the layout of the display in a declarative manner
        setContentView(R.layout.main);
    }
}

The Eclipse IDE and the ADT plugin generates a simple Android application that has only one window/form. It also overrides the onCreate(Bundle savedInstanceState) method that is the default handler for the Activity creation event. This is a good moment to define the user interface. Also, Eclipse generates a simple user interface that has a linear layout and a Hello Android text. Because the generated user interface is done in a declarative manner remove the

        //loads a declarative layout
        //setContentView(R.layout.main);

statement. In this way, we will design the entire interface from the application code:

1. The first thing you must do is to open the Android API documentation, especially the section regarding the android.widget package. The great number of classes, methods and properties makes impossible learning by heart the  API and if you want to remember or to find a method check the documentation for that particular class.

2. The first modification of the generated solution is to change the text in the title bar. This is a property of the Activity and it is managed by the setTitle() method. All the modifications are done in the onCreate(Bundle savedInstanceState):

    @Override
    public void onCreate(Bundle savedInstanceState) {
    	//call the base class method
        super.onCreate(savedInstanceState);

        //set the title bar text
        this.setTitle("First Android Application");
    }

3. In order to define and control the position of user interface elements on the display we will create a linear layout. It will have a vertical orientation because we want its child elements to be placed on the layout on a top-bottom order:

        //define and create a linear layout
        LinearLayout mainLayout;
        mainLayout = new LinearLayout(this);
        //set vertical orientation
	mainLayout.setOrientation(1);

4. Create a container for the text information. In Android text labels are managed by a TextView widget. The text will have a defined String value (setText()), size (setTextSize()) and color (setTextColor()). Also we apply bold and italic style on the system default sans serif font (setTypeface()) using the Typeface class. For the color we use a predefined system color (Color class) but we can also define it using a RGB combination:

        TextView txtInfo = new TextView(this);
        txtInfo.setText("Hello World Android !");
        txtInfo.setTypeface(Typeface.SANS_SERIF, Typeface.BOLD_ITALIC);
        txtInfo.setTextSize(20);
        txtInfo.setTextColor(Color.GREEN);
        //txtInfo.setTextColor(Color.rgb(0, 255, 0));

5. Create a Button instance with the Click me ! text.

        Button btnClick = new Button(this);
        //define the button caption
        btnClick.setText("Click me !");

6. Once the user interface widgets have been created it doesn’t mean they will be displayed. In order to make them visible we must add them to the display layout:

        mainLayout.addView(txtInfo);
        mainLayout.addView(btnAbout);

7. Instruct the Activity to use the created layout as its display:

        //attach the layout to the Activity display
        this.setContentView(mainLayout);

After the last step, the user interface looks like this:

Example of simple Android Application
Example of simple Android Application

What we want to do now is to center the content of the display and to set some properties for the button.

8. In order to manage the position (on both axis, vertical and horizontal) of the content inside the layout it is used the setGravity(int gravity) method. The method uses as arguments a combination of predefined values. For the Gravity.CENTER_HORIZONTAL|Gravity.CENTER_VERTICAL combination we will instruct the layout to center vertically and horizontally its content:

mainLayout.setGravity(Gravity.CENTER_HORIZONTAL|Gravity.CENTER_VERTICAL);

9. By default the width of the TextView and the Button is equal  to the width of the parent container (in this example the LinearLayout). To control it, we can use the LayoutParams class that can be used to define the weight, width, height and gravity of the view element. Once the LayoutParams structure has been created, it is attached to the View element using the setLayoutParams( LayoutParams params ) method.

If we want to define the width of the TextView element equal to its content plus its padding then the width parameter of the LayoutParams instance will be WRAP_CONTENT. For the button we will use a predefined width of 120 pixels.

//define the LayoutParams for the TextView
//width - equal to the content
//height - equal to the content
android.widget.LinearLayout.LayoutParams txtLayoutParams =
    new LinearLayout.LayoutParams(
        android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
        android.view.ViewGroup.LayoutParams.WRAP_CONTENT);
//set the LayoutParams
txtInfo.setLayoutParams(txtLayoutParams);

//define the LayoutParams for the Button
//width - 120 px
//height - equal to the content
android.widget.LinearLayout.LayoutParams btnLayoutParams =
     new LinearLayout.LayoutParams(
         120,
         android.view.ViewGroup.LayoutParams.WRAP_CONTENT);
//set the LayoutParams
btnClick.setLayoutParams(btnLayoutParams);
Attention !
The LayoutParams structure is defined in the android.widget.LinearLayout package but the LayoutParams.WRAP_CONTENT and LayoutParams.MATCH_PARENT (replaces LayoutParams.FILL_PARENT) constants and their class are defined in android.view.ViewGroup package.

Adding the previous statements, before the call to setContentView(), we get the desired interface for the Android application:

Example of simple Android Application
Example of simple Android Application

How to design the Android user interface in a declarative manner

Programming languages and development tools have evolved to allow programmers to develop more complex applications and to concentrate on the solution functionality and architecture. The user interface represents an important component of the application but the core and the functionality is given by the source code behind it. Without it, the user interface is useless because it does nothing.

The declarative design of user interfaces for Android applications is based on XML markup language (as XHTML or HTML) which can be easily read and understood by programmers with little knowledge on Android platform. Despite the possibility to code the UI design, it is recommended to use the declarative approach because:

  • the architecture of the application UI is like a tree with a ViewGroup element as root and with widgets elements as leafs; the parent-child relation and the single root element are conditions that allow the use of XML files (they have a tree structure with the same rules);
  • the XML file can be edited with a simple text editor and its syntax is very simple comparing it with the Java language;
  • it is not related with any Java programming knowledge;
  • every Java class used for layouts and widgets has an equivalent as an element in the XML (with very few exceptions); as XML language is case sensitive as Java, the elements have the same name as the classes (i.e. the Java class TextView has the <TextView> equivalent);
  • the Android API documentation describes both the classes and the XML elements;
  • object properties are defined using XML attributes with the android::property_name="value" form;
  • you can change the XML based design without recompiling the source code; the XML files are preprocessed in a compressed binary format but this can be done independently from is the source code compilation.

The XML files that contain the UI description are placed in the \res\layout\ subfolder of the Android project directory (for a detailed description of the Android project components read Android Tutorial – How to create, run and read your first application, Hello World and Android Tutorial – Applications key concepts, activities and resources).

For an empty Android project, the Eclipse ADT plugin creates an initial layout which is described by the main.xml file from the \res\layout\ subfolder. Also, a statement from the overridden form of the onCreate() method instructs the Activity to set as main display the layout defined in main.xml.

        //R is the class that contains resources IDs
        setContentView(R.layout.main);

The initial generated form by Eclipse plugin is:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="@string/hello"
    />
</LinearLayout>

The first declaration is an information required for a XML document. The encoding attribute defines the set of characters used in the XML document.

Reading the main.xml document it is easy to see that the display is defined by a LinearLayout with a vertical orientation that fills the display and that contains a TextView element.

In order to recreate in a declarative manner the proposed Android application (described by the first image) we must edit the main.xml file. This can be done in Eclipse using either the graphical layout designer or the XML text editor.

Eclipse IDE Graphical editor for Android application layout
Eclipse IDE Graphical editor for Android application layout

The graphical layout has evolved and it has became a very useful tool for rapidly design the interface. When it comes to set properties values it is faster using the xml text editor which has a inteli-sense contextual menu activated with Ctrl+Space. In this simple example we will use the xml text editor.

Another interesting XML document is strings.xml from the \res\values\ project subfolder (for a detailed description of the Android project components read Android Tutorial – How to create, run and read your first application, Hello World and Android Tutorial – Applications key concepts, activities and resources). Initially it has two strings values, hello and app_name. The second represent the text from main display title bar.

The strings.xml is NOT used only by the declarative design if UI. It is a global resource for the Android project and its elements can be referenced from Java source code and from layout XML documents.

Attention !
The android:layout_width and android:layout_height attributes are mandatory for any widget and ViewGroup layout. Without one or both you get a RuntimeException.

1. Open the android.widget package documentation and reset the main.xml file to a blank display by deleting the generated UI and leaving only the first line of the XML document:

<?xml version="1.0" encoding="utf-8"?>

2. As for the procedural scenario, the first modification of the generated solution is to change the text in the title bar. This is done by modifying the app_name element from the strings.xml file. We set “First Android Application” as its new value.

Attention !
When you edit the layout XML file in the Eclipse text editor (NOT the Graphical Layout editor) use the inteli-sense contextual menu and the autocomplete function. The autocomplete contextual menu is activated with Ctrl+Space and it is very helpful by suggesting possible attributes names and values.

3. In the empty main.xml file we will the define the root node which is a linear layout that has a vertical orientation. The xmlns:android="http://schemas.android.com/apk/res/android" attribute is something required by the Android platform because it defined the XML namespace for Android.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
</LinearLayout>

Compared with the Java statements from the procedural solution, the attributes that define the width and the height of the layout are required for the <LinearLayout> element. Without them, you get a RuntimeException.

4. In the linear layout we add a TextView child. The best practice regarding constant values recommends using XML files from \res\values\ (string.xml for constant Strings) for storing them, but we can use them directly in the source code, as we did in the procedural solution by calling setText() method, or in the layout XML file. So, we will put the TextView value directly in the main.xml description, using the android:text attribut. For defining the text size we use the android:textSize attribute. For the font and style we use android:typeface and android:textStyle. The color of the text is set using android:textColor attribute and an #RGB value. Do not forget to set the layout_width and layout_height attributes. As we want a visible space equal to the content of the TextView we will set them to wrap_content.

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Hello World Android !"
    android:textSize="20px"
    android:textColor="#0f0"
    android:typeface="sans"
    android:textStyle="bold|italic"
/>

5. If we want to add a button to the linear layout, inside the <LinearLayout> …</LinearLayout> we define a <Button> element that has the value “Click me !” for its android:text attribut. Do not forget to set the layout_width and layout_height attributes. Because we want a custom width size button we set the 120 pixels for the layout_width.

<Button
    android:layout_width="120px"
    android:layout_height="wrap_content"
    android:text="Click me !"
/>

6. By default, any widget defined in the main.xml file or other layout file it will be displayed when the layout is loaded. Compared with the programmatic approach you don’t do something else to add them to the display (in the programmatic solution you create the instance and add it with addView() to the layout).

7. In order to manage the position (on both axis, vertical and horizontal) of the content inside the layout it is used the android:layout_gravity attribute. The attribute uses as values a combination of predefined values separated by | (logical OR). For the  “center_vertical|center_horizontal” combination we will instruct the layout to center vertically and horizontally its content:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_vertical|center_horizontal"
    >

8. Set the Activity to use the layout as its display. This is done in the Activity onCreate() method by calling the setContentView() method:

     setContentView(R.layout.main);

If you run the Android application you should get the same display as the one generated programmatic in the first section of this post.

Example of simple Android Application
Example of simple Android Application

Procedural vs. Declarative design of Android User Interface

This last head-to-head comparison of the two approaches may help you conclude on the advantages and possibilities of each method used to design the Android user interface:

Procedural design of Android UI

Declarative design of Android UI


using Java source code in the Activity onCreate() method

defining XML elements in main.xml file from the \res\layout\ project subfolder


//set the title bar text
this.setTitle(
"First Android Application");

Edit

<string name="app_name">
    First Android Application
</string>

element in the project strings.xml file


//define and create a linear layout
LinearLayout mainLayout;
mainLayout = 
    new LinearLayout(this);

//center the content
mainLayout.setGravity(
    Gravity.CENTER_HORIZONTAL |
    Gravity.CENTER_VERTICAL);
//set vertical orientation
mainLayout.setOrientation(1); 
<LinearLayout
    xmlns:android = "http://schemas.android.com/..."
    android:orientation = "vertical"
    android:layout_width = "match_parent"
    android:layout_height = "match_parent"
    android:gravity = "center_vertical|center_horizontal"
    >
</LinearLayout>

* – schema truncated

TextView txtInfo = 
        new TextView(this);
txtInfo.setText(
        "Hello World Android !");

//define the LayoutParams
//width - equal to the content
//height - equal to the content
LinearLayout.LayoutParams txtLayoutParams = 
    new LinearLayout.LayoutParams(
       ViewGroup.LayoutParams.WRAP_CONTENT,
       ViewGroup.LayoutParams.WRAP_CONTENT);

//set the LayoutParams
txtInfo.setLayoutParams(
        txtLayoutParams);

txtInfo.setTextSize(20);
txtInfo.setTypeface(
    Typeface.SANS_SERIF, 
    Typeface.BOLD_ITALIC);
txtInfo.setTextColor(Color.GREEN);
<TextView 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="Hello World Android !" 
    android:textSize="20dp" 
    android:textColor="#0f0"
    android:typeface="sans"
    android:textStyle="bold|italic"
/>

Button btnClick = 
    new Button(this);
//define the caption
btnClick.setText(
        "Click me !");

//define the LayoutParams
//width - 120 px
//height - equal to the content
LinearLayout.LayoutParams btnLayoutParams = 
    new LinearLayout.LayoutParams(
        120,
        ViewGroup.LayoutParams.WRAP_CONTENT
        );
//set the LayoutParams
btnClick.setLayoutParams(btnLayoutParams);
<Button 
    android:layout_width="120px" 
    android:layout_height="wrap_content" 
    android:text="Click me !"
/>

//add controls to the layout
mainLayout.addView(txtInfo);
mainLayout.addView(btnClick);
defining the <TextView> and <Button> elements between <LinearLayout> and </LinearLayout>


//attach the layout
this.setContentView(mainLayout);
//attach the layout
this.setContentView(R.layout.main);

Other topics that are part of this Android tutorial are accessible through Android Tutorial – Overview and contents.

Other articles from the Android tutorial:

Like it? Then share this post or check the external adds. Sharing is the best way to appreciate the author.