Getting to Know the Android User Interface

What You Will Learn In This Chapter

  • The various ViewGroups you can use to layout your views
  • How to adapt and manage changes in screen orientation
  • How to create the UI programmatically
  • How to listen for UI notifications

In this chapter, you learn the details about creating user interface in Android, and how users interact with them. In addition, you will learn how to handle changes in screen orientation on your on your Android devices.

Understanding The Components Of A Screen

In previous chapters, you learned that the basic unit of an Android application is an activity. An activity displays the user interface of your application, which may contain widgets such as buttons, labels, textboxes, and so on. Typically, you define your UI using an XML file (e.g., the activity_main.xml file located in the res/layout folder of your project), which looks similar to the folowing:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="akraj.snow.test.MainActivity"
    tools:showIn="@layout/activity_main">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />
</LinearLayout>

During runtime, you load the XML UI in the onCreate() method handler in your Activity class, using the setContentView() method of the Activity class:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
}

During compilation, each element in the XML file is compiled into its equivalent Android GUI class, with attributes represented by methods. The Android system then creates the UI of the activity when it is loaded.

View and ViewGroups

An activity contains view and ViewGroups.
A View is a widget that has appearance on screen.
Examples of view are buttons, labels, and textboxes. A view derives from the base class android.view.View.
A ViewGroup (which is itself a special type of view) provides the layout in which you can order the appearance and sequence of views.
Examples of ViewGroups include LinearLayout and FrameLayout. A ViewGroup derives from the base class android.view.ViewGroup.
Android Supports The Following ViewGroups:

  • LinearLayout
  • AbsoluteLayout
  • TableLayout
  • RelativeLayout
  • FrameLayout
  • ScrollView

The following sections describe each of these ViewGroups in more detail. Note that in practice it is common to combine different types of layouts to create the UI you want.

LinearLayout

The LinearLayout arranges view in a single column or a single row. Child views can be arranged either vertically or horizontally.
In the activity_main.xml file, observe that the root element is <LinearLayout> and it has a <TextView> element contained within it. The <LinearLayout> element controls the order in which the views contained within it appear.
Each View and ViewGroup has a set of common attributes, some of which are described below

ATTRIBUTE DESCRIPTION
layout_width Specifies the width of the View or ViewGroup
layout_height Specifies the height of the View or ViewGroup
layout_marginTop Specifies extra space on the top of the View or ViewGroup
layout_marginBottom Specifies extra space on the bottom of the View or ViewGroup
layout_marginLeft Specifies extra space on the Left of the View or ViewGroup
layout_marginRight Specifies extra space on the Rigth of the View or ViewGroup
layout_gravity Specifies how child Views are positioned
layout_weight Specifies how much of the extra space in the layout should be
allocated to the View
layout_x Specifies the x-coordinate of the View or ViewGroup
layout_y Specifies the y-coordinate of the View or ViewGroup

NOTE: Some of these attributes are applicable only when a View is in a specific
ViewGroup. For example, the layout_weight and layout_gravity attributes
are applicable only when a View is in either a LinearLayout or a TableLayout.

For example, the width of the <TextView> element fills the entire width of its parent (which is the
screen in this case) using the fill_parent constant. Its height is indicated by the wrap_content
constant, which means that its height is the height of its content (in this case, the text contained
within it). If you don’t want the <TextView> view to occupy the entire row, you can set its layout_
width attribute to wrap_content, like this:

<TextView
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:text="@string/hello" />

UNITS OF MEASUREMENT
When specifying the size of an element on an Android UI, you should be aware of
the following units of measurement:
dp — Density-independent pixel. 1 dp is equivalent to one pixel on a 160 dpi
screen. This is the recommended unit of measurement when specifying the
dimension of views in your layout. The 160 dpi screen is the baseline density
assumed by Android. You can specify either “dp” or “dip” when referring to a
density-independent pixel.
sp — Scale-independent pixel. This is similar to dp and is recommended for
specifying font sizes.
pt — Point. A point is defined to be 1/72 of an inch, based on the physical
screen size.
px — Pixel. Corresponds to actual pixels on the screen. Using this unit is not
recommended, as your UI may not render correctly on devices with a different
screen resolution.

screen_size_1
 
This image shows the screen of the Nexus S. It has a 4-inch screen
(diagonally), with a screen width of 2.04 inches. Its resolution is
480 (width)  800 (height) pixels. With 480 pixels spread across
a width of 2.04 inches, the result is a pixel density of about 235
dots per inch (dpi).
As you can see from the figure, the pixel density of a screen varies
according to screen size and resolution.
Android defines and recognizes four screen densities:
Low density (ldpi) — 120 dpi
Medium density (mdpi) — 160 dpi
High density (hdpi) — 240 dpi
Extra High density (xhdpi) — 320 dpi
 
 
 

HOW TO CONVERT DP TO PX
The formula for converting dp to px (pixels) is as follows:
Actual pixels = dp * (dpi / 160), where dpi is either 120, 160, 240, or 320.

The preceding example also specifies that the orientation of the layout is vertical:

<LinearLayout
       xmlns:android="http://schemas.android.com/apk/res/android"
       android:layout_width="fill_parent"
       android:layout_height="fill_parent"
       android:orientation="vertical">

In LinearLayout, you can apply the layout_weight and layout_gravity attributes to views
contained within it, as the following example:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
    <Button
        android:layout_width="160dp"
        android:layout_height="wrap_content"
        android:text="Button"layout-2016-03-17-180207
        android:layout_gravity="left"
        android:layout_weight="1" />
    <Button
        android:layout_width="160dp"
        android:layout_height="wrap_content"
        android:text="Button"
        android:layout_gravity="center"
        android:layout_weight="2" />
    <Button
        android:layout_width="160dp"
        android:layout_height="wrap_content"
        android:text="Button"
        android:layout_gravity="right"
        android:layout_weight="3" />
</LinearLayout>

If you change the orientation of the LinearLayout to horizontal, you need to change the width of each view to 0 dp, and the views will be displayed as shown below:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="horizontal" >
    <Button
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Button"
        android:layout_gravity="left" layout-2016-03-17-181255
        android:layout_weight="1" />
    <Button
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Button"
        android:layout_gravity="center_horizontal"
        android:layout_weight="2" />
    <Button
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Button"
        android:layout_gravity="right"
        android:layout_weight="3" />
</LinearLayout>

AbsoluteLayout

A layout that lets you specify exact locations (x/y coordinates) of its children. Absolute layouts are less flexible and harder to maintain than other types of layouts without absolute positioning.

This class was deprecated in API level 3.
Use FrameLayout, RelativeLayout or a custom layout instead.

Table Layout

The TableLayout groups views into rows and columns. You use the <TableRow> element to designate
a row in the table. Each row can contain one or more views. Each view you place within a row forms
a cell. The width of each column is determined by the largest width of each cell in that column.

<TableLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <TableRow
        android:layout_width="match_parent"
        android:layout_height="match_parent">layout-2016-03-17-184002
        <TextView
            android:text="User Name:"
            android:width ="120dp"/>
        <EditText
            android:id="@+id/txtUserName"
        android:width="200dp" />
    </TableRow>
    <TableRow
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView
            android:text="Password:"
            android:width ="120dp"/>
        <EditText
            android:id="@+id/txtPassword"
            android:width="200dp" />
    </TableRow>
    <TableRow
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView />
        <CheckBox android:id="@+id/chkRememberPassword"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Remember Password"/>
    </TableRow>
    <TableRow
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <Button
            android:id="@+id/buttonSignIn"
            android:text="Log In" />
    </TableRow>
</TableLayout>

RelativeLayout

The RelativeLayout enables you to specify how child views are positioned relative to each other.

<RelativeLayout
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/verify_code_text"
        android:textSize="25dp"
        android:gravity="center"
        android:padding="10dp"/>
    <EditText
        android:layout_width="match_parent"layout-2016-03-17-185039
        android:layout_height="wrap_content"
        android:id="@+id/editVerifyCode"
        android:hint="Enter Your OTP"
        android:inputType="number"
        android:padding="20dp"
        android:layout_below="@+id/textView"/>
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Verify"
        android:id="@+id/btnVerifyCode"
        android:layout_below="@+id/editVerifyCode"
        android:padding="20dp"/>
</RelativeLayout>

FrameLayout

The FrameLayout is a placeholder on screen that you can use to display a single view. Views that you add to a FrameLayout are always anchored to the top left of the layout.

<FrameLayout
    xmlns:app="http://schemas.android.com/apk/res-auto"layout-2016-03-17-185647
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_launcher"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Click Me"/>
</FrameLayout>

ScrollView

A ScrollView is a special type of FrameLayout in that it enables users to scroll through a list of
views that occupy more space than the physical display. The ScrollView can contain only one child
view or ViewGroup, which normally is a LinearLayout.

NOTE: Do not use a ListView (discussed in ListView Chapter) together with the
ScrollView. The ListView is designed for showing a list of related information
and is optimized for dealing with large lists.

<ScrollView
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="New Button"
            android:id="@+id/button2" />
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="New Button"
            android:id="@+id/button3" />
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="New Button"
            android:id="@+id/button4" />
        <EditText
            android:layout_width="match_parent"layout-2016-03-17-190805
            android:layout_height="700dp"
            android:id="@+id/editText"/>
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="New Button"
            android:id="@+id/button5" />
        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="New Button"
            android:id="@+id/button6" />
    </LinearLayout>
</ScrollView>

If you load the preceding code on the Android emulator, you
will see something like Image-sv1
Because the EditText automatically gets the focus, it fills up the entire activity (as the height
was set to 700dp). To prevent it from getting the focus, add the following two attributes to the
<LinearLayout> element:

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:focusable="true"
    android:focusableInTouchMode="true">

Sometimes you may want the EditText to automatically get the focus, but you do not want the
soft input panel (keyboard) to appear automatically (which happens on a real device). To prevent
the keyboard from appearing, add the following attribute to the <activity> element in the
AndroidManifest.xml file:

<activity
    android:name=".MainActivity"
    android:label="@string/app_name"
    android:theme="@style/AppTheme"
    android:windowSoftInputMode="stateHidden">

 WHAT YOU LEARNED IN THIS CHAPTER

TOPIC KEY CONCEPTS
LinearLayout Arranges views in a single column or single row
AbsoluteLayout Enables you to specify the exact location of its children
TableLayout Groups views into rows and columns
RelativeLayout Enables you to specify how child views are positioned relative to
each other
FrameLayout A placeholder on screen that you can use to display a single view
ScrollView A special type of FrameLayout in that it enables users to scroll
through a list of views that occupy more space than the physical
display allows
Unit of Measure Use dp for specifying the dimension of views and sp for font size.

About the author

Akshay Raj

View all posts