Android UI Layouts and Controls - CodeProject
Android UI Layouts and Controls - CodeProject
Take out your Android phone, pick an app, and launch it, what comes into sight? The User Interface! The user interface or UI is the only
thing and everything that the user can see and interact with your app. Nowadays, a typical UI is graphical based, comprising UI controls
like textbox, button, checkbox, radio button, datepicker, and many more, and is presented in a variety of layouts. Naturally, we shall
start with the UI.
I have set the scope of this article to cover the more common and more important UI layouts and UI controls as follows:
UI layouts
LinearLayout
RelativeLayout
TableLayout
FrameLayout
RadioGroup
ListView
GridView
UI Controls
Button
TextView
EditText
CheckBox
RadioButton
ToggleButton
Spinner
AutoCompleteTextView
Progress Bar
Pickers
ImageView
The View class is the base class of all graphical UI objects collectively called UI controls or Widgets like Button, TextView, EditText,
CheckBox, RadioButton, ImageView, Spinner, and many more, that you see on your Android device's screen. Every visible UI control
occupies an area on your screen and provides the point of interaction between you and the app through events like clicking, touching,
and keying. You may liken the various View objects as household items like furniture and appliances in a house.
The ViewGroup class, on the other hand, is the invisible organizer that provides a variety of UI layouts to position the various View
objects on your screen. For example, you may arrange the UI controls one above another in a linear fashion using LinearLayout layout,
or relative to each other using RelativeLayout layout. In fact, ViewGroup class is also derived from View class, in other words, you can
have a ViewGroup object ﴾child﴿ nested in another ViewGroup object ﴾parent﴿, and each can take on different layouts. You may liken the
ViewGroup's layouts as the layout of rooms and space in the house.
First, the conceptual plan. The concepturalized UI in Figure 1 consists of a number of View objects organized into two ViewGroups ‐ one
ViewGroup is embedded in another. It is like an interior plan of a house that has one space nested in another, each may layout their own
household items in a different way.
Figure 1: UI in Abstract Form
To realize the plan, we have decided that the overall UI layout should be RelativeLayout and the nested layout LinearLayout. We have
also decided on the actual UI controls, TextView, EditText, CheckBox, and so on, to use for each View object in the respective layouts. The
resulted concrete plan is shown in Figure 2. It is like deciding on the type of furniture and appliances and their positions in each space.
Figure 2: UI in Concrete Form
When the plan is implemented, you can see the UI on an Android Virtual Device ﴾AVD﴿ as shown in Figure 3.
Figure 3: UI in Implementation
You will need an AVD or a physical device to test your app as you work on it. I have used the following AVD configuration based on
Nexus 4 as shown in Figure 4. Specially take note to uncheck the Keyboard option so that a soft keyboard will be available for use in the
AVD. You are advised to use the same configuration for your AVD so that we can travel on the same path most of the time. You may
refer to my article on Setting Up Your Android Development Environment to learn about creating an AVD.
Figure 4: AVD Configuration
Android will build a new project with a default Activity called "MainActivity" and a default layout called "activity_main.xml" ﴾Figure 9﴿.
Figure 9: New Project Launched
LinearLayout
We will kick start the learning journey of building Android UIs with a GridView layout called LinearLayout.
Open the "activity_main.xml" which is the layout file for MainActivity's UI, follow these steps diligently and you will pick up valuable
learning points along the way:
1. Switch to Text view ﴾bottom left of Figure 9﴿, then change the default RelativeLayout to LinearLayout and delete the default
TextView block from the XML page.
2. Switch to Design view, you should now see the LinearLayout layout appear under the Device Screen node of the Component
Tree pane. Highlight this LinearLayout node, then locate the orientation property in the Properties pane below the Component
Tree pane, click and set it to horizontal.
3. Drag and drop a Button control from the Widgets palette onto the virtual device's screen. The Button control is also appeared
under the Device Screen node of the Component Tree pane. ﴾Figure 12﴿
4. Continue to add one more Button controls from the Widgets palette onto the virtual device's screen. The two buttons will be
placed side by side horizontally ﴾Figure 13﴿.
Figure 13: LinearLayout with two Button Controls
Learning Point 1:
The state ﴾color, size, margin, padding, weight, etc﴿ of each UI component can be altered through their properties.
You can see a complete list of properties pertaining to a particular UI component on the Properties pane ﴾bottom
right﴿ in Android Studio when you click on that component. That makes Android Studio a great tool to learn about the
various UI components!
5. background
As the LinearLayout is not visible, let's change its background property to a new color as shown in Figure 14. ﴾Make sure that
you have selected the LinearLayout (Horizontal) in the Component Tree.﴿ You will see that the whole screen is rendered with the
new color, in other words, the LinearLayout covers the whole screen. Why is that so? The answer lies with the layout:width and
layout:height properties of the LinearLayout. they both take the value of "match_parent" which means "as big as the parent
screen".
Figure 14: Change background
Up to now, you have created the initial UI by merely dragging and dropping in the Design view. Aren't you curious what is
happening behind the scene. Android Studio has translated all those you have done in the Design view into an XML file, i.e.
"activity_main.xml". Switch over to the Text view, you will see the XML code as shown in Figure 15.
Figure 15: activity_main.xml
Note the following attributes in the <LinearLayout> node that correspond to their respective properties in the Properties pane in
the Design view.
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffb9d7ff"
gravity
6. Keeping the LinearLayout (Horizontal) selected, expand the gravity property and check the checkboxes for the right and center
values respectively. This will position the two buttons in the right‐center of the whole screen. Try out other checkbox values
﴾individually and then collectively﴿ to see the effects.
Figure 16: Playing with gravity
Learning Point 2:
The gravity property of the LinearLayout is used to determine the positioning of its child Views. It can take one or
more constant values ﴾as shown in Figure 15﴿ separated by '|', such as "center|right".
The following code would has been added as attributes to the <LinearLayout> node in the "activity_main.xml". Switch to Text
view and look for it.
android:gravity="center|right"
Once you are done playing with the gravity property, undo any changes and recover the screen to the state as shown in Figure
14.
7. padding
Back to the screen in Figure 14, keeping the LinearLayout (Horizontal) selected, expand the padding property and enter 50dp
and 70dp to the left and top parameters respectively. This will shift the two buttons rightwards and downwards by the stipulated
amounts as shown in Figure 16. Try out other parameters with different values ﴾individually and then collectively﴿ to see the
effects.
Learning Point 3:
The padding property of the LinearLayout is used to specify the internal space between its border and its nearest child
Views. You can specify paddings for the left, top, right, and bottom sides of the layout independently.
The following code would have been added as attributes to the <LinearLayout> node in the "activity_main.xml". Switch to Text
view and look for them.
android:paddingLeft="50dp"
android:paddingTop="70dp"
Once you are done playing with the padding property, undo any changes and recover the screen to the state as shown in Figure
14.
8. layout:width, layout:height
Back to the screen in Figure 13, keeping the LinearLayout (Horizontal) selected, look for layout:width and layout:height
properties in the Properties pane, change their value to "wrap_content". What did you see? The LinearLayout has been adjusted
to just fitting the two buttons as shown in Figure 18.
Learning Point 4:
The layout:width and layout:height properties of the LinearLayout allow you to set the width and height of the
layout. You can specify width and height with exact measurements in dp ﴾density‐independent pixels﴿ but more often
than not, you will use one of these constants to set the width or height, namely "fill_parent", "match_parent", or
"wrap_content". Note that fill_parent has been deprecated starting from API Level 8 and is replaced by match_parent.
The match_parent constant will stretch the layout to fit its parent GridView entirely ﴾minus the padding, if any﴿, e.g.
the screen, whereas the wrap_content will size the layout to fit its entire child Views.
The android:layout_width and android:layout_height attributes in the <LinearLayout> node in the "activity_main.xml" would
have been modified as shown. Switch to Text view and look for them.
android:layout_width="wrap_content"
android:layout_height="wrap_content"
Once you are done here, undo any changes and recover the screen to the state as shown in Figure 14.
9. orientation
Back to the screen in Figure 14, keeping the LinearLayout (Horizontal) selected, look for orientation property in the Properties
pane, change its value to "vertical". What did you see? The two buttons will now be stacked up vertically. You will also notice
that the LinearLayout (Horizontal) has been changed to LinearLayout (Vertical) in the Component Tree pane ﴾Figure 19﴿.
Learning Point 5:
The orientation property is privy to LinearLayout that makes it distinct from other GridView layouts. It takes the value
of either "horizontal" or "vertical". It controls how the child Views are to be arranged in LinearLayout. Horizontal
orientation will arrange them in one horizontal row of multiple columns, whereas vertical orientation in one vertical
column of multiple rows. The default orientation is "horizontal".
The android:orientation attribute in the <LinearLayout> node in the "activity_main.xml" would have been modified as shown.
Switch to Text view and look for it.
android:orientation="vertical"
10. margin
Switch to the Text view, then add a line of code as shown in Figure 20.
While you type along, Android Studio will offer you a dropdownlist of suggested words to help you in auto‐completing your
code as shown in Figures 21 and 22. ﴾In order to let Android Studio help you, try to type a bit slower; when the matched word
appears, use arrow key to navigate to it and tab key to select it.﴿
You have just added a margin of 16dp outside the border surrounding the LinearLayout, the value of which is referenced from
the "activity_vertical_margin" element in "dimens.xml" as shown in Figure 24. To refer to any resources in XML, the syntax is
@resourceType/resourceName
.
Figure 24: dimens.xml
Learning Point 6:
The "android:layout_margin" property sets the all‐round margin for the layout which is the external space between
the border of the current Views ﴾e.g. layout﴿ and the nearest external Views. You can also specify individual margins for
bottom, left, right, and top, as shown in Figure 25.
Summary:
LinearLayout is a ViewGroup object that arranges all child Views one by one in either horizontal or vertical direction as
dictated by its distinct property called orientation. All the child Views of a LinearLayout are always placed linearly one after
another. A horizontal orientation will arrange them in only one row of multiple columns, whereas vertical orientation in one
column of multiple rows. The default orientation is "horizontal".
LinearLayout is the simplest and straight forward layout model of the GridView objects. But it has the least flexibility in that it only
allows either horizontal or vertical layout. Although additional layouts can be achieved using nested LinearLayouts, i.e. one LinearLayouts
within another LinearLayouts, it is not advisable as that will complicate your design and degrade the performance. If you find yourself
using several nested LinearLayouts, it is time to consider a single RelativeLayout.
RelativeLayout
In the current project, create a new Activity called "RelativeLayout" to practice on another GridView object ‐ RelativeLayout.
1. Follow the trail as shown from Figures 26 to 27 to create the new Activity.
Figure 26: New Blank Activity
2. The "activity_relative_layout.xml" file created by the blank activity template comes with a RelativeLayout and a TextView
that says "Hello world!". ﴾Figure 28﴿
3. In the Design view, drag and drop a Button control from the Widgets Palette ﴾Figures 29 and 30﴿. As you are dragging over the
screen, a dialog box pops up updating you with information about the margins to the right of and below <generated> ﴾Figure
29﴿. The <generated> refers to the "Hello world!" TextView control. In other words, it is showing you the relative position of the
Button control to the TextView control.
You will notice that the TextView has been assigned a new android:id attribute as shown:
android:id="@+id/textView2"
and the new <Button> node has the following attributes referencing the "Hello world!" TextView through its android:id attribute.
These attributes determine the position of this button in relation to the TextView.
android:layout_below="@+id/textView2"
android:layout_toRightOf="@+id/textView2"
android:layout_toEndOf="@+id/textView2"
android:layout_marginLeft="23dp"
android:layout_marginTop="48dp"
5. In the Design view, drag and drop a second Button control from the Widgets Palette ﴾Figures 32 and 33﴿ towards the bottom
right of the screen. When the button is nearing the edge of the screen, a dialog box pops up updating you with information
about the respective margins for aligning to the right and bottom of the parent ViewGroup, i.e. the RelativeLayout ﴾Figure 32﴿.
Figure 32: Dragging a Second Button control
You will notice that a second <Button> node has been added. Pay attention to these attributes which determine the position of
this second button in relation to its parent GridView, i.e. the RelativeLayout.
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_marginRight="68dp"
android:layout_marginBottom="130dp"
Summary:
In RelativeLayout model, the positioning of its child Views is specified in either of the following ways:
android:layout_below="@+id/viewName"
For example,
android:layout_below="@+id/textView2"
While the RelativeLayout model provides the maximum flexibility for layout View objects on the UI, it requires more time to plan and
design. For UI layout that simply requires a 2‐D structure, use TableLayout.
TableLayout
In the current project, create a new Activity called "TableLayout" to practice on another GridView object ‐ TableLayout. Follow these
steps:
1. Open the "activity_table_layout.xml" in the Design view, then delete the default RelativeLayout and TextView in the Component
Tree pane.
2. Drag and drop a TableLayout layout from the Layouts palette onto the virtual device's screen.
3. Drag and drop a Large Text widget ﴾which is actually a TextView View﴿ onto the virtual device's screen ﴾Figure 35﴿ As you are
dragging it across the screen, a 2‐D grid appears and a dialog box pops up showing the current position in terms of index
numbers of row and column. ﴾The index number starts from zero.﴿ Drop the TextView at ﴾row 1, column 1﴿ ﴾Figure 36﴿.
4. Let's change the default text to something else, say "Sign In". Follow the trail in Figure 37. Double‐click on the TextView to bring
out a dialog box. In the dialog box, click on the button that marked "..." beside the" text:" textbox to bring out the Resources
window, then click on the New Resource button on the bottom left corner of this window and select New String Value....
Figure 37: Add new Resource
A new window opens for you to create a new string resource, enter the following values accordingly and hit OK ﴾Figure 38﴿.
Figure 38: Enter new Resource Values
The new string resource has been added to the "strings.xml". Check it out. ﴾Figure 39﴿.
If you look into the "activity_table_layout.xml" file ﴾Figure 40﴿, the android:text attribute of the TextView is now pointing to the
new string resource through this syntax @string/sign_in.
Figure 40: TextView points to the new String Resource
Learning Point 7:
When you need a new text string, do not hard code it. Instead, you should create a new string resource that takes that
text string as value. You will then reference this string resource in the XML or in code whenever you need to use text
string on any UIs. That is reusability and maintainability at its best. You should always visit Figures 37 to 41 for
reference.
5. You will continue to build the TableLayout UI on your own. The completed UI should look like that in Figure 42. Beside the Large
Text widget for the "Sign In..." label,
Drag and drop two Medium Text Widgets onto the UI and change their text properties to "Email" and "Password"
respectively. ﴾Follow the steps from Figures 37 to 40.﴿
Drag and drop an E‐mail and a Password Text Fields ﴾which are actually EditText Views﴿ onto the UI and insert the
words "Email" and "Password" into their respective hint properties. You should use the two string resources that you
have created above. How? In the Properties pane, click in the text field beside the hint property, a button that marked "..."
will appear, then click on it to bring out the Resources window ﴾similar to what you see in Figure 37﴿. This time, you
should see the two strings you created above for "Email" and "Password" being listed, just use them. That is the beauty
of reusability!
Note:
When set, the value of the hint property will be displayed in the EditText text field when the text field is empty.
Lastly, drag a Button Widget onto the UI and change its text property to "Let me in!".
The 2‐D grid in Figure 44 should help you in visualizing the positioning of the various View controls in the TableLayout ﴾Figure
43﴿.
To understand how TableLayout organizes the child Views, let's examine this code snippet from the "activity_table_layout.xml"
﴾Figure 44﴿.
Figure 44: Snippet of activity_table_layout.xml
Learning Point 8:
Each row in the TableLayout is appended as a <TableRow> node which contains the child Views. The order of the<TableRow>
node is important. When this XML is referenced, the<TableRow> nodes will be traversed from top to bottom to determine
which one is on top and which below. In other words, the order of the <TableRow> node in the XML file will translate literally
into its row index in the TableLayout, i.e. the first one from the top of the file will appear as first row in the TableLayout, second
one second row, and so on. On the other hand, the position of a child View in a particular row is indicated by the
android:layout_column attribute:
for example,
android:layout_column="1"
which indicates the second column in a row.
In addition, a child View may occupy more than one column using android:layout_span attribute. Ultimately, the total column
count of a TableLayout is determined by the row that has the most number of column.
FrameLayout, ImageView
A FrameLayout is a ViewGroup that divides the screen into blocks of area each of which is supposed to holds a single child View. You
may place multiple child Views inside a single block, then the latter ones will overlay the preceding ones. The android:layout_gravity
attribute of the child View will dictate which block it will go into. Let's build a page using FrameLayout as the layout model that contains
an ImageView overlaid with a TextView.
1. Create a new Activity called "FrameLayout", then follow these steps to create a UI that look like that in Figure 45.
3. Run it on an AVD and you should see this as shown in Figure 47.
Figure 47: Text Selection in EditText
Button
So far, we have explored four GridView layouts ‐ LinearLayout, RelativeLayout, TableLayout, and FrameLayout. Aren't you anxious to taste
the fruit of your labor? You wish is granted. However, that cannot be achieved without the help of the Button control. So we will digress
from the layout models for the time being and move over to look at the various UI controls. The first stop is, of course, the Button.
A Button control provides an area on the UI where a user can touch to initiate an action. You will create a number of buttons on the
"MainActivity" so that we can navigate to the various layout pages that you have created so far.
1. weight
Open the "activity_main.xml" in the Text view, then add the following code to the first and second Button nodes respectively.
android:layout_weight="1.0"
and
android:layout_weight="2.0"
The resulting code should look like that in Figure 48 and the screen in Figure 49:
Figure 48: android:layout_weight
Figure 49: The Outcome
What has happened? The first button has been given one‐third of its parent GridView whereas the second button the remaining
two‐third. This is caused by the values of 1.0 and 2.0 being assigned to the android:layout_weight of the respective buttons.
These values are relative and represent the proportion of the GridView that they will occupy. The same effect can be achieved by
changing the values to 1.2 and 2.4. Try it!
Learning Point 9:
The android:layout_weight property sets the proportion of width or height ﴾depending on orientation﴿ that a View
will occupy with relation to others in the LinearLayout. It will affect the width of Views in horizontal orientation and
height in vertical orientation.
2. Remove the android:android_weight attribute from both buttons, add four more Button controls, set the android:layout_width
attribute of all the five buttons to "match_parent", and change their android:text attribute to some newly created string resource.
The final UI should look like that in Figure 50. ﴾You have done all these before, so take it as a revision. ﴿
Figure 50: The new Look
It is more common for a Button control to be rendered with a text caption, but it can also be rendered with an icon or both.
Open "activity_main.xml" in the Text view, follow the trail from Figures 52 to 54 to add an icon on top of the text caption of the
LinearLayout button. We will use the default icon called "ic_launcher" provided by Android Studio.
There you are, the ic_launcher icon has been added on top of the LinearLayout button ﴾Figure 55﴿.
Figure 55: Added drawable to Button
4. Button Event
We will now add interactivity to the RelativeLayout button so that when a user touches it, the RelativeLayout page ﴾Figure 33﴿
should be displayed. Let's do it:
Open *activity_main.xml* in the Text view, add the Android:onClick attribute to the <Button> node that renders the
RelativeLayout button and assign it a the name of the method ﴾event handler﴿ that will take care of the touch event. For
me, I named it "getRelativeLayoutPage". ﴾Figure 56﴿
Figure 56: Add Android:onClick
Open the *MainActivity.java* which is the Activity that hosts the layout in "activity_main.xml". The setContentView
method inside the onCreate method will bind the "activity_main.xml" layout to the *MainActivity.java*. Add one method
called "getRelativeLayoutPage" in the code as shown in Figure 56. If it complains of some error, this is because the View
class is contained inside the android.view.View package which is not yet included. Fret not! Just click on it once
followed by Alt + Enter and this problem will go away instantly. Thanks to Android Studio.
Add the highlighted code into the getRelativeLayoutPage method ﴾Figure 58﴿. If it complains of another error, this is
because the Intent class is contained inside the android.content.Intent package which is not yet included. You should
know to resolve it this time.
*An Intent object is the Android's way of describing a message stating its "intention" to do something, i.e. to navigate to
RelativeLayout. This Intent object is then passed to the startActivity method to carry out the intended action.
Launch your app on an AVD or a physical Android device, it should start with the MainActivity page, touching the
RelativeLayout button should bring you to the RelativeLayout page. Well done! you will do the same for the TableLayout
and FrameLayout buttons. Your completed app should work as shown in Figure 58.
Figure 59: Button Action!
5. Custom Style
We can customize the background of the Button Control to represent the three states of a button ‐ pressed, focused, and
default ﴾neither pressed nor focused﴿ . Let's do it:
Download the "android_icons.zip" to your computer and unzip to get three images, namely "ic_action_search",
"ic_action_send", "ic_action_refresh". ﴾These images are parts of the Action Bar Icon Pack from Android Developers.﴿
Follow the trail from Figures 60 to 63 to import these images to the drawable resource folders.
Create a sub directory called "drawable" under the res directory ﴾Figures 64 and 65﴿.
Add a drawable resource file called "button_custom" inside the drawable directory ﴾Figures 66 and 67﴿.
The newly created drawable resource file will be saved as *button_custom.xml*. Your drawables should now contain
these resources as shown in Figure 68.
Figure 68: All the drawable Resources
Open the *button_custom.xml* and add the following code as shown in Figure 69.
The "button_custom.xml" binds the three images to the respective states ‐ pressed, focused, and default ﴾neither pressed
nor focused﴿.
Note:
The order of the <item> elements is important. When this drawable is referenced, the <item> elements will be
traversed from top to bottom to determine which one is applicable for the current button state. The default
drawable must be placed last as it is only applied when both android:state_pressed and android:state_focused
have been evaluated as false.
Open the *activity_relative_layout.xml*, in the <Button> node for the first button, delete the android:text attribute, then
add the highlighted code as shown in Figure 69. The "button_custom.xml" is now applied to the background of the first
button control.
Launch your app on an AVD or a physical Android device, navigate to the RelativeLayout page. The background of the
first button should now appear as . Touching it will cause it to change to . When the button got focused, its
TextView
As the name suggested, TextView is a View object that simply displays text to the user. By default it is not editable. It is commonly used
to display heading, static textual information, and labels to other View objects.
Let's re‐visit "activity_table_layout.xml" and take a closer look at one of its TextView object for "Sign In...".
1. Open the "activity_table_layout.xml" in Text view. Android Studio called this TextView "Large Text" in the Palette as its
android:textAppearance attribute has been assigned the text size of "?android:attr/textAppearanceLarge" ﴾Figure 72﴿ which
is equal to 22sp. Similarly, there the two other TextViews being called "Medium Text" and "Small Text" by Android Studio. Their
android:textAppearance attributes have been assigned the text sizes of "?android:attr/textAppearanceMedium" and "?
android:attr/textAppearanceSmall" respectively. The text size for the former is 18sp whereas the later 14sp.
Figure 72: TextView
In the first highlighted line, you have made the TextView selectable by setting its android:textIsSelectable attribute to "true", it
allow users to make selection gesture on its content which in turn triggers the copy and paste function of the Android system.
In the second highlighted line, you have enabled the text to change color when it is touched by setting the
android:textColorHighlight to some color value. When it is set to "true"
Try it up on an AVD or a physical device! Catch a glimpse of that running on my AVD ﴾Figure 74﴿. It works!
Still at the "activity_table_layout.xml", this time we will take a closer look at one of its EditText object for "Email".
1. Open the "activity_table_layout.xml" in Text view. Android Studio called this EditText "E‐mail" in the Palette as its
android:inputType attribute has been assigned the value of "textEmailAddress" ﴾Figure 75﴿.
This is an innovative way of telling the Android system that it is expecting an email input. So what is the big deal? Let run it on
the AVD, and place your cursor inside this Email text field. A soft keyboard would appear like that in Figure 76.
Figure 76: Email Input Type Keyboard
Keep staring at the soft keyboard ﴾I mean it﴿ while placing the cursor on the Password text field. Notice any changes on the
keyboard, yes, the "@" key has been replaced with comma ﴾Figure 77﴿
android:inputType="number"
and re‐launch it on the AVD, this time you will get a basic number keypad! ﴾Figure 78﴿. ﴾Remember to undo your doing after the
fun.﴿
Figure 78: Number Pad
We have seen that the android:inputType attribute of EditText can be used to indicate the type of text to be entered
to the Android system which in turn provides the matching soft keyboard for use. Some of the more common input
type values for this type of purpose are:
"text" which is the default and calls for a normal text keyboard.
"textEmailAddress" which calls for normal text keyboard that includes the @ key.
"number" which calls for a basic number keypad.
"phone" which calls for a phone dial pad.
In addition, the android:inputType attribute can also define other keyboard behaviors, such as to mask password text,
allow multi‐line input, or to capitalize a new sentence, and many more. Some of these input types are:
"textPassword" which calls for normal text keyboard, but mask the text entered.
"textMultiLine" which calls for normal text keyboard that allows users to enter long strings of text that include
line breaks.
"textCapSentence" which calls for normal text keyboard that capitalizes the first alphabet of each new
sentence.
"textAutoCorrect" which calls for normal text keyboard that provides helping words to correct common
spelling errors.
You can specify multiple input types to the android:inputType attribute using the "|" separator. Like this
android:inputType="textCapSentence|textAutoCorrect"
2. The EditText come with the selection feature that enables you to cut, copy, and paste. Try it out on an AVD or a physical device, it
work like a charm! ﴾Figure 79﴿.
More UI Controls
We have already dealt with these UI controls, namely Button, ImageView, TextView, and EditText. We will continue to explore many more
UI controls ‐ CheckBox, RadioButton and RadioGroup, ToggleButton , Spinner, AutoCompleteTextView, Progress Bar, and Pickers.
CheckBox
A CheckBox allows users to select or unselect an option. We use a set of checkboxes when we want to allow uses to select multiple
options that are mutually exclusive. Follow these steps to construct a list of checkboxes:
1. Open the "activity_linear_layout.xml" in Design view, drag and drop a new LinearLayout from the Palette onto the first
LinearLayout and set its orientation to "horizontal" and its layout_height to "match_parent" so that you can drag and drop
checkboxes inside. In this way, you have nested a LinearLayout inside another LinearLayout ﴾Figure 80﴿. You will build your
CheckBoxes inside this inner LinearLayout.
2. Drag and drop a CheckBox widget onto the inner LinearLayout. Rename the CheckBox's text to "Jogging". Remember that you
should create a string resource which you will referenced instead of hard coding it ﴾81﴿. ﴾Remember Learning Point 7﴿
The "activity_linear_layout.xml" and the UI should look like those in Figure 82.
Figure 82: The CheckBox in XML
3. Pay attention to these three attributes: android:id, android:checked, and android:onClick in each <CheckBox> node. We will
discuss them next.
4. Open the "activity_linear_layout.xml" in the Text view, change all the android:id values given by default by Android Studio to
something more descriptive. For example, instead of "@+id/checkBox" or "@+id/checkBox2", use "@+id/chkJogging" for
"Jogging" checkbox, and "@+id/chkSwimming" for "Swimming" checkbox, and so on. The "chk" prefix is short for checkbox. In
fact, you should do the same to all the ids of all elements.
One important point that I must stress is that you should change all the android:id values given by default by Android
Studio to something more descriptive. For example, instead of "@+id/checkBox" or "@+id/checkBox2", use
"@+id/chkJogging" for "Jogging" checkbox, and "@+id/chkSwimming" for "Swimming" checkbox, and so on. The
"chk" prefix is short for checkbox.
5. The android:checked attribute takes a boolean value of either true or false, true for checked whereas false unchecked. You can
use this attribute to set the initial check state of a CheckBox.
6. Next come to the Android:onClick attribute. We have discussed this already at Button Event in Figure 55. The Android:onClick
here has been assigned an event handler ﴾method﴿ called "onCheckboxClicked" in its Activity class which is the
"LinearLayout.java".
7. Repeat steps 2 to 6 to create a few more checkboxes. After this, set the layout_height of the inner LinearLayout to
"wrap_content". The completed UI should look like that in Figure 83.
Figure 83: CheckBoxes
8. You will add a method to handle the check event in "LinearLayout.java". ﴾If you encounter any error, refer to Figure 55 for help.﴿
Open the "LinearLayout.java" that hosts the "activity_linear_layout.xml", add the "onCheckboxClicked" method like this ﴾Figure
84﴿;
Figure 84: Add Event Handler
In Android, the Java code for locating a particular View object ﴾UI element﴿ is,
For example,
You may start to realize the good intention for using descriptive name for id ﴾Learning Point 11﴿ ‐ you know which View object
you are referring by simply reading the id, you cannot do this with id that read "checkbox2" or "checkbox3", can you?
So what does the method do? Well, whenever you check or uncheck any checkbox, it will echo the names of all the checkboxes
that are currently being checked via the Toast object. However, before you can test run it, it has to be navigated from the
"MainActivity" page. Let's use the first button in the "MainActivity" page that reads "LinearLayout" to do this.
9. What are you waiting for, you have done similar exercises before, remember Figure 56.
android:onClick="getLinearLayoutPage"
Add this method to the "MainActivity.java":
and it is done!
10. Now, you can try it on an AVD or your Android device. It work like this ﴾Figure 85﴿.
RadioButton, RadioGroup
Like the CheckBox, a RadioButton offers users an option to choose. However, the radio button does not live alone. It belongs to a
group of radio buttons whereby only one of them can be selected at any one time, such as the selection of gender. How to ensure that,
the answer is "grouping them together in a RadioGroup". In this way, the system ensures that only one radio button can be selected at
a time.
1. Open the "activity_linear_layout.xml" in Design view, drag a RadioGroup from the Containers section of the Palette and placed it
below the LinearLayout for checkboxes ﴾Make sure you have set the layout_height of this LinearLayout to "wrap_content"﴿. In the
Properties pane for this RadioGroup, set its orientation to "horizontal" and its layout_height and layout_weight to "match_parent"
so that you can drag and drop radio buttons inside. RadioGroup is a subclass of LinearLayout that has a vertical orientation by
default, but it is for the purpose of grouping a set of radio buttons. Next, drag and drop two Radio Buttons inside the
RadioGroup, one each for "Female" and "Male" respectively. Once this is done, change the layout_height to "wrap_content". It
should look like that in Figure 86.
2. Open the "activity_linear_layout.xml" in Text view, assigned "onRadioButtonClicked" to the Android:onClick attribute. The
completed XML for the radio buttons should look like that in Figure 87.
3. Add the "onRadioButtonClicked" method to the "LinearLayout.java" like this ﴾Figure 88﴿;
Figure 88: Event Handler for Radio Buttons
Tip:
Use RadioButton when you want to show all the options to the users. Otherwise, you should consider using Spinner instead.
ToggleButton
A ToggleButton is an on/off switch. It can be used in turning on and off features like vibration mode, silent mode, WiFi connection, and
so on. We will add a ToggleButton to the LinearLayout page to toggle WiFi connection.
1. Open the "activity_linear_layout.xml" in Design view, drag a ToggleButton widget from the Palette and placed it below the
RadioGroup. Set its textOn and textOff properties to "WiFi On" and "WiFi Off" respectively ﴾Figure 90﴿
2. Open the "activity_linear_layout.xml" in Text view, assigned "onToggleClicked" to the Android:onClick attribute. The completed
XML for the toggle button should look like that in Figure 91.
3. Add the "onToggleClicked" method to the "LinearLayout.java" like this ﴾Figure 92﴿;
Figure 92: Event Handler for ToggleButton
4. Add the following permissions to the "AndroidManifest.xml" ﴾Figure 93﴿ to allow your app to access and change the device's WiFi
state while keeping the processor from sleeping or screen from dimming.
5. You have to use a real device to test it. This is the screenshot from my device in landscape orientation ﴾Figure 94﴿.
1. In the "strings.xml", add a string array called "zodiac" as show in Figure 95. This will be the data source for binding to your
spinner.
2. Open the "activity_linear_layout.xml" in Design view, drag a Spinner widget from the Palette and placed it below the
ToggleButton ﴾Figure 96﴿.
3. Open the "activity_linear_layout.xml" in Text view, change the default value of android:id accordingly as shown in Figure 97.
Figure 97: Spinner in XML
4. In the "LinearLayout.java", create an ArrayAdapter and attach it to the spinner as shown in Figure 98.
In the method, an ArrayAdapter, a subclass of Adapter class, is being used to bridge the data source, i.e. the string array
resource called "zodiac" ﴾Figure 94﴿ referenced to in code via "R.array.zodiac", and the View, i.e. the Spinner. ArrayAdapter is also
responsible for making a TextView for each item in the data source.
6. In order to capture the item selected from the spinner for further processing, you have to attach a "OnItemSelectedListener" to
it. Follow these steps:
// import android.widget.AdapterView;
public class LinearLayout extends Activity implements AdapterView.OnItemSelectedListener {
// ... other code ...
}
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String selectedItem = parent.getItemAtPosition(position).toString();
Toast.makeText(parent.getContext(), selectedItem, Toast.LENGTH_LONG).show();
}
7. Run it on the AVD, select an item from the spinner ﴾Figure 101﴿, and it should echo the name of the zodiac selected ﴾Figure 102﴿.
Figure 101: Select an "Leo"
Figure 102: Echo "Leo"
AutoCompleteTextView
When you are typing on a Google search box, you will get a list of suggested words appearing in a dropdownlist. This is auto‐complete.
The Android framework provides this similar feature using the AutoCompleteTextView. The AutoCompleteTextView is a View that is
similar to EditText, with the added capability of showing a list of suggested words from some data source automatically while the user is
typing. You will construct a AutoCompleteTextView that draws the suggested words from the list of zodiac names that we used in the
Spinner exercise.
1. Open the "activity_linear_layout.xml" in Design view, drag an AutoCompleteTextView widget ﴾under the Expert section of the
Palette﴿ and placed it below the Spinner ﴾Figure 103﴿.
Figure 103: activity_linear_layout.xml
2. In the "LinearLayout.java", create an ArrayAdapter and attach it to the spinner as shown in Figure 104.
3. Launch it on an AVD, type in a letter and watch the AutoCompleteTextView in action ﴾Figure 105﴿
Figure 105: AutoCompleteTextView at work!
Progress Bar
It is a common practice to show users a progress bar on their screen when they are uploading or downloading lengthy stuff from the
Internet. In Android, the progress bar is implemented through a ProgressDialog class which is actually a UI by itself. You will create a
progress bar on the "RelativeLayout" page and get it to simulate a task in progress upon a button click.
1. Open the "activity_relative_layout.xml" in Text view, change the android:text attribute and add an android:onClick attribute to the
<New Button> node as shown:
android:text="Show Progress..."
android:onClick="showProgress"
2. In the "RelativeLayout.java", add the showProgress method as shown in Figure 106. This method will be called when the "Show
Progress..." button is clicked. The code will instantiate a ProgressDialog object and set some of its properties like setMessage and
setProgressStyle. This ProgressDialog object will run in a separate thread so that it does not block the main UI thread.
Figure 106: showProgress method
3. Launch it on an AVD, navigate to RelativeLayout page, click on the "Show Progress..." button, and watch the progress bar in
action as shown in Figure 107.
Figure 107: Progress Bar at work!
1. Create a new Activity called "DateTimePickers", leave the default RelativeLayout as it is, but remove the default TextView. drag
and drop a DatePicker and a TimePicker from the Palette to the screen ﴾Figure 108﴿.
Figure 108: The Picky Duo
2. Open the "activity_date_time_pickers.xml", you see the XML code as shown in Figure 109. Note the android:onClick attributes
for the DatePicker and TimePicker.
Figure 109: activity_date_time_pickers.xml
3. Open the "DateTimePickers.java" that hosts the "activity_date_time_pickers.xml", insert the highlight code as shown in Figure 110.
The getDate and getTime methods will be invoked to echo the date or time selected on the screen whenever a user click on the
respective controls.
Figure 110: Methods to Handle Click Events
4. Once again, before you can test run it, it has to be navigated from the "MainActivity" page. Let's set up the "Pickers" button in
the "MainActivity" page for this purpose.
android:onClick="getDateTimePickers"
and it is done!
5. Run it, pick a date or time, then click on either of them. See it for yourself in Figure 111.
Figure 111: Pickers at work!
ListView
A ListView is a ViewGroup that displays a list of scrollable items from a data source via an Adapter. An Adapter acts as the middle man
to pull rows of data from a data source such as an array or database, and to convert each row of data into a View which is then inserted
into the ListView. The view in each row can be different and can be as complicated as you want ﴾Figure 112﴿. You will construct a ListView
in your app to display the list of zodiac names that we used in the Spinner exercise.
Figure 112: Adapter Explained (Click image to watch the Video)
1. Create a new Activity called "ListViewActivity", remove any default layout or view on the screen, drag and drop a ListView from
the Palette to the screen ﴾Figure 113﴿.
Figure 113: activity_list_view.xml
2. Open the "ListViewActivity.java" that hosts the "activity_list_view.xml", insert the highlight code as shown in Figure 114.
3. Before you can test run it, it has to be navigated from the "MainActivity" page. Let's set up the "ListView" button in the
"MainActivity" page for this purpose.
Open the "activity_main.xml" in Text view.
android:onClick="getListViewPage"
and it is done!
GridView
A GridView is a ViewGroup that displays items in a 2‐D scrollable grid and the grid items are obtained from a data source via a
ListAdapter a subclass of the Adapter class. You will construct a GridView in your app to display a 2‐D grid of image thumbnails.
Whenever an item is selected, it will echo the index number of the image.
1. You may make use of the sample images from the "sample_photos.zip" for this exercise. Just download, unzip, and move the
photos to the "res/drawable" folder.
2. Create a new Activity called "GridViewActivity", remove any default layout or view on the screen, drag and drop a GridView from
the Palette to the screen and enter the various attributes in the "activity_grid_view.xml" accordingly as shown in Figure 116.
3. Open the "GridViewActivity.java" that hosts the "activity_grid_view.xml", insert the highlight code as shown in Figure 117. The
GridView is being captured via the findViewById method. The setAdapter method then sets a custom ImageAdapter as the
source for all items to be displayed in this GridView. The next step will be to create this ImageAdapter class.
Figure 117: Binding GridView to Image Source Via ImageAdapter
4. Follow the trail in Figure 118 to create a new Java Class called "ImageAdapter" in the current project, then enter the following
code into this class. The ImageAdapter class create an ImageView object for each of the images in the image array called
"imageIds" and define its properties, e.g. GridView.LayoutParams(180, 180) sets the height and width for the ImageView.
package com.example.peterleow.androiduis;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
public ImageAdapter(Context c) {
context = c;
}
imageView.setImageResource(imageIds[position]);
return imageView;
}
5. Before you can test run it, it has to be navigated from the "MainActivity" page. Let's set up the "GridView" button in the
"MainActivity" page for this purpose.
android:onClick="getGridViewPage"
and it is done!
Reflection
We are nearing the rest stop. Let's pause for a while and reflect. Do you notice the differences between this group of Layout models ‐
LinearLayout, RelativeLayout, and TableLayout, and this group ‐ ListView and GridView. They both organize elements on the UI. However,
the similarity stops here.
The former group deal mainly with UI controls like button, spinner, text fields and so on, which are usually created at design time in XML
format.
On the contrary, the purpose of the latter is to tabulate data in either one‐ or two‐dimension grid that are only known at runtime. An
Adapter acts as the middle man to draw and model the data before passing it to either the ListView or GridView for display.
Best Practices
Throughout the journey, I have cited some important learning points, tips, and summaries where applicable. In particular, I would like to
stress these three points as best practices.
Learning Point 7 ‐ When you need a new text string, do not hard code it. Instead, you should create a new string resource that
takes that text string as value. You will then reference this string resource in the XML or in code whenever you need to use text
string on any UIs. That is reusability and maintainability at its best. You should always visit Figures 37 to 41 for reference.
Learning Point 11 ‐ Change all the android:id values given by default by Android Studio to something more descriptive. For
example, instead of "@+id/checkBox" or "@+id/checkBox2", use "@+id/chkJogging" for "Jogging" checkbox, and
"@+id/chkSwimming" for "Swimming" checkbox, and so on. The "chk" prefix is short for checkbox.
You have been building UI layouts by declaring them as XML elements and structured them in an XML file. Keep it that way! In
fact, the Android framework allows you to create UI layouts at runtime using Java code. However, this approach should be
avoided as far as possible as you will be mixing the presentation of your app from the code that controls its behavior. That
violates the principle of "separation of concerns".
Tips
Last but not least, I would like to round up some tips that hopefully will make your Android development experience, especially with
Android Studio, a less winding one.
Always start your AVD as early as possible and leave it running, of course, having more RAM and faster processors certainly help,
else use a real device
Test your layout on both orientations, if you allow it, to make sure that your UI turns up as expected.
Red colored code usually signifies missing packages. Place your cursor above it and Alt + Enter to import the necessary
packages.
Look through your XML files, make sure all nodes are well‐structured and no missing node.
Look for this menu icon on the menu bar that read "Sync Project with Gradle Files" to sync your project.
On the menu bar, select Analyze > Inspect Code... which will opens an Inspection console that lists all potentials issues
with your app. If you are patient and meticulous enough, you should be able to locate the faults here ﴾Figure 120﴿
What is the last resort? The answer is "hitting File > Invalidate Caches / Restart... and pray!"
Taking Stock
This journey seemed endless. I am glad it has ended. You have learned the many UI layouts and UI controls in Android, with the bonus
of learning some coding to handle simple interactions. You should now have enough "muscle" to compose an Android UI and add basic
interactivity using Java code. I have put all them together into a quick link list for a quick jump to the various elements in this article.
UI layouts
LinearLayout
RelativeLayout
TableLayout
FrameLayout
RadioGroup
ListView
GridView
UI Controls
Button
TextView
EditText
CheckBox
RadioButton
ToggleButton
Spinner
AutoCompleteTextView
Progress Bar
Pickers
ImageView
P.S. For more focused learning of Java, I encourage you to visit some online tutorial sites for self‐learning, for example, you may try out
this one. One last thing, remember to wash your hands.
Reference
Android Developers
License
This article, along with any associated source code and files, is licensed under The Code Project Open License ﴾CPOL﴿
Share
子曰:"三人行,必有我师焉;择其善者而从之,其不善者而改之
"There is always something we can learn from another person. Choose to follow his strengths while use his shortcomings to reflect
upon ourselves."
― Confucius
“Live as if you were to die tomorrow. Learn as if you were to live forever.”
― Mahatma Gandhi
http://www.amazon.com/author/peterleow
Permalink | Advertise | Privacy | Terms of Use | Mobile Article Copyright 2014 by Peter Leow
Seleccionar idioma ▼
Web01 | 2.8.160721.1 | Last Updated 4 Jul 2015 Everything else Copyright © CodeProject, 1999‐2016