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.

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"
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"
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">
<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"
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"
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"
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. |