Sans Pareil Technologies, Inc.

Key To Your Business

Lesson 6

Options menu and app bar

The options menu is the primary collection of menu items for an activity. Actions that have a global impact on the app, such as "Search," "Compose email," and "Settings" are usually displayed in the options menu. Items from the options menu are presented by the app bar as a combination of on-screen action items and overflow options.

Context menu and contextual action mode

A context menu is a floating menu that appears when the user performs a long-click on an element. It provides actions that affect the selected content or context frame.

On Android 3.0 and higher, you should instead use the contextual action mode to enable actions on selected content. This mode displays action items that affect the selected content in a bar at the top of the screen and allows the user to select multiple items.


Popup menu

A popup menu displays a list of items in a vertical list that's anchored to the view that invoked the menu. It is used for providing an overflow of actions that relate to specific content or to provide options for a second part of a command. Actions in a popup menu should not directly affect the corresponding content—that's what contextual actions are for. Rather, the popup menu is for extended actions that relate to regions of content in your activity.


Defining a Menu in XML

For all menu types, Android provides a standard XML format to define menu items. Instead of building a menu in your activity's code, you should define a menu and all its items in an XML menu resource. You can then inflate the menu resource (load it as a Menu object) in your activity or fragment.

Using a menu resource is a good practice for a few reasons:
  • It is easier to visualise the menu structure in XML.
  • It separates the content for the menu from your application's behavioural code.

It allows you to create alternative menu configurations for different platform versions, screen sizes, and other configurations by leveraging the app resources framework.

To define the menu, create an XML file inside your project's res/menu/ directory and build the menu with the following elements:

  • <menu> Defines a Menu, which is a container for menu items. A <menu> element must be the root node for the file and can hold one or more <item> and <group> elements.
  • <item> Creates a MenuItem, which represents a single item in a menu. This element may contain a nested <menu> element in order to create a submenu.
  • <group> An optional, invisible container for <item> elements. It allows you to categorise menu items so they share properties such as active state and visibility.
Screen Shot 2016-02-12 at 13.17.03

The <item> element supports several attributes you can use to define an item's appearance and behaviour. The items in the above menu include the following attributes:

  • android:id A resource ID that's unique to the item, which allows the application to recognize the item when the user selects it.
  • android:icon A reference to a drawable to use as the item's icon.
  • android:title A reference to a string to use as the item's title.
  • android:showAsAction Specifies when and how this item should appear as an action item in the app bar.

These are the most important attributes you should use, but there are many more available. For information about all the supported attributes, see the Menu Resource document.
Screen Shot 2016-02-12 at 11.42.34

You can add a submenu to an item in any menu (except a submenu) by adding a <menu> element as the child of an <item>. Submenus are useful when your application has a lot of functions that can be organised into topics, like items in a PC application's menu bar (File, Edit, View, etc.).

Creating an Options Menu

You can declare items for the options menu from either your Activity subclass or a Fragment subclass. If both your activity and fragment(s) declare items for the options menu, they are combined in the UI. The activity's items appear first, followed by those of each fragment in the order in which each fragment is added to the activity. If necessary, you can re-order the menu items with the android:orderInCategory attribute in each <item> you need to move.
To specify the options menu for an activity, override onCreateOptionsMenu() (fragments provide their own onCreateOptionsMenu() callback). In this method, you can inflate your menu resource into the Menu provided in the callback.
Screen Shot 2016-02-12 at 13.42.44

You can also add menu items using add() and retrieve items with findItem() to revise their properties with MenuItem APIs.  The system calls onCreateOptionsMenu() when starting the activity, in order to show items in the app bar.

Changing menu items at runtime

If you want to modify the options menu based on events that occur during the activity lifecycle, you can do so in the onPrepareOptionsMenu() method. This method passes you the Menu object as it currently exists so you can modify it, such as add, remove, or disable items. (Fragments also provide an onPrepareOptionsMenu() callback.)

Handling click events

When the user selects an item from the options menu (including action items in the app bar), the system calls your activity's onOptionsItemSelected() method. This method passes the MenuItem selected. You can identify the item by calling getItemId(), which returns the unique ID for the menu item (defined by the android:id attribute in the menu resource or with an integer given to the add() method). You can match this ID against known menu items to perform the appropriate action.
Screen Shot 2016-02-12 at 14.14.43

When you successfully handle a menu item, return true. If you don't handle the menu item, you should call the superclass implementation of onOptionsItemSelected() (the default implementation returns false).

If your activity includes fragments, the system first calls onOptionsItemSelected() for the activity then for each fragment (in the order each fragment was added) until one returns true or all fragments have been called.

Tip: You can define the on-click behaviour for a menu item in XML, using the android:onClick attribute. The value for the attribute must be the name of a method defined by the activity using the menu. The method must be public and accept a single MenuItem parameter—when the system calls this method, it passes the menu item selected.

Tip: If your application contains multiple activities and some of them provide the same options menu, consider creating an activity that implements nothing except the onCreateOptionsMenu() and onOptionsItemSelected() methods. Then extend this class for each activity that should share the same options menu. This way, you can manage one set of code for handling menu actions and each descendant class inherits the menu behaviours. If you want to add menu items to one of the descendant activities, override onCreateOptionsMenu() in that activity. Call super.onCreateOptionsMenu(menu) so the original menu items are created, then add new menu items with menu.add(). You can also override the super class's behaviour for individual menu items.

Creating Contextual Menus

A contextual menu offers actions that affect a specific item or context frame in the UI. You can provide a context menu for any view, but they are most often used for items in a ListView, GridView, or other view collections in which the user can perform direct actions on each item.
There are two ways to provide contextual actions:
  • In a floating context menu. A menu appears as a floating list of menu items (similar to a dialog) when the user performs a long-click (press and hold) on a view that declares support for a context menu. Users can perform a contextual action on one item at a time.
  • In the contextual action mode. This mode is a system implementation of ActionMode that displays a contextual action bar at the top of the screen with action items that affect the selected item(s). When this mode is active, users can perform an action on multiple items at once (if your app allows it).

Creating a floating context menu

  • Register the View to which the context menu should be associated by calling registerForContextMenu() and pass it the View.  If your activity uses a ListView or GridView and you want each item to provide the same context menu, register all items for a context menu by passing theListView or GridView to registerForContextMenu().
  • Implement the onCreateContextMenu() method in your Activity or Fragment.  When the registered view receives a long-click event, the system calls your onCreateContextMenu() method. This is where you define the menu items, usually by inflating a menu resource.  MenuInflater allows you to inflate the context menu from a menu resource. The callback method parameters include the View that the user selected and a ContextMenu.ContextMenuInfo object that provides additional information about the item selected. If your activity has several views that each provide a different context menu, you might use these parameters to determine which context menu to inflate.Screen Shot 2016-02-12 at 15.44.38
  • Implement onContextItemSelected().  When the user selects a menu item, the system calls this method so you can perform the appropriate action.  The getItemId() method queries the ID for the selected menu item, which you should assign to each menu item in XML using the android:id attribute.  When you successfully handle a menu item, return true.  If you don't handle the menu item, you should pass the menu item to the superclass implementation. If your activity includes fragments, the activity receives this callback first. By calling the superclass when unhandled, the system passes the event to the respective callback method in each fragment, one at a time (in the order each fragment was added) until true or false is returned.

  • Screen Shot 2016-02-12 at 15.45.17

Contextual Action Mode

The contextual action mode is a system implementation of ActionMode that focuses user interaction toward performing contextual actions. When a user enables this mode by selecting an item, a contextual action bar appears at the top of the screen to present actions the user can perform on the currently selected item(s). While this mode is enabled, the user can select multiple items (if you allow it), deselect items, and continue to navigate within the activity (as much as you're willing to allow). The action mode is disabled and the contextual action bar disappears when the user deselects all items, presses the BACK button, or selects the Done action on the left side of the bar.
Note: The contextual action bar is not necessarily associated with the app bar. They operate independently, even though the contextual action bar visually overtakes the app bar position.
  • For views that provide contextual actions, you should usually invoke the contextual action mode upon one of two events (or both):
  • The user performs a long-click on the view.The user selects a checkbox or similar UI component within the view.

How your application invokes the contextual action mode and defines the behavior for each action depends on your design. There are basically two designs:
  • For contextual actions on individual, arbitrary views.
  • For batch contextual actions on groups of items in a ListView or GridView (allowing the user to select multiple items and perform an action on them all).

Enabling the contextual action mode for individual views

If you want to invoke the contextual action mode only when the user selects specific views, you should:
  • Implement the ActionMode.Callback interface. In its callback methods, you can specify the actions for the contextual action bar, respond to click events on action items, and handle other lifecycle events for the action mode.
    Notice that these event callbacks are almost exactly the same as the callbacks for the options menu, except each of these also pass the ActionMode object associated with the event. You can use ActionMode APIs to make various changes to the CAB, such as revise the title and subtitle with
    setTitle() and setSubtitle() (useful to indicate how many items are selected).
  • Call startActionMode() when you want to show the bar (such as when the user long-clicks the view).
    When you call
    startActionMode(), the system returns the ActionMode created. By saving this in a member variable, you can make changes to the contextual action bar in response to other events.

Enabling batch contextual actions in a ListView or GridView

  • Implement the AbsListView.MultiChoiceModeListener interface and set it for the view group with setMultiChoiceModeListener(). In the listener's callback methods, you can specify the actions for the contextual action bar, respond to click events on action items, and handle other callbacks inherited from the ActionMode.Callback interface.
  • Call setChoiceMode() with the CHOICE_MODE_MULTIPLE_MODAL argument.
    When the user selects an item with a long-click, the system calls the
    onCreateActionMode() method and displays the contextual action bar with the specified actions. While the contextual action bar is visible, users can select additional items.

Creating a Popup Menu

A PopupMenu is a modal menu anchored to a View. It appears below the anchor view if there is room, or above the view otherwise.
  • Providing an overflow-style menu for actions that relate to specific content.
    Note: This is not the same as a context menu, which is generally for actions that affect selected content. For actions that affect selected content, use the contextual action mode or floating context menu.
  • Providing a second part of a command sentence (such as a button marked "Add" that produces a popup menu with different "Add" options).
  • Providing a drop-down similar to Spinner that does not retain a persistent selection.

PopupMenu is usually defined in XML and displayed from an activity.
Screen Shot 2016-02-12 at 16.16.17
  • Instantate a PopupMenu with its constructor, which takes the current application Context and the View to which the menu should be anchored.
  • Use MenuInflater to inflate your menu resource into the Menu object returned by PopupMenu.getMenu(). On API level 14 and above, you can use PopupMenu.inflate() instead.
  • Invoke

Screen Shot 2016-02-12 at 16.18.39
The menu is dismissed when the user selects an item or touches outside the menu area. You can listen for the dismiss event using PopupMenu.OnDismissListener.

Handling click events

To perform an action when the user selects a menu item, you must implement the PopupMenu.OnMenuItemClickListener interface and register it with your PopupMenu by calling setOnMenuItemclickListener(). When the user selects an item, the system calls the onMenuItemClick() callback in your interface.

Creating Menu Groups

A menu group is a collection of menu items that share certain traits.

You can create a group by nesting <item> elements inside a <group> element in your menu resource or by specifying a group ID with the add() method.
Screen Shot 2016-02-14 at 10.27.27

The items that are in the group appear at the same level as the first item—all three items in the menu are siblings. However, you can modify the traits of the two items in the group by referencing the group ID and using the methods listed above. The system will also never separate grouped items. For example, if you declare
android:showAsAction="ifRoom" for each item, they will either both appear in the action bar or both appear in the action overflow.

Using checkable menu items

A menu can be useful as an interface for turning options on and off, using a checkbox for stand-alone options, or radio buttons for groups of mutually exclusive options.

Note: Menu items in the Icon Menu (from the options menu) cannot display a checkbox or radio button. If you choose to make items in the Icon Menu checkable, you must manually indicate the checked state by swapping the icon and/or text each time the state changes.

You can define the checkable behaviour for individual menu items using the
android:checkable attribute in the <item> element, or for an entire group with the android:checkableBehavior attribute in the <group> element.
Screen Shot 2016-02-15 at 09.51.22

android:checkableBehavior attribute accepts either:
  • single Only one item from the group can be checked (radio buttons)
  • all All items can be checked (checkboxes)
  • none No items are checkable

You can apply a default checked state to an item using the android:checked attribute in the <item> element and change it in code with the setChecked() method.

When a checkable item is selected, the system calls your respective item-selected callback method (such as
onOptionsItemSelected()). It is here that you must set the state of the checkbox, because a checkbox or radio button does not change its state automatically. You can query the current state of the item (as it was before the user selected it) with isChecked() and then set the checked state with setChecked().
Screen Shot 2016-02-15 at 09.55.29

If you don't set the checked state this way, then the visible state of the item (the checkbox or radio button) will not change when the user selects it. When you do set the state, the activity preserves the checked state of the item so that when the user opens the menu later, the checked state that you set is visible.

Note: Checkable menu items are intended to be used only on a per-session basis and not saved after the application is destroyed. If you have application settings that you would like to save for the user, you should store the data using Shared Preferences.

Menu Items Based on an Intent

Sometimes you'll want a menu item to launch an activity using an Intent (whether it's an activity in your application or another application). When you know the intent you want to use and have a specific menu item that should initiate the intent, you can execute the intent with startActivity() during the appropriate on-item-selected callback method (such as the onOptionsItemSelected() callback).

However, if you are not certain that the user's device contains an application that handles the intent, then adding a menu item that invokes it can result in a non-functioning menu item, because the intent might not resolve to an activity. To solve this, Android lets you dynamically add menu items to your menu when Android finds activities on the device that handle your intent.

To add menu items based on available activities that accept an intent:

Note: CATEGORY_SELECTED_ALTERNATIVE is used to handle the currently selected element on the screen. So, it should only be used when creating a Menu in onCreateContextMenu().
Screen Shot 2016-02-15 at 10.02.07

For each activity found that provides an intent filter matching the intent defined, a menu item is added, using the value in the intent filter's android:label as the menu item title and the application icon as the menu item icon. The
addIntentOptions() method returns the number of menu items added.

Note: When you call addIntentOptions(), it overrides any and all menu items in the menu group specified in the first argument.

Allowing your activity to be added to other menus

You can also offer the services of your activity to other applications, so your application can be included in the menu of others. Define an intent filter as usual, but be sure to include the
CATEGORY_ALTERNATIVE and/or CATEGORY_SELECTED_ALTERNATIVE values for the intent filter category.
Screen Shot 2016-02-15 at 10.08.34

Work on Lab5