
Enabling Contextual Action Mode for a view
A Context Menu provides additional options related to a specific view—the same concept as a right-click on the desktop. Android currently supports two different approaches: the floating Context Menu and Contextual Mode. Contextual Action Mode was introduced in Android 3.0. The older floating Context Menu could lead to confusion since there was no indication of the currently selected item and it didn't support actions on multiple items—such as selecting multiple emails to delete in one action.
Creating a Floating Context Menu
If you need to use the old style Context Menu, for example, to support preAndroid 3.0 devices, it's very similar to the Option Menu API, just different method names. To create the menu, use onCreateContextMenu()
instead of onCreateOptionsMenu()
. To handle the menu item selection, use onContextItemSelected()
instead of onOptionsItemSelected()
. Finally, call registerForContextMenu()
to let the system know you want Context Menu events for the view.
Since Contextual Mode is considered the preferred way to display context options, this recipe will focus on the newer API. Contextual Mode offers the same features as the floating Context Menu, but also adds additional functionality by allowing multiple item selection when using batch mode.
This recipe will demonstrate the setup of Contextual Mode for a single view. Once activated, with a long press, a Contextual Action Bar (CAB) will replace the Action Bar until Contextual Mode is finished.
Note
The Contextual Action Bar is not the same as the Action Bar and your activity does not need to include an Action Bar.
Getting ready
Use Android Studio to create a new project and call it ContextualMode
. Use the default Phone & Tablet option and select Empty Activity when prompted to add an Activity. Create a menu directory (res/menu
) as we did in the first recipe, Creating an Options menu, to store the XML for the contextual menu.
How to do it...
We will create an ImageView to serve as the host view to initialize Contextual Mode. Since Contextual Mode is usually triggered with a long press, we will set up a long click listener in onCreate()
for the ImageView
. When called, we will start Contextual Mode and pass an ActionMode
callback to handle the Contextual Mode events. Here are the steps:
- We will start by adding two new string resources. Open the
strings.xml
file and add the following:<string name="menu_cast">Cast</string> <string name="menu_print">Print</string>
- With the strings created, we can now create the menu by creating a new file in
res/menu
calledcontext_menu.xml
using the following XML:<?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_cast" android:title="@string/menu_cast" /> <item android:id="@+id/menu_print" android:title="@string/menu_print" /> </menu>
- Now add an
ImageView
toactivity_main.xml
to serve as the source for initiating Contextual Mode. Here is the XML for the ImageView:<ImageView android:id="@+id/imageView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_centerHorizontal="true" android:src="@mipmap/ic_launcher"/>
- With the UI now set up, we can add the code for Contextual Mode. First, we need a global variable to store the
ActionMode
instance returned when we callstartActionMode()
. Add the following line of code toMainActivity.java
below the class constructor:ActionMode mActionMode;
- Next, create an
ActionMode
callback to pass tostartActionMode().
Add the following code to theMainActivity
class below the code in the previous step:private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() { @Override public boolean onCreateActionMode(ActionMode mode, Menu menu) { mode.getMenuInflater().inflate(R.menu.context_menu, menu); return true; } @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return false; } @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { switch (item.getItemId()) { case R.id. menu_cast: Toast.makeText(MainActivity.this, "Cast", Toast.LENGTH_SHORT).show(); mode.finish(); return true; case R.id. menu_print: Toast.makeText(MainActivity.this, "Print", Toast.LENGTH_SHORT).show(); mode.finish(); return true; default: return false; } } @Override public void onDestroyActionMode(ActionMode mode) { mActionMode = null; } };
- With the
ActionMode
callback created, we just need to callstartActionMode()
to begin Contextual Mode. Add the following code to theonCreate()
method to set up the long click listener:ImageView imageView = (ImageView)findViewById(R.id.imageView); imageView.setOnLongClickListener(new View.OnLongClickListener() { public boolean onLongClick(View view) { if (mActionMode != null) return false; mActionMode = startActionMode(mActionModeCallback); return true; } });
- Run the program on a device or emulator to see the CAB in action.
How it works...
As you saw in Step 2, we have used the same menu XML to define the contextual menu as the other menus.
The main piece of code to understand is the ActionMode
callback. This is where we handle the Contextual Mode events: initializing the menu, handling menu item selections, and cleaning up. We start Contextual Mode in the long press event with a call to startActionMode()
by passing in the ActionMode
callback created in Step 5.
When action mode is triggered, the system calls the onCreateActionMode()
callback, which inflates the menu and displays it in the Contextual Action Bar. The user can dismiss the Contextual Action Bar by pressing the back arrow or the back key. The CAB is also dismissed when the user makes a menu selection. We show a Toast to give a visual feedback for this recipe but this is where you would implement your functionality.
There's more...
In this example, we store the ActionMode
returned from the startActionMode()
call. We use it to prevent a new instance from being created when the Action Mode is already active. We could also use this instance to make changes to the Contextual Action Bar itself, such as changing the title with the following:
mActionMode.setTitle("New Title");
This is particularly useful when working with multiple item selections as we'll see in the next recipe.
See also
- See the next recipe, Using Contextual Batch Mode with a ListView, to work with multiple items selection