≡ Menu

How to Create Option, Context, and Popup Menus in Android App

In an Android App, menu is an efficient and friendly way to display multiple options, from which users can choose what they like.

Android provides the following three type of menus:

  1. Options menu
  2. Context menu
  3. Popup menu


Once you understand the fundamentals of how to write an android app, the next logical step is to create a simple android app that has some menu items.

This tutorial will explain in detail how the Android menu works along with the code snippets.

Each of these menu have different usage and have different work flow as shown in the table below.

Initialize Prepare Click Event Batch Mode
Options Menu X X X
Context Menu – Floating X X
Context Menu – Action Mode X X X X
Popup Menu X

Part I. Common Menu Operations

The two most common operations for a menu are initialization, and action for an item select event.

1. Initialize a Menu

From the view of user program, operation to a menu is done by the Menu interface. In the initial callback, we can call corresponding method of the interface to do the initial job.

The most common way is to use a MenuInflater to inflate menu from a XML menu resource definition.

MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.game_menu, menu);

The hierarchy of menu can be well defined with the <item> and <menu> xml notion.

A menu item is defined in <item>, and we can set properties such as title, id and icon for each menu item. A submenu is a menu that included inside a .

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/menu_item1" android:title="@string/menu_item1"/ >
<item android:id="@+id/menu_item2" android:title="@string/menu_item2" >
<!-- "file" submenu -->
    <menu>
        <item android:id="@+id/sub_menu_item1"
            android:title="@string/sub_menu_item1" />
        <item android:id="@+id/sub_menu_item2"
            android:title="@string/sub_menu_item2" />
    </menu>
</item>
</menu>

In the above example, please note that the title property should be referred to a predefined string resource. For the id property, the “+” can be used to create a new id resource.

2. Action for the selection event

The following is a sample code snippet for the menu item action:

// Handle item selection
switch (item.getItemId()) {
  caseR.id. menu_item1:
    //act for menu_item1
    return true;
  caseR.id. sub_menu_item1:
    //act for sub_menu_item1
    return true;
  default:
    //pass the event to parent, for options menu, use below
    return super.onOptionsItemSelected(item);
}

In the above example, please note the following:

  • For the menus items that do not have android:onClick property, there is always a default callback function for click event, which takes the in action menu item as input, and return a Boolean value that indicates whether the event is handled.
  • For the not interested item, just returns with the call of callback function from the super class.
  • Usually, ID retrieved by MenuItem.getItemId() method is used to identify the menu item.
  • For menu created by XML menu resource, as the compiler will guarantee that all the IDs are unique, it’s safe to distinguish menu item by ID.
  • But for programmatically created menu items, it must be assured by the programmer that menu ID is not conflict with each other.

Part II. Menus in Android

1. Options Menu

For Android 2.3.x (API level 10) or lower, the options menu will be shown in the bottom of screen with a 2×3 grid layout, on the press of Menu button. For Android 3.0 (API level 11) and higher, the menu is placed in the action bar, and will be expanded when clicked. When using ADT, the options menu will be created by default for activity.

Initialize the Menu

This callback is used for initialization purpose, which will only be called once when the menu is shown for the first time.

@Override
public boolean onCreateOptionsMenu(Menu menu) {
  // Inflate the menu; this adds items to the action bar if it is present.
  getMenuInflater().inflate(R.menu.main, menu);
  return true;
}

Update the Menu

After the initialization, modification should be done in onPrepareOptionsMenu callback, in which we can add/remove/modify the menu according to the working status of the program.

On Android 2.3.x and lower, the callback is always called before showing the option menu to user. On Android 3.0 or higher, the invalidateOptionsMenu() should be called so as to trigger the onPerpareOptionsMenu().

@Override
public boolean onPrepareOptionsMenu(Menu menu) {
    // Do the enable/disable/modification here
    return super.onPrepareOptionsMenu(menu);
}

2. Context Menu

Context Menu is used when the content is contextually related to the place/view where a menu is triggered.

Android provides the following two kinds of context menu:

  1. Floating context menu – This is displayed next to a view when it is long pressed
  2. Action mode context menu – This shows an action bar when the view is long pressed. In action bar mode, it is also possible to select multiple items to do a batch operation.

a) Floating Context Menu

Declare Context Menu Provider

For the view that registers as context menu provider, OS will trigger the context menu sequence when long-lick event of the view is received.

Registration for the context menu should be done by calling Activity.registerForContextMenu() with the view instance as argument.

public void registerForContextMenu(View view) {
  view.setOnCreateContextMenuListener(this);
}

Initialize the Menu

The callback function of menu initial is onCreateContextMenu.

Additionally, there is a View instance passed to it, which can be used to determinate the content of menu according to different views.

Floating context menu does not have an update callback function, which means we should inflate/initial the menu every time. So, when the context menu contains too much items, an attention of lag should be paid.

@Override
public void onCreateContextMenu(ContextMenu menu, View v,
   	ContextMenuInfomenuInfo) {
  //Do the initial here
  super.onCreateContextMenu(menu, v, menuInfo);
}

Action for a selection event

Similar to options menu, floating contextual menu has a callback function of click event, the onContextItemSelected.

@Override
public boolean onContextItemSelected(MenuItem item) {
  // Do the action by id here
  return super.onContextItemSelected(item);
}

b) Contextual Action Mode

On the first selection of an item, the action mode that shows a contextual action bar on the top of screen will be triggered, and then multiple sections can be done. Please note that API level 11 is needed for action mode.

Implement the ActionMode Callback

Action mode employs a unify interface that includes all of the callbacks: onCreateActionMode, onPrepareActionMode, and onActionItemClicked for initialization, preparation and action respectively. The action mode argument can be used to control the status of action mode, such as ActionMode.finish() to exit from the action mode.

private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {
  @Override
  public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
    // TODO Auto-generated method stub
    return false;
  }
  @Override
  public void onDestroyActionMode(ActionMode mode) {
    // TODO Auto-generated method stub
  }
  @Override
  public boolean onCreateActionMode(ActionMode mode, Menu menu) {
    // TODO Auto-generated method stub
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
  }
  @Override
  public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
    // TODO Auto-generated method stub
    return false;
  }
};

Start the Action Mode

Action mode should be triggered by user program, usually on the event of long click.

View.setOnLongClickListener(new View.OnLongClickListener() {
  @Override
  public boolean onLongClick(View v) {
    // Trigger the action mode
    if (mActionMode != null)
      return false;
      mActionMode = MainActivity.this.startActionMode(mActionModeCallback);
      //getActivity().startActionMode(mActionModeCallback);
  }
});

c) Batch Action Mode

For ListView, GridView, and any extension of AbsListView, a batch action mode can be triggered via the MultiChoiseModeListener, which inherits ActionMode.Callback interface for action mode support, and also implements onItemCheckedStateChanged for item checked event support.

//ListViewlistView = getListView(); 
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL); 
listView.setMultiChoiceModeListener(new MultiChoiceModeListener() {

  @Override
  public boolean onActionItemClicked(ActionMode arg0, MenuItem arg1) {
    // TODO Auto-generated method stub
    return false;
  }
  @Override
  public boolean onCreateActionMode(ActionMode arg0, Menu arg1) {
    // TODO Auto-generated method stub
    getMenuInflater().inflate(R.menu.main, arg1);
    return true;
  }
  @Override
  public void onDestroyActionMode(ActionMode arg0) {
    // TODO Auto-generated method stub
  }
  @Override
  public boolean onPrepareActionMode(ActionMode arg0, Menu arg1) {
    // TODO Auto-generated method stub
    return false;
  }
  @Override
  public void onItemCheckedStateChanged(ActionMode arg0, int arg1,
                 	long arg2, boolean arg3) {
    // TODO Auto-generated method stub
  }
});

3. Popup Menu

Popup menu is a menu that anchors to a view. Be different with other menus described above, PopupMenu is a class belongs to the Widget package, and user program can initial and show a popup menu on the action of any event.

Initialize and display popup menu

A typical popup initialization can be done as shown in the following code-snippet.

PopupMenu popup = new PopupMenu(this, view);
getMenuInflater().inflate(R.menu.main, popup.getMenu());
popup.show();

Action for selected event

Popup menu item click event will be pass to onMenuItemClick() if the anchor view implements the PopupMenu.OnMenuItemClickListener.

@Override
public boolean onMenuItemClick(MenuItem item) {
  return false;
}

Otherwise, a listener handle should be registered by the call of PopupMenu.setOnMenuItemClickListerner();

popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
  @Override
  public boolean onMenuItemClick(MenuItem item) {
    // TODO Auto-generated method stub
    return false;
  }
});

Part III. Where is the Menu Instance?

The question come into mind when playing with android menu for the first time is that, initial callbacks only manipulate the menu through an interface.

But, where is the menu instance exactly? We will take options menu as an example.

The calling stack snippet of options menu initial is shown below:

PhoneWindow.mInvalidatePanelMenuRunnable -> 
PhoneWindow.doInvalidatePanelMenu -> 
PhoneWindow.preparePanel ->
Activity.onCreatePanelMenu ->
Activity.onCreateOptionsMenu

Before passing to the callback of Activity, the menu as an instance of MenuBuilder is created in PhoneWindow.initializePanelMenu, which is called inside PhoneWindow.preparePanel().

Please note that the following code snippet is taken from Android 4.3, and re-edited with not related code section trimmed off.

PhoneWindow.java:
public final boolean preparePanel(PanelFeatureStatest, KeyEvent event) {
  // code trimmed
  if (st.createdPanelView == null) {
    // Init the panel state's menu--return false if init failed
    if (st.menu == null || st.refreshMenuContent) {
      if (st.menu == null) {
        if (!initializePanelMenu(st) || (st.menu == null)) {
          return false;
        }
      }
      if (mActionBar != null) {
        if (mActionMenuPresenterCallback == null) {
          mActionMenuPresenterCallback = new ActionMenuPresenterCallback();
        }
        mActionBar.setMenu(st.menu, mActionMenuPresenterCallback);
      }
      // Call callback, and return if it doesn't want to display menu.
      // Creating the panel menu will involve a lot of manipulation;
      // don't dispatch change events to presenters until we're done.
      st.menu.stopDispatchingItemsChanged();
      if ((cb == null) || !cb.onCreatePanelMenu(st.featureId, st.menu)) {
        // Ditch the menu created above
        st.setMenu(null);
        if (mActionBar != null) {
          // Don't show it in the action bar either
          mActionBar.setMenu(null, mActionMenuPresenterCallback);
        }
        return false;
      }
      st.refreshMenuContent = false;
    }
    // code trimed
  }
}
protected boolean initializePanelMenu(final PanelFeatureStatest) {
  Context context = getContext();
  // code trimed
  finalMenuBuilder menu = new MenuBuilder(context);
  menu.setCallback(this);
  st.setMenu(menu);
  return true;
}
Add your comment

If you enjoyed this article, you might also like..

  1. 50 Linux Sysadmin Tutorials
  2. 50 Most Frequently Used Linux Commands (With Examples)
  3. Top 25 Best Linux Performance Monitoring and Debugging Tools
  4. Mommy, I found it! – 15 Practical Linux Find Command Examples
  5. Linux 101 Hacks 2nd Edition eBook Linux 101 Hacks Book

Bash 101 Hacks Book Sed and Awk 101 Hacks Book Nagios Core 3 Book Vim 101 Hacks Book

Comments on this entry are closed.

  • Giacomo December 19, 2013, 8:48 am

    I have an advice to give you: if I were you I would put some images for showing the result of the code

  • Anonymous February 17, 2017, 12:04 am

    Thankyou..
    Can you please give one example of onPrepareOptionsMenu?
    How to update menu?