Android 3.0 Application Development: Managing Menus

Exclusive offer: get 50% off this eBook here
Android 3.0 Application Development Cookbook

Android 3.0 Application Development Cookbook — Save 50%

Over 70 working recipes covering every aspect of Android development

$26.99    $13.50
by Kyle Merrifield Mew | July 2011 | Open Source

Menus are an essential part of almost any operating system. On mobile systems where screen real estate is limited, they play an even more important role. Android provides similar mechanisms for menus as it does for other visual elements, making it possible to separate them from application code by the use of XML.

In this article by Kyle Merrifield Mew, author of Android 3.0 Application Development Cookbook, we will cover the following topics:

  • Creating and inflating an options menu
  • Designing Android compliant menu icons
  • Building a context sensitive menu
  • Handling menu selections
  • Building menu groups of checkable items
  • Applying shortcut keys and submenus

 

Android 3.0 Application Development Cookbook

Android 3.0 Application Development Cookbook

Over 70 working recipes covering every aspect of Android development

        Read more about this book      

(For more resources on Android, see here.)

Introduction

All Android handsets have a hard menu key for calling up secondary choices that do not need to be made available from a main screen, or perhaps need to be made available across an application.

Android 3.0 Application Development Cookbook

In concord with Android's philosophy of separating appearance from function, menus are generally created in the same way as other visual elements, that is, with the use of a definitive XML layout file.

There is lot that can be done to control menus dynamically and Android provides classes and interfaces for displaying context-sensitive menus, organizing menu items into groups, and including shortcuts.

 

Creating and inflating an options menu

To keep our application code separate from our menu layout information, Android uses a designated resource folder (res/menu) and an XML layout file to define the physical appearance of our menu; such as the titles and icons we see in Android pop-up menus. The Activity class contains a callback method, onCreateOptionsMenu(), that can be overridden to inflate a menu.

Getting ready

Android menus are defined in a specific, designated folder. Eclipse does not create this folder by default so start up a new project and add a new folder inside the res folder and call it menu.

How to do it...

  1. Create a new XML file in our new res/menu folder and call it my_menu.xml. Complete the new file as follows:

    <?xml version="1.0" encoding="utf-8"?>
    <menu
    xmlns:android="http://schemas.android.com/apk/res/android">
    <item
    android:id="@+id/item_one"
    android:title="first item" />
    <item
    android:id="@+id/item_two"
    android:title="second item" />
    </menu>

  2. In the Java application file, include the following overridden callback:

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.my_menu, menu);
    return true;
    }

  3. Run the application on a handset or emulator and press the hard menu key to view the menu:

    Android 3.0 Application Development Cookbook

How it works...

Whenever we create an Android menu using XML we must place it in the folder we used here (res/menu). Likewise, the base node of our XML structure must be <menu>.

The purpose of the id element should be self explanatory and the title attribute is used to set the text that the user sees when the menu item is inflated.

The MenuInflater object is a straightforward way of turning an XML layout file into a Java object. We create a MenuInflater with getMenuInflater() which returns a MenuInflater from the current activity, of which it is a member. The inflate() call takes both the XML file and the equivalent Java object as its parameters.

There's more...

The type of menu we created here is referred to as an options menu and it comes in two flavors depending on how many items it contains. There is also a neater way to handle item titles when they are too long to be completely displayed.

Handling longer options menus

When an options menu has six or fewer items it appears as a block of items at the bottom of the screen. This is called the icon menu and is, as its name suggests, the only menu type capable of displaying icons. On tablets running API level 11 or greater the Action bar can also be used to access the menu.

The icon menu is also the only menu type that cannot display radio buttons or check marks.

When an inflated options menu has more than six items, the sixth place on the icon menu is replaced by the system's own More item, which when pressed calls up the extended menu which displays all items from the sixth onwards, adding a scroll bar if necessary.

Android 3.0 Application Development Cookbook

Providing condensed menu titles

If Android cannot fit an item's title text into the space provided (often as little as one third of the screen width) it will simply truncate it. To provide a more readable alternative, include the android:titleCondensed="string" attribute alongside android:title in the item definition.

Adding Option menu items to the Action Bar

For tablet devices targeting Android 3.0 or greater, option menu items can be added to the Action Bar.

Adjust the target build of the above project to API level 11 or above and replace the res/menu/my_menu.xml file with the following:

<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/item_one"
android:title="first item"
android:icon="@drawable/icon"
android:showAsAction="ifRoom" />
<item
android:id="@+id/item_two"
android:title="second item"
android:icon="@drawable/icon"
android:showAsAction="ifRoom|withText" />
<item
android:id="@+id/item_three"
android:title="third item"
android:icon="@drawable/icon"
android:showAsAction="always" />
<item
android:id="@+id/item_four"
android:title="fourth item"
android:icon="@drawable/icon"
android:showAsAction="never" />
</menu>

Note from the output that unless the withText flag is included, the menu item will display only as an icon:

Android 3.0 Application Development Cookbook

 

Designing Android compliant menu icons

The menu items we defined in the previous recipe had only text titles to identify them to the user, however nearly all Icon Menus that we see on Android devices combine a text title with an icon. Although it is perfectly possible to use any graphic image as a menu icon, using images that do not conform to Android's own guidelines on icon design is strongly discouraged, and Android's own development team are particularly insistent that only the subscribed color palette and effects are used. This is so that these built-in menus which are universal across Android applications provide a continuous experience for the user.

Here we examine the colors and dimensions prescribed and also examine how to provide the subsequent images as system resources in such a way as to cater for a variety of screen densities.

Getting ready

The little application we put together in the last recipe makes a good starting point for this one. Most of the information here is to do with design of the icons, so you may want to have a graphics editor such as GIMP or PhotoShop open, or you may want to refer back here later for the exact dimensions and palettes.

How to do it...

  1. Open the res/menu/my_menu.xml file and add the android:icon elements seen here to each item:

    <?xml version="1.0" encoding="utf-8"?>
    <menu
    xmlns:android="http://schemas.android.com/apk/res/android">
    <item
    android:id="@+id/item_one"
    android:icon="@drawable/my_menu_icon"
    android:title="first item" />
    <item
    android:id="@+id/item_two"
    android:icon="@drawable/my_menu_icon"
    android:title="second item" />
    </menu>

  2. With your graphics editor, create a new transparent PNG file, precisely 48 by 48 pixels in dimension.
  3. Ensuring that there is at least a 6 pixel border all the way around, produce your icon as a simple two-dimensional flat shape. Something like this:

    Android 3.0 Application Development Cookbook

  4. Fill the shape with a grayscale gradient that ranges from 47% to 64% (white) with the lighter end at the top.
  5. Provide a black inner shadow with the following settings:
    • 20% opaque
    • 90° angle (top to bottom)
    • 2 pixel width
    • 2 pixel distance
  6. Next, add an inner bevel with:
    • Depth of 1%
    • 90° altitude
    • 70% opaque, white highlight
    • 25% opaque, black shadow
  7. Now give the graphic a white outer glow with:
    • 55% opacity
    • 3 pixel size
    • 10% spread

    Android 3.0 Application Development Cookbook

  8. Make two copies of our graphic, one resized to 36 by 36 pixels and one 72 by 72 pixels.
  9. Save the largest file in the res/drawable-hdpi as my_menu_icon.png.
  10. Save the 48 by 48 pixel file with the same name in the drawable-mdpi folder and the smallest image in drawable-ldpi.
  11. To see the full effect of these three files in action you will need to run the software on handsets with different screen resolutions or construct emulators to that purpose.

How it works...

As already mentioned, Android currently insists that menu icons conform to their guidelines and most of the terms used here should be familiar to anyone who has designed an icon before.

The designated drawable folders allow us to provide the best possible graphics for a wide variety of screen densities. Android will automatically select the most appropriate graphic for a handset or tablet so that we can refer to our icons generically with @drawable/.

It is only ever necessary to provide icons for the first five menu items as the Icon Menu is the only type to allow icons.

 

Android 3.0 Application Development Cookbook Over 70 working recipes covering every aspect of Android development
Published: July 2011
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

 

        Read more about this book      

(For more resources on Android, see here.)

Building a context sensitive menu

Very often we want our menus to present choices to the user in a context sensitive way, commonly achieved on PCs with a right-click. In Android a long click is used to produce such menus when they are available. All Android Views are capable of receiving this action and here we will create two different Views and connect them to a menu. Also we will examine one or two of the built-in features of the Android ContextMenu.

Getting ready

Just as in the previous two recipes, we will be defining a menu layout here in XML which we will then connect to our Views with Java using an activity callback. Start a new Android project in Eclipse and create a new folder res/menu.

How to do it...

  1. Within the res/menu folder, create an Android XML file called my_menu.xml.
  2. Complete my_menu.xml so that it contains two items, each with a title and an id, as we did before. You can of course copy much of this from the previous recipe if you wish:

    <?xml version="1.0" encoding="utf-8"?>
    <menu
    xmlns:android="http://schemas.android.com/apk/res/android">
    <item
    android:id="@+id/item_one"
    android:title="first item" />
    <item
    android:id="@+id/item_two"
    android:title="second item" />
    </menu>

  3. Open and edit the main.xml file in the res/layout folder, and also replace the default TextView and add an EditText to the vertically aligned LinearLayout, as seen in the following screenshot:

    Android 3.0 Application Development Cookbook

  4. Provide each view with an appropriate ID, for example android:id="@+id/text_view" and android:id="@+id/edit_text".
  5. In our Java activity class, declare two private fields, mTextView and mEditText.
  6. Retrieve the XML resources with findViewById() from within the onCreate() method:
    mTextView = (TextView) findViewById(R.id.text_view);
    mEditText = (EditText) findViewById(R.id.edit_text);
  7. Still within onCreate() connect our views with our menu using:
    registerForContextMenu(mTextView);
    registerForContextMenu(mEditText);
  8. Now override the onCreateContextMenu() activity method:

    @Override
    public void onCreateContextMenu(ContextMenu m,
    View v, ContextMenuInfo i) {
    super.onCreateContextMenu(m, v, i);
    m.setHeaderTitle("my title");
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.my_menu, m);
    }

  9. Test the application on an emulator or handset, making sure to examine the context menu for both views.

How it works...

In terms of definition and inflation Context Menus are very similar to Options Menus. In fact the format of the XML and use of a MenuInflater are identical. It is the registerForContextMenu() call that makes the difference here and it is simply used to inform the system that a view has a context menu associated with it.

Our activity supplies us with the onCreateContextMenu() method, which performs the same function that the onCreateOptionsMenu() does for a standard menu, with the exception that we also need to pass the view that received the long click and a ContextMenuInfo object.

ContextMenuInfo is an interface belonging to ContextMenu and acts as an adapter passing any extra information about the menu inflation such as the item selected in a list view.

We gave our menu a header title with ContextMenu.setHeaderTitle(). Here we simply applied a string literal, but it is more conventional and logical to identify the view that was long-clicked in the title of its context menu. This value can be retrieved with View.getID().

Note that if you remove the line m.setHeaderTitle("my title"); and call up the menu from the EditText, then it will provide its own header Edit text which is overridden when we provide our own.

Android widgets such as EditText that contain editable text provide their own context menus with various cut and paste functions. This is why we call onCreateContextMenu() on its superclass, to handle menu items provided by the system.

Android 3.0 Application Development Cookbook

When we register our view with a context menu, we append our items to these readymade ones.

There's more...

It is not always possible to know in advance precisely what items may or may not be needed in a menu at runtime and so Android provides a way to add menu items from within our Java code.

Adding menu items dynamically

Menu items can be included either from within the onCreateOptionsMenu() method or the onCreateContextMenu() method, with Menu's add() member:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add("a new item");
...

We can also define menu item IDs as class fields, for example:

public class MenuExample extends Activity {
private static final int MENU1 = Menu.FIRST;
...

This gives us greater control over our dynamically constructed items:

menu.add(0, MENU1, 0, "another item");

The previous line, when included in one of our menu onCreate callbacks has the following structure:

Menu.add(int groupId, int itemId, int order, CharSequence title).

 

Handling menu selections

It is all very well to be able to design menus and have them inflate according to user actions but we also need some way to interpret and respond in return. Again the Activity class provides a hook for menu selections in the form of a callback, onOptionsItemSelected().

Getting ready

In this recipe we will be using an XML menu definition identical to the previous one, so you may well wish to copy and paste this file to save time. Nevertheless start up a new Android project in Eclipse.

How to do it...

  1. Define an XML menu called my_menu.xml in the res/menu folder, creating this folder if necessary, and provide it with two items, giving each at least an id and a title.
  2. In the res/layout folder edit the main.xml file so that the layout contains a single TextView with an android:id, for example:

    <TextView
    android:id="@+id/text_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textSize="20dip"
    android:text="Press menu" />

  3. In our Java activity class create a TextView field and associate it with its XML resource equivalent.
  4. Include code to inflate our menu by overriding the onCreateOptionsMenu() method as follows:

    @Override
    public boolean onCreateOptionsMenu(Menu m) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.my_menu, m);
    return true;
    }

  5. Finally add the code to control the actual individual selections with the onOptionsItemSelected() method:

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case R.id.item_one:
    mTextView.setText("You selected menu item one");
    return true;
    case R.id.item_two:
    mTextView.setText("You selected menu item two");
    return true;
    default:
    return super.onOptionsItemSelected(item);
    }
    }

  6. Run the project on a handset or emulator to test the menu selections:

Android 3.0 Application Development Cookbook

How it works...

The construction of an options menus was covered earlier in the article, as was its inflation. The activity member introduced here is onOptionsItemSelected() and the key identifier is MenuItem.getItemId(), which we used to differentiate between items.

We could of course use the passed MenuItem variable item to identify its source, and along with getItemId() we could have used getTitle() or getOrder() or several other public MenuItem methods.

We called onCreateOptionsMenu() on its superclass here more for completion than necessity and it is used to handle system menu items that may be called.

There's more...

As stated in its name the onOptionsItemSelected() is suitable only for Android's Options Menu. As one would expect, there is an equivalent method for Context Menus.

It is also possible to do more sophisticated things than change some text; for example we could start an activity from a menu item.

Selecting context menu items

To control the behavior of individual menu items for Context Menus use the onContextItemSelected(MenuItem item) activity callback.

Starting an activity from a menu

To start an activity from within the onOptionsItemSelected() or onContextItemSelected() methods, launch the activity with an Intent object using startActivity().

 

Android 3.0 Application Development Cookbook Over 70 working recipes covering every aspect of Android development
Published: July 2011
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

 

        Read more about this book      

(For more resources on Android, see here.)

Building menu groups of checkable items

Another common use for menus is to switch certain functions on or off and often this has to be done in a mutually exclusive manner such as when only one possible selection can be made from a list. For this purpose Android provides a framework for defining checkboxes and radio buttons using groups of menu items.

Getting ready

The Eclipse IDE provides another, more intuitive way to construct XML menu files in the form of a graphical pane that can be accessed with the Layout tab of any Android XML file. Start up a new project and inside the res folder, create a new folder called menu.

How to do it...

  1. Create a new Android XML file inside res/menu and call it my_menu.xml.
  2. View the new file through the Layout tab.
  3. Using the controls provided (in particular the Add..., Up, and Down buttons) construct a menu as seen in the next screenshot. Give each item an id and a title. You will need to create the Group first:

    Android 3.0 Application Development Cookbook

  4. Give the menu group an id and set the Checkable behavior to single:

    Android 3.0 Application Development Cookbook

  5. Edit the main.xml file in the res/layout folder so that the root layout contains a single TextView:

    <TextView
    android:id="@+id/text_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textSize="20sp"
    android:padding="6dip"
    android:text="long click here" />

  6. In the main Java activity file, connect the TextView in Java and register it for a Context Menu:

    private TextView mTextView;
    @Override
    public void onCreate(Bundle state) {
    super.onCreate(state);
    setContentView(R.layout.main);
    mTextView = (TextView) findViewById(R.id.text_view);
    registerForContextMenu(mTextView);
    }

  7. Override the onCreateContextMenu() hook as we have here:

    @Override
    public void onCreateContextMenu(ContextMenu m,
    View v, ContextMenuInfo i) {
    super.onCreateContextMenu(m, v, i);
    m.setHeaderTitle("my title");
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.my_menu, m);
    }

  8. Now run the project on an emulator or a handset and call up our menu by longclicking on the text view. The three items in the group should have radio buttons alongside them.
  9. Using the Layout pane, edit our menu file so that the Checkable behavior of the group is all rather than single.
  10. Run the program again to observe the difference this change makes. Our radio buttons are now checkboxes:

Android 3.0 Application Development Cookbook

How it works...

Despite using Eclipse's visual XML editing capacities, the way we constructed our menu here was no different from previous recipes in this article and the same can be said for the way we registered a view with a menu and the way we inflated it. It is a good idea to take a look at the XML code directly to see how this exercise differs. The use of the <group> node should not be difficult to understand. The android:checkableBehavior element can take three values:

  • single—where only one item can be checked at a time, producing radio buttons
  • all—where any item can be checked, producing check boxes
  • none—making no items checkable

Individual items can be set as checkable with android:checkable="true" and their state can be controlled specifically with android:checked="true" or "false".

There's more...

The state of checkable objects created in this way must be managed in code and Android provides the isChecked() and setChecked() methods for this purpose.

Changing checkable items dynamically

The state of an Android menu checkable item can be requested and changed from within our Java code. Generally speaking this would be done from one of the related callbacks such as the onContextItemSelected() method.

The MenuItem.isChecked() method returns a boolean reflecting the checked state of the item which can be changed by passing a boolean with MenuItem.setChecked().

 

Applying shortcut keys and submenus

The Menu, ContextMenu, and MenuItem classes that we have covered in this article make up the key components of Android's menus. However there is still one class that we have not touched, the SubMenu, and no article on menus would be complete without a mention of shortcuts. As with other features, Android allows us to create and manipulate submenus and shortcuts using both XML and Java.

Getting ready

It is probably a good idea to use the project we created in the last recipe (Building menu groups of checkable items) but if you do not have it, start up an Android project and put together a quick menu XML file with three or four items in the res/menu folder. We will also need a TextView that is registered for a Context Menu.

How to do it...

  1. Open the menu file inside res/menu and replace the first item with the code below:

    <item
    android:id="@+id/sub_menu"
    android:title="sub menu">
    <menu>
    <item
    android:id="@+id/sub_one"
    android:title="submenu one" />
    <item
    android:id="@+id/sub_two"
    android:title="submenu two" />
    </menu>
    </item>

  2. In the same file, add one of the following elements to the second item and the other to the third:
    android:numericShortcut="3"
  3. In the Java activity file, implement an onCreateContextMenu() method to inflate our menu as follows:

    @Override
    public void onCreateContextMenu(ContextMenu m,
    View v, ContextMenuInfo i) {
    super.onCreateContextMenu(m, v, i);
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.my_menu, m);
    }

  4. Next, provide the class-wide field:
    private static final int MENU1 = Menu.FIRST;
  5. Then, add the following line before the MenuInflater declaration:
    m.addSubMenu(0, MENU1, 1, "my new submenu");
  6. Finally, run and view the project on an emulator or a handset with a keyboard and call up the context menu followed by the submenu:

Android 3.0 Application Development Cookbook

How it works...

SubMenus are created and accessed in almost exactly the same manner as other menu elements and can be placed in any of the provided menus, although they cannot be placed within each other, that is, a SubMenu cannot contain another SubMenu.

Shortcuts too are simple to include although they will only work on a handset or emulator with a keyboard. They can be assigned in Java as well with setNumericShortcut(char).

SubMenus can be added dynamically as we did here and the addSubMenu() method allows us to specify the group, ID, position, and title.

Summary

In this article we saw how to provide and manage pop-up menus for activities and applications.


Further resources on this subject:


About the Author :


Kyle Merrifield Mew

Kyle Merrifield Mew is a writer, journalist, and developer who has been programming since the early 80s and who has been following the Android operating system, since its purchase by Google, with great interest. Kyle has always believed that open source platforms would one day provide lucrative opportunities for anyone with programming skills and that Android is that platform.

Books From Packt


Android Application Testing Guide
Android Application Testing Guide

Flash Development for Android Cookbook
Flash Development for Android Cookbook

Android User Interface Development: Beginner's Guide
Android User Interface Development: Beginner's Guide

iPhone JavaScript Cookbook
iPhone JavaScript Cookbook

jQuery Mobile First Look
jQuery Mobile First Look

Rhomobile Beginner's Guide
Rhomobile Beginner's Guide

Xcode 4 iPhone Development Beginner's Guide
Xcode 4 iPhone Development Beginner's Guide

MeeGo 1.0 Mobile Application Development Cookbook
MeeGo 1.0 Mobile Application Development Cookbook


No votes yet

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
i
j
d
h
C
b
Enter the code without spaces and pay attention to upper/lower case.
Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software