Download Module 5 - FAU Android

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
Module 6. User Interface Design
1.
Android Views, Layouts, Menus and Dialogs
a) Views

Definition:
o In an Android application, the user interface is built using View and ViewGroup
objects. There are many types of views and view groups, each of which is a
descendant of the View class.
o View objects are the basic units of user interface expression on the Android
platform. The View class serves as the base for subclasses called "widgets,"
which offer fully implemented UI objects, like text fields and buttons. The
ViewGroup class serves as the base for subclasses called "layouts," which offer
different kinds of layout architecture, like linear, tabular and relative.
o Relationship between Views and Activity


An activity can contain one or more views.
An activity has to have at least one view if we want to have a user
interface.
o A View object:




is a data structure whose properties store the layout parameters and
content for a specific rectangular area of the screen.
handles its own measurement, layout, drawing, focus change, scrolling,
and key/gesture interactions for the rectangular area of the screen in which
it resides.
is also a point of interaction for the user and the receiver of the interaction
events.
View Hierarchy
o On the Android platform, you define an Activity's UI using a hierarchy of View
and ViewGroup nodes, as shown in the diagram below.
Figure 6.1 View Hierarchy Example.
o A hierarchy tree can be built up using Android’s set of predefined widgets and
layouts, or with custom Views that you create yourself.
o In order to attach the view hierarchy tree to the screen for rendering, your Activity
must call the setContentView() method and pass a reference to the root node
object.
o The root node of the hierarchy requests that its child nodes draw themselves — in
turn, each view group node is responsible for calling upon each of its own child
views to draw themselves.
o Let’s look at an example of a Sudoku application [3] where a view is used:
package org.example.sudoku;
import android.app.Activity;
import android.os.Bundle;
public class Sudoku extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}



The onCreate() method of this activity is called automatically by Android
to initialize the activity. As you can see there is a call to
setContentView() which fills in the contents of the activity’s screen.
R.lauout.main is a resource identifier that refers to the main.xml file
in the res/layout directory. This main.xml declares the user interface in
XML.
The R class is managed automatically by the Android.
b) Layouts



The most common way to define your layout and express the view hierarchy is with
an XML layout file.
Each element in an XML Layout is a View (or a subclass of a View, such as a
Button)or ViewGroup object (or descendent thereof). View objects are leaves in the
tree, ViewGroup objects are branches in the tree (see the View Hierarchy figure
above).
The name of an XML element is respective to the Java class that it represents. So a
<TextView> element creates a TextView in your UI, and a <LinearLayout> element
creates a LinearLayout view group. When you load a layout resource, the Android
system initializes these run-time objects, corresponding to the elements in your
layout. Let’s look at the following example which defines a simple vertical layout
with a text view and a button:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a TextView" />
<Button android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello, I am a Button" />
</LinearLayout>


o Notice that the LinearLayout element contains both the TextView and the
Button. You can nest another LinearLayout (or other type of view group)
inside here, to lengthen the view hierarchy and create a more complex layout.
A layout is a container for one or more child objects and a behavior to position them
on the screen within the rectangle of the parent object. Here is a list of the most
common layouts provided by Android:
o FrameLayout : Arranges its children so they all start at the top left of the
screen. This is used for tabbed views and image switchers.
o LinearLayout: Arranges its children in a single column or row. This is the
most common layout you will use.
o RelativeLayout: Arranges its children in relation to each other or to the
parent. This is often used in forms.
o TableLayout: Arranges its children in rows and columns, similar to an
HTML table.
Common parameters to all layouts:
o
xmlns:android=”http://schemas.android.com/apk/res/android”

Defines the XML namespace for Android. You should define this once, in
the first XML tag in the file.
o android:layout_width=”fill_parent”, android:layout_height=”fill_parent”
 Takes up the entire width and height of the parent (in this case, the
window). Possible values are fill_parent and wrap_content.

Sudoku Example:
o Let’s look at an example of the Sudoku application where the user interface is
defined in main.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/main_title" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/continue_label" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/new_game_label" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/about_label" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/exit_label" />
</LinearLayout>
o Running the Sudoku application with this xml file we get the following screen
shot:
Figure 6.2 Sudoku Application Main Screen
o The following code represents the Sudoku main.xml file which defines the
user interface for our Sudoku application.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:background="@color/background"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:padding="30dip"
android:orientation="horizontal">
<LinearLayout
android:orientation="vertical"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_gravity="center">
<TextView
android:text="@string/main_title"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center"
android:layout_marginBottom="25dip"
android:textSize="24.5sp" />
<Button
android:id="@+id/continue_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/continue_label" />
<Button
android:id="@+id/new_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/new_game_label" />
<Button
android:id="@+id/about_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/about_label" />
<Button
android:id="@+id/exit_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/exit_label" />
</LinearLayout>
</LinearLayout>
o As we can see the UI defined here contains a LinearLayout inside another
LinearLayout. The first <LinearLayout> element defines the application
settings like background color through android:background attribute, the
hight and the width of the screen and so on.
o The inner LinearLayout defines the layout for the buttons that will be
contained here. The attribute android:orientation indicates the orientation
of the elements in the screen, and we can see that the height, width and gravity
are defined here. This LinearLayout contains a TextView, used as a label for
the Game, showing the text: “Android Sudoku” as a title for the screen. Than
we see four button elements, one for Continue, one for New Game, another
one for About and finally one for Exit.
o Inside the <LinearLayout> tag there exists a child widget:
<TextView
android:text="@string/main_title"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center"
android:layout_marginBottom="25dip"
android:textSize="24.5sp" />
which defines a simple text label. Notice that instead of hard coding the
English text we are using @string/main_title syntax to refer to strings
in the res/values/strings.xml file. All the text (string literals) that
appears in your application needs to be specified in your resource files.
This file looks like this:
<resources>
<string name="app_name">Sudoku</string>
<string name="main_title">Android Sudoku</string>
<string name="continue_label">Continue</string>
<string name="new_game_label">New Game</string>
<string name="about_label">About</string>
<string name="exit_label">Exit</string>
</resources>
As you can see the @string/main_title value is Android Sudoku.
o Now if we run the Sudoku application (version 2 of the Sudoku code Sudokuv2) we will get something like this:
Figure 6.3 Sudoku Application

The onClick method is implemented by our activity (Sudoku) and automatically
called each time one of the four buttons is pressed. First step is to determine which of
the buttons was pressed and based on that, act accordingly.
public void onClick(View v) {
switch (v.getId()) {
case R.id.continue_button:
startGame(Game.DIFFICULTY_CONTINUE);
break;
// ...
case R.id.about_button:
Intent i = new Intent(this, About.class);
startActivity(i);
break;
// More buttons go here (if any) ...
case R.id.new_button:
openNewGameDialog();
break;
case R.id.exit_button:
finish();
break;
}
}

For this to appear in the main screen of the application we need to add the view
created in the xml file in the Sudoku class. In the below onCreate method behaviour
is added to the application. Code was added to call findViewById() to look up an
Android view given its resource ID and setOnClickListener() to tell Android
which objects to tickle when the user touches or clicks the view. For the click listener
to work we need to implement OnClickListener in the Sudoku Activity by adding
implement OnClickListener.
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Set up click listeners for all the buttons
View continueButton = this.findViewById(R.id.continue_button);
continueButton.setOnClickListener(this);
View newButton = this.findViewById(R.id.new_button);
newButton.setOnClickListener(this);
View aboutButton = this.findViewById(R.id.about_button);
aboutButton.setOnClickListener(this);
View exitButton = this.findViewById(R.id.exit_button);
exitButton.setOnClickListener(this);
}
o Remember that constants like R.id.about_button are created by the Eclipse
plug-in in R.java when it sees @+id/about_button in
res/layout/main.xml.

Let’s look at another xml file for the About Activity. This file looks like this:
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dip">
<TextView
android:id="@+id/about_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/about_text" />
</ScrollView>
This file describes the screen About which contains a simple text given in
@strings/about_text. This screen is obtained if we navigate to About button in the
Sudoku application, and it looks like this:
Figure 6.4 About Screen in Sudoku Application
o For the above screen to appear we need to link it to the About Activity. This is
done in the About class:
import android.app.Activity;
import android.os.Bundle;
public class About extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.about);
}
}
The link is done by calling setContentView(R.layout.about) which will
look for the about.xml file in the layout subdirectory. Remember that
onCreate() is automatically called by the Android platform to initialize the
About Activity.
o Keep in mind that every activity needs to be declared in
AndroidManifest.xml. This file contains the following:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.example.sudoku"
android:versionCode="1"
android:versionName="1.0.0">
<application android:icon="@drawable/icon"
android:label="@string/app_name">
<activity android:name=".Sudoku"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".About"
android:label="@string/about_title"
</activity>
<!-- More activities can go here -->
</application>
</manifest>
o As we can see the above file contains a reference to the icon of the application
which is located in the resource directory, specifically drawable/icon.
Furthermore it contains the application label as @string/app_name, and
contains the activities defined in the application, in our case Sudoku, About,
Settings and Game.

If we want to apply a Theme we will need to add the following line:
to the activity element for About,
thus obtaining:
android:theme="@android:style/Theme.Dialog"
<activity android:name=".About"
android:label="@string/about_title"
android:theme="@android:style/Theme.Dialog">
</activity>

Including this change to the Manifest file and running the application again, the
following screen is obtained for the About screen. As you can see, now the About
information is displayed as a Dialog which appears on top of the main Sudoku screen.
Figure 6.5 Themed About Screen of Sudoku
c) Menus


Menus are an important part of any application. They provide familiar interfaces that
reveal application functions and settings. Android offers an easy programming
interface for developers to provide standardized application menus for various
situations.
Android offers three fundamental types of application menus:
o Options Menu – is the primary set of menu items for an Activity. It is revealed
by pressing the device MENU key. Within the Options Menu are two groups
of menu items:

Icon Menu – is the collection of items initially visible at the bottom of the
screen at the press of the MENU key.
 It supports a maximum of six menu items.
 These are the only menu items that support icons and the only menu
items that do not support checkboxes or radio buttons.
 Expanded Menu – is a vertical list of items exposed by the "More" menu
item from the Icon Menu.
 It exists only when the Icon Menu becomes over-loaded and is
comprised of the sixth Option Menu item and the rest.

o Context Menu – is a floating list of menu items that may appear when you
perform a long-press on a View (such as a list item).
o Submenu – is a floating list of menu items that is revealed by an item in the
Options Menu or a Context Menu.
 A Submenu item cannot support nested Submenus.
Options Menu
o The Options Menu is opened by pressing the device MENU key.
o If more than six items are added to the Options Menu, then those that can't fit
in the Icon Menu are revealed in the Expanded Menu, via the "More" menu
item. The Expanded Menu is automatically added when there are more than
six items.
o Should include basic application functions and any necessary navigation items
(e.g., to a home screen or application settings). You can also add Submenus
for organizing topics and including extra menu functionality.
o When this menu is opened for the first time, the Android system will call the
Activity onCreateOptionsMenu() callback method. Before looking into how to
override this method to fit our purposes, let’s look at the xml file in
res/menu/menu.xml for the menu of the Sudoku application.
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/settings"
android:title="@string/settings_label"
android:alphabeticShortcut="@string/settings_shortcut" />
</menu>
Where settings_shortcut is defined in the strings.xml file as:
<string name=”settings_shortcut”>s</string>
The title of the menu is specified in settings_label in strings.xml file showing
“Settings…”. Figure 6.6 represents the illustration of the menu in the Sudoku
application.
Figure 6.6 Sudoku’s Menu
o In a menu XML layout, there are three valid elements: <menu>, <group> and
<item>. The item and group elements must be children of a menu, but item
elements may also be the children of a group, and another menu element may
be the child of an item (to create a Submenu). Of course, the root node of any
file must be a menu element.
o Now let’s look at how the menu is invoked in our application. We need to
override the Sudoku.onCreateOptionsMenu() method, as follows:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
getMenuInflater() returns an instance of MenuInflater that we use to read the
menu definition from XML and turns it into a real view.
When the user selects any menu item, onOptionsItemSelected() will be called.
Here is the definition for that method:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.settings:
startActivity(new Intent(this, Settings.class));
return true;
// More items go here (if any) ...
}
return false;
}
o The same menu can be obtained by creating it directly in the code using the
following code:
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, 0, 0, R.string.settings_label);
return true;
}
The Settings screen obtained by pressing the button Settings from the options menu
is the shown in Figure 6.7. The two options provided refer to music and hints. The
first option is playing music in the background, while the second one shows hits
during the play. Depending on whether the music is turned on or off, the Music
class will play music in the background or not. Hints are used when drawing the
board, in PuzzleView class, presented in more detail in the following module.
Figure 6.7 Sudoku Settings Screen


Context Menu
o The Android context menu is similar, in concept, to the menu revealed with a
"right-click" on a PC. When a view is registered to a context menu,
performing a "long-press" (press and hold for about two seconds) on the
object will reveal a floating menu that provides functions relating to that item.
o can be registered to any View object, however, they are most often used for
items in a ListView, which helpfully indicates the presence of the context
menu by transforming the background color of the ListView item when
pressed. (The items in the phone's contact list offer an example of this
feature.)
o Similar to the options menu, to create a context menu, you must override the
Activity’s context menu callback methods: onCreateContextMenu() and
onContextItemSelected().
Submenus
o A sub menu can be added within any menu, except another sub menu. These
are very useful when your application has a lot of functions that may be
organized in topics, like the items in a PC application's menu bar (File, Edit,
View, etc.).
o A sub menu is created by adding it to an existing Menu with addSubMenu().
This returns a SubMenu object (an extension of Menu). You can then add
additional items to this menu, with the normal routine, using the add()
methods. For example:
public boolean onCreateOptionsMenu(Menu menu) {
boolean result = super.onCreateOptionsMenu(menu);
SubMenu fileMenu = menu.addSubMenu("File");
SubMenu editMenu = menu.addSubMenu("Edit");
fileMenu.add("new");
fileMenu.add("open");
fileMenu.add("save");
editMenu.add("undo");
editMenu.add("redo");
return result;
}

Menu Features
o Menu Groups

When adding new items to a menu, you can optionally include each
item in a group. A menu group is a collection of menu items that can
share certain traits, like whether they are visible, enabled, or
checkable.
 A group is defined by an integer (or a resource id, in XML). A menu
item is added to the group when it is added to the menu, using one of
the add() methods that accepts a
groupId as an argument, such as
add(int, int, int, int).
 You can show or hide the entire group
with setGroupVisible(); enable or
disable
the
group
with
setGroupEnabled(); and set whether
the items can be checkable with
setGroupCheckable().
o Checkable menu items
 Any menu item can be used as an
interface for turning options on and off.
This can be indicated with a checkbox
for stand-alone options, or radio buttons
for groups of mutually exlusive options
(see the screenshot to the right).
 To make a single item checkable, use the
setCheckable() method, like so:
menu.add(0, VIBRATE_SETTING_ID, 0, "Vibrate")
.setCheckable(true);
This will display a checkbox with the menu item (unless it's in the Icon
Menu).

To make a group of mutually exclusive radio button items, simply
assign the same group ID to each menu item and call
setGroupCheckable(). In this case, you don't need to call
setCheckable() on each menu items, because the group as a whole is
set checkable. Here's an example of two mutually exclusive options in
a Submenu:
SubMenu subMenu = menu.addSubMenu("Color");
subMenu.add(COLOR_MENU_GROUP, COLOR_RED_ID, 0, "Red");
subMenu.add(COLOR_MENU_GROUP, COLOR_BLUE_ID, 0, "Blue");
subMenu.setGroupCheckable(COLOR_MENU_GROUP, true, true);
In the setGroupCheckable() method, the first argument is the group ID
that we want to set checkable. The second argument is whether we want
the group items to be checkable. The last one is whether we want each
item to be exclusively checkable (if we set this false, then all the items
will be checkboxes instead of radio buttons). When the group is set to be
exclusive (radio buttons), each time a new item is selected, all other are
automatically de-selected.
o Shortcut keys
 Quick access shortcut keys using letters and/or numbers can be added
to menu items with setAlphabeticShortcut(char) (to set char
shortcut), setNumericShortcut(int) (to set numeric shortcut), or
setShortcut(char,int) (to set both). Case is not sensitive. For
example:
menu.add(0, MENU_QUIT, 0, "Quit").setAlphabeticShortcut('q');


Now, when the menu is open (or while holding the MENU key),
pressing the "q" key will select this item.
In XML the same result can be achieved using the following syntax:
android:alphabeticShortcut="@string/settings_shortcut"
like in the definition of the menu Settings presented previously and listed
below.
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/settings"
android:title="@string/settings_label"
android:alphabeticShortcut="@string/settings_shortcut" />
</menu>
d) Dialogs








A dialog is usually a small window that appears in front of the current Activity.
The underlying Activity loses focus and the dialog accepts all user interaction.
Dialogs are normally used for notifications and short activities that directly relate to
the application in progress.
The Android API supports the following types of Dialog objects:
o AlertDialog – a dialog that can manage zero, one, two, or three buttons, and/or
a list of selectable items that can include checkboxes or radio buttons. The
AlertDialog is capable of constructing most dialog user interfaces and is the
suggested dialog type.
o ProgressDialog – a dialog that displays a progress wheel or progress bar.
Because it's an extension of the AlertDialog, it also supports buttons.
o DatePickerDialog – a dialog that allows the user to select a date.
o TimePickerDialog – a dialog that allows the user to select a time.
A dialog is always created and displayed as a part of an Activity. You should
normally create dialogs from within your Activity's onCreateDialog(int) callback
method. When you use this callback, the Android system automatically manages the
state of each dialog and hooks them to the Activity, effectively making it the "owner"
of each dialog. As such, each dialog inherits certain properties from the Activity.
When you want to show a dialog, call showDialog(int) and pass it an integer that
uniquely identifies the dialog that you want to display.
When a dialog is requested for the first time, Android calls onCreateDialog(int) from
your Activity, which is where you should instantiate the Dialog. This callback method
is passed the same ID that you passed to showDialog(int). After you create the
Dialog, return the object at the end of the method.
Now let’s look at our Sudoku application to see how an AlertDialog is created. When
the option New Game is chosen in the menu of Sudoku, we want to pop up a dialog
box asking the user to select between three difficulty levels. First we need to add a
few more strings in res/values/strings.xml:
<string
<string
<string
<string
name="new_game_title">Difficulty</string>
name="easy_label">Easy</string>
name="medium_label">Medium</string>
name="hard_label">Hard</string>
Now we need to create the list of difficulties as an array resource in
res/values/arrays.xml:
<resources>
<array name="difficulty">
<item>@string/easy_label</item>
<item>@string/medium_label</item>
<item>@string/hard_label</item>
</array>
</resources>
The code to create the new AlertDialog is located in openNewGameDialog() method
called when the user presses on the button corresponding for New Game is listed
below. Next Figure illustrates the screen displaying this alert dialog.
After the user chooses a difficulty level, the onClick method of
DialogOnClickListener class is being called that will actually call the last method,
startGame.
class DialogOnClickListener implements DialogInterface.OnClickListener{
public void onClick(DialogInterface dialoginterface,
int i) {
startGame(i);
}
}
/** Ask the user what difficulty level they want */
private void openNewGameDialog() {
DialogOnClickListener listener = new DialogOnClickListener();
AlertDialog.Builder alertDiag = new AlertDialog.Builder(this);
alertDiag.setTitle(R.string.new_game_title);
alertDiag.setItems(R.array.difficulty,listener);
alertDiag.show();
}
/** Start a new game with the given difficulty level */
private void startGame(int i) {
Log.d(TAG, "clicked on " + i);
// Start game here...
}
The setItems() method takes two parameters: the resource ID of the item list, in this case an
array named difficulty defined in res/values/arrays.xml, and a listener that will be called
when one of the items is selected.
The method startGame(int i) will contain the main functionality of the game and will be
presented in the next Module.
Figure 6.8 Difficulty Alert Dialog Screen
References:
[1]
[2]
[3]
XML Online Tutorial, http://www.w3schools.com/xml/default.asp
Android Online Tutorial, http://developer.android.com/guide/index.html
Ed Burnette, Hello, Android: Introducing Google’s Mobile Development Platform.