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.
UseFrameLayout
,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 scrollthrough 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. |