Creating an Options menu

Before we actually create and display a menu, let's look at a menu to see the end result. The following is a screenshot showing the menu section of Chrome:

The most obvious feature to note is that the menu will look different based on the screen size. By default, menu items will be added to the Overflow menu—that's the menu you see when you press the three dots at the far right edge.

Menus are typically created in resource files using XML (like many other Android resources) but they are stored in the res/menu directory though they can also be created in code. To create a menu resource, use the <menu> element as shown:

<menu xmlns:android="http://schemas.android.com/apk/res/android">
</menu>

The <item> element defines each inpidual menu item and is enclosed in the <menu> element. A basic menu item looks as follows:

<item 
    android:id="@+id/settings"
    android:title="@string/settings" />

The most common <item> attributes are the following:

  • id: This is the standard resource identifier
  • title: This indicates the text to display
  • icon: This is a draw-able resource
  • showAsAction: This has been explained as follows (see the following paragraph)
  • enabled: This is enabled by default

Let's look at showAsAction in more detail.

The showAsAction attribute controls how the menu item is shown. The options include the following:

  • ifRoom: This menu item should be included in the Action Bar if there's enough space
  • withText: This indicates that both the title and the icon should be shown
  • never: This indicates that the menu item should never be included in the Action Bar; always show in the overflow menu
  • always: This indicates that the menu item should be always included in the Action Bar (use sparingly as space is limited)
    Note

    Multiple options can be combined using the pipe (|) separator, such as showAsAction="ifRoom|withText".

With the fundamentals of the menu resource covered, we are now ready to create a standard Options menu and inflate it.

Getting ready

Use Android Studio to create a new project called OptionsMenu. Use the default Phone & Tablet option and select the Empty Activity option when prompted for the Activity Type. Since the wizard does not create the res/menu folder by default, navigate to File | New | Directory to create it before continuing.

How to do it...

With the new project created as described in the preceding section, you are ready to create a menu. However, first, we will add a string resource to the strings.xml file for the menu title. We will use the new string for the menu title when we create the XML for the menu. Here are the steps:

  1. Start by opening the strings.xml file and add the following <string> element to the <resources> element:
    <string name="menu_settings">Settings</string>
  2. Create a new file in the res/menu directory and call it menu_main.xml.
  3. Open the menu_main.xml file and add the following XML to define the menu:
    <?xml version="1.0" encoding="utf-8"?>
    <menu
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">
        <item android:id="@+id/menu_settings"
            android:title="@string/menu_settings"
            app:showAsAction="never">
        </item>
    </menu>
  4. With the menu now created, we just have to override the onCreateOptionsMenu() method in ActivityMain.java to inflate the menu:
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }
  5. Run the program on a device or emulator to see the menu in the Action Bar.

How it works...

There are two basic steps here:

  1. Define the menu in XML.
  2. Inflate the menu when the activity is created.

As a good programming habit, we define the string in the strings.xml file rather than hardcoding it in the XML. We then use the standard Android string identifier to set the title for the menu in Step 3. Since this is a "Settings" menu item, we don't want this to be shown in the Action Bar. To make sure it is never shown, use showAsAction="never".

With the menu defined, we will use the menu inflater in Step 4 to load the menu during the Activity creation. Notice the R.menu.menu_main menu resource syntax? This is why we create the XML in the res/menu directory — so the system will know this is a menu resource.

In Step 4, we used app:showAsAction rather than Android: android:showAsAction. This is because we are using the AppCompat library (also referred to as the Android Support Library). By default, the Android Studio new project wizard includes the support library in the project.

There's more...

If you ran the program in Step 5, then you must have seen the Settings menu item when you pressed the menu overflow button. But that was it. Nothing else happened. Obviously, menu items aren't very useful if the application doesn't respond to them. Responding to the Options menu is done through the onOptionsItemSelected() callback.

Add the following method to the application to see a Toast when the Settings menu is selected:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if (item.getItemId() == R.id.menu_settings) {
        Toast.makeText(this, "Settings", Toast.LENGTH_LONG).show();
    } else {
        return super.onContextItemSelected(item);
    }
    return true;
}

That's it. You now have a working menu!

Tip

As shown in the preceding example, return true when you've handled the callback; otherwise, call the super class as shown in the else statement.

Using a menu item to launch an activity

In this example, we show a Toast so we can see a working example; however, we could just as easily launch a new activity if needed. As you did in the Starting a new activity with an Intent object recipe of Chapter 1, Activities, create an Intent and call it with startActivity().

Creating sub menus

Sub menus 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 other sub menus. To define a sub menu, include a <menu> element within an <item> element. Here is the XML form this recipe with two sub menu items added:

<?xml version="1.0" encoding="utf-8"?>
<menu
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item android:id="@+id/menu_settings
        android:title="@string/menu_settings"
        app:showAsAction="never">
        <menu>
            <item android:id="@+id/menu_sub1"
                android:title="Storage Settings" />
            <item android:id="@+id/menu_sub2"
                android:title="Screen Settings" />
        </menu>
    </item>
</menu>
Grouping menu items

Another menu feature that Android supports is grouping menu items. Android provides several methods for groups, including the following:

  • setGroupVisible(): Show or hide all items
  • setGroupEnabled(): Enable or disable all items
  • setGroupCheckable(): Set the checkable behavior
Tip

Android will keep all grouped items with showAsAction="ifRoom" together. This means all items in the group with showAsAction="ifRoom" will be in the Action Bar or all items will be in the overflow.

To create a group, add the <item> menu elements to a <group> element. Here is an example using the menu XML from this recipe with two additional items in a group:

<?xml version="1.0" encoding="utf-8"?>
<menu
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <group android:id="@+id/group_one" >
        <item android:id="@+id/menu_item1"
            android:title="Item 1"
            app:showAsAction="ifRoom"/>
        <item android:id="@+id/menu_item2"
            android:title="Item 2"
            app:showAsAction="ifRoom"/>
    </group>
    <item android:id="@+id/menu_settings"
        android:title="@string/menu_settings"
        app:showAsAction="never"/>
</menu>

See also