Using the contextual action mode
The contextual action mode is a system implementation of ActionMode
thatfocuses user interaction toward performing contextual actions. When auser enables this mode by selecting an item, a contextual action bar appears at the top ofthe screen to present actions the user can perform on the currently selected item(s). While thismode is enabled, the user can select multiple items (if you allow it), deselect items, and continueto navigate within the activity (as much as you're willing to allow). The action mode is disabledand 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 necessarilyassociated with the action bar. They operateindependently, even though the contextual action bar visually overtakes the action barposition.
If you're developing for Android 3.0 (API level 11) or higher, youshould usually use the contextual action mode to present contextual actions, instead of the floating context menu.
For views that provide contextual actions, you should usually invoke the contextual action modeupon 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 eachaction 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
orGridView
(allowing the user to select multipleitems and perform an action on them all).
The following sections describe the setup required for each scenario.
Enabling the contextual action mode for individual views
If you want to invoke the contextual action mode only when the user selects specificviews, you should:
- Implement the
ActionMode.Callback
interface. In its callback methods, youcan specify the actions for the contextual action bar, respond to click events on action items, andhandle other lifecycle events for the action mode. - Call
startActionMode()
when you want to show thebar (such as when the user long-clicks the view).
For example:
- Implement the
ActionMode.Callback
interface:private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() { // Called when the action mode is created; startActionMode() was called @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { // Inflate a menu resource providing context menu items MenuInflater inflater = mode.getMenuInflater(); inflater.inflate(R.menu.context_menu, menu); return true; } // Called each time the action mode is shown. Always called after onCreateActionMode, but // may be called multiple times if the mode is invalidated. @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return false; // Return false if nothing is done } // Called when the user selects a contextual menu item @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { switch (item.getItemId()) { case R.id.menu_share: shareCurrentItem(); mode.finish(); // Action picked, so close the CAB return true; default: return false; } } // Called when the user exits the action mode @Override public void onDestroyActionMode(ActionMode mode) { mActionMode = null; } };
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 useActionMode
APIs to make various changes to the CAB, such as revise the title andsubtitle withsetTitle()
andsetSubtitle()
(useful to indicate how many items areselected).Also notice that the above sample sets the
mActionMode
variable null when theaction mode is destroyed. In the next step, you'll see how it's initialized and how savingthe member variable in your activity or fragment can be useful. - Call
startActionMode()
to enable the contextualaction mode when appropriate, such as in response to a long-click on aView
:someView.setOnLongClickListener(new View.OnLongClickListener() { // Called when the user long-clicks on someView public boolean onLongClick(View view) { if (mActionMode != null) { return false; } // Start the CAB using the ActionMode.Callback defined above mActionMode = getActivity().startActionMode(mActionModeCallback); view.setSelected(true); return true; } });
When you call
startActionMode()
, the system returnstheActionMode
created. By saving this in a member variable, you canmake changes to the contextual action bar in response to other events. In the above sample, theActionMode
is used to ensure that theActionMode
instanceis not recreated if it's already active, by checking whether the member is null before starting theaction mode.
Enabling batch contextual actions in a ListView or GridView
If you have a collection of items in a ListView
or GridView
(or another extension of AbsListView
) and want toallow users to perform batch actions, you should:
- Implement the
AbsListView.MultiChoiceModeListener
interface and set itfor the view group withsetMultiChoiceModeListener()
. In the listener's callback methods, you can specify the actionsfor the contextual action bar, respond to click events on action items, and handle other callbacksinherited from theActionMode.Callback
interface. - Call
setChoiceMode()
with theCHOICE_MODE_MULTIPLE_MODAL
argument.
For example:
ListView listView = getListView();
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
listView.setMultiChoiceModeListener(new MultiChoiceModeListener() {
@Override
public void onItemCheckedStateChanged(ActionMode mode, int position,
long id, boolean checked) {
// Here you can do something when items are selected/de-selected,
// such as update the title in the CAB
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
// Respond to clicks on the actions in the CAB
switch (item.getItemId()) {
case R.id.menu_delete:
deleteSelectedItems();
mode.finish(); // Action picked, so close the CAB
return true;
default:
return false;
}
}
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// Inflate the menu for the CAB
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.context, menu);
return true;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
// Here you can make any necessary updates to the activity when
// the CAB is removed. By default, selected items are deselected/unchecked.
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
// Here you can perform updates to the CAB due to
// an invalidate()
request
return false;
}
});
That's it. Now 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 contextualaction bar is visible, users can select additional items.
In some cases in which the contextual actions provide common action items, you mightwant to add a checkbox or a similar UI element that allows users to select items, because theymight not discover the long-click behavior. When a user selects the checkbox, youcan invoke the contextual action mode by setting the respective list item to the checkedstate with setItemChecked()
.