the sub-menu itself. As with onCreateOptionsMenu()
, you should chain upward to the superclass, then add menu choices to the sub-menu. One limitation is that you cannot indefinitely nest sub-menus — a menu can have a sub-menu, but a sub-menu cannot itself have a sub-sub-menu.
If the user makes a menu choice, your activity will be notified via the onOptionsItemSelected()
callback that a menu choice was selected. You are given the MenuItem
object corresponding to the selected menu choice. A typical pattern is to switch()
on the menu ID (item.getItemId()
) and take appropriate action. Note that onOptionsItemSelected()
is used regardless of whether the chosen menu item was in the base menu or in a sub-menu.
Menus in Context
By and large, context menus use the same guts as option menus. The two main differences are how you populate the menu and how you are informed of menu choices.
First you need to indicate which widget(s) on your activity have context menus. To do this, call registerForContextMenu()
from your activity, supplying the View
that is the widget in need of a context menu.
Next you need to implement onCreateContextMenu()
, which, among other things, is passed the View
you supplied in registerForContextMenu()
. You can use that to determine which menu to build, assuming your activity has more than one.
The onCreateContextMenu()
method gets the ContextMenu
itself, the View
the context menu is associated with, and a ContextMenu.ContextMenuInfo
, which tells you which item in the list the user did the tap-and-hold over, in case you want to customize the context menu based on that information. For example, you could toggle a checkable menu choice based on the current state of the item.
It is also important to note that onCreateContextMenu()
gets called each time the context menu is requested. Unlike the options menu (which is built only once per activity), context menus are discarded once they are used or dismissed. Hence, you do not want to hold onto the supplied ContextMenu
object; just rely on getting the chance to rebuild the menu to suit your activity’s needs on demand based on user actions.
To find out when a context-menu choice was selected, implement onContextItemSelected()
on the activity. Note that you get only the MenuItem
instance that was chosen in this callback. As a result, if your activity has two or more context menus, you may want to ensure they have unique menu-item identifiers for all their choices so you can tell them apart in this callback. Also, you can call getMenuInfo()
on the MenuItem
to get the ContextMenu.ContextMenuInfo
you received in onCreateContextMenu()
. Otherwise, this callback behaves the same as onOptionsItemSelected()
, described in the previous section.
Taking a Peek
In the sample project Menus/Menus
at http://apress.com/, you will find an amended version of the ListView
sample (List
) with an associated menu. Since the menus are defined in Java code, the XML layout need not change and is not reprinted here.
However, the Java code has a few new behaviors, as shown here:
public class MenuDemo extends ListActivity {
TextView selection;
String[] items={'lorem', 'ipsum', 'dolor', 'sit', 'amet',
'consectetuer', 'adipiscing', 'elit', 'morbi', 'vel',
'ligula', 'vitae', 'arcu', 'aliquet', 'mollis',
'etiam', 'vel', 'erat', 'placerat', 'ante',
'porttitor', 'sodales', 'pellentesque', 'augue', 'purus'};
public static final int EIGHT_ID = Menu.FIRST+1;
public static final int SIXTEEN_ID = Menu.FIRST+2;
public static final int TWENTY_FOUR_ID = Menu.FIRST+3;
public static final int TWO_ID = Menu.FIRST+4;
public static final int THIRTY_TWO_ID = Menu.FIRST+5;
public static final int FORTY_ID = Menu.FIRST+6;
public static final int ONE_ID = Menu.FIRST+7;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
setListAdapter(new ArrayAdapter<String> (this,
android.R.layout.simple_list_item_1, items));
selection = (TextView)findViewById(R.id.selection);
registerForContextMenu(getListView());
}
public void onListItemClick(ListView parent, View v,
int position, long id) {
selection.setText(items[position]);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenu.ContextMenuInfo menuInfo) {
populateMenu(menu);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
populateMenu(menu);
return(super.onCreateOptionsMenu (menu));
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {