Android Contextual Action Mode Over Toolbar - Androhub

Toolbar Action Mode Banner

Android Contextual Action Mode Over Toolbar

You have seen Action Mode Menu in many apps like Whatsapp, Hike, Gmail, etc. while selecting multiple chats/emails on long press i.e. called Action Mode

What is Action Mode?

It represents a contextual mode of the user interface. Action modes can be used to provide alternative interaction modes and replace parts of the normal UI until finished. Examples of good action modes include text selection and contextual actions.

How to Use?

For Using Action Mode we need to extend our class with ActionMode.Callback. Its a Callback interface for action modes. Supplied to startSupportActionMode(Callback) (Callback)}, a Callback configures and handles events raised by a user’s interaction with an action mode.

An action mode’s lifecycle is as follows:

Example

In this tutorial, we are going to learn how to implement Action Mode on ListView and RecyclerView item selection.

Prerequisite:

  1. ListView
  2. RecyclerView
  3. Toolbar
  4. Tab Bar Layout

VIDEO DEMO

1. Create a new project in Android Studio by navigating to File ⇒ New ⇒ New Project and fill required details. By default my activity is MainActivity.java.

2. Open build.gradle and include this libraries show below:

3. Open strings.xml located under res=>values folder and add following strings.

4. Create new xml file naming colors.xml  under res=>values folder and add the following colors.

5. Open styles.xml located under res=>values folder and add following styles.

Some important part about above styles.xml:

  • windowActionModeOverlay should be true otherwise you will get action mode above toolbar not overlays the toolbar.
action mode above toolbar
action mode above toolbar
  • actionModeBackground is used to set custom background to your action mode menu else it will take default theme color.
default theme action mode
default theme action mode

6. Create activity_main.xml and add the following code. In this i am using Tab Bar Layout for creating tabs.

7. Create list_view_fragment.xml for ListView fragment and add ListView to it.

8. Like above we also need to create recycler_view_fragment.xml for RecyclerView fragment and add the RecyclerView to it.

9. Now we need to create custom row for both ListView and RecyclerView. So we can use same xml for both, so create new xml file naming item_row.xml.

10. Now come to MainActivity.java and add the following code for adding tabs and fragments to it.

11. Create new ViewPagerAdapter.java class for ViewPager tab fragments.

12. For Custom ListView and RecyclerView we need to create getter and setter class naming Item_Model.java.

13. Now create ListView_Fragment.java and add the following code. In this i am implementing ActionMode on ListView long click item and starting Action Mode.

14. Now for ListView adapter create new adapter class naming ListView_Adapter.java and add the following code. In this last some methods do the main thing for item selection.

15. Now this is main class in which Action Mode things happen. So create new class name Toolbar_ActionMode_Callback.java  and add the following code. In this we are inflating action mode menu and implementing click listener over menu items.

16. For action mode menu create menu inside menu folder and add the following menus to it.

17. Now for RecyclerView create new java class naming RecyclerView_Fragment.java and add the following code. It is mostly same as ListView_Fragment.java.

18. Create ViewHolder for RecyclerView adapter naming DemoViewHolder.java and add the following code.

19. For RecyclerView adapter create new java class naming RecyclerView_Adapter.java and add the code.

20. For RecyclerView click listener we need to create a interface naming RecyclerClick_Listener.java and the following code.

21. Now for implementing touch listener over Recycler View create RecyclerTouchListener.java and implement the interface that we created and add the following code to it.

22. Finally, all done – now you can also create ActionMode.

Thanks. 🙂

 

30 Comments

Test
Wednesday, October 5th, 2016

Nice Example ! Thanks !

Peter
Monday, December 5th, 2016

Thanks for this excellent tutorial!

Ralf
Monday, December 19th, 2016

How can I save the selected items? So that when I rotate the phone they are selected correctly.

Dr. Droid
Monday, December 19th, 2016

Hi Ralf,

To save the selected items please check the below link:
http://stackoverflow.com/questions/20209015/how-do-i-preserve-the-state-of-a-selected-spinner-dropdown-item-on-orientation-c

Let me know if you need any assistance.
Thanks

Ralf
Tuesday, December 20th, 2016

The problem is that when selecting multiples items from the listview or recyclerview, and then changing the orientation (example: portrait to landscape) of the device, the items are no longer selected. How do I keep them selected?

tks,

Dr. Droid
Wednesday, December 21st, 2016

Hi Ralf,

For saving listview/recyclerview selection you need to save the selection state in onSaveInstanceState(Bundle outState) method only and get it back in
onCreate(Bundle state){
if( state != null ){
//Get your selected state.
}
}

There are so many solutions available over stackoverflow.
Thanks

Ralf
Wednesday, December 21st, 2016

Hi Dr.Droid,

Thanks for help! =)

Bibin
Wednesday, March 29th, 2017

Hi,

Is there any property to change the background colour of toolbar when action mode enabled. I mean dynamically change toolbar color when action mode enabled.

Dr. Droid
Wednesday, March 29th, 2017

Hi Bibin,

In above article if you see the video, in video if user enable action mode then toolbar color is changing.
If you mean something different then let me know.

Thanks

johson
Thursday, May 4th, 2017

private void implementListViewClickListeners() {
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView parent, View view, int position, long id) {
//If ActionMode not null select item
if (mActionMode != null)
onListItemSelect(position);
}
});
listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView parent, View view, int position, long id) {
//Select item on long click
onListItemSelect(position);
return true;
}
});
}

i was told that i need an identifier in the AdapterView in ListView.java class

Dr. Droid
Thursday, May 4th, 2017

Hi Johnson,

Sorry!! But i didn’t get your problem. Can you please make your question clear?

Thanks

Rishav Chudal
Friday, July 14th, 2017

Hello there,

I have looked on your tutorial and I have concerned with other tutorials too. The code implementation is slightly different than yours but the concept is same.
I also have two tabs and I am trying to handle all possible touch given by the user. Suppose I am selecting items from the recycler view list of one tab & accidently or for purpose I click on the another tab. Then I have implemented action mode to be destroyed. And returning to previous tab gives me the recycler view items, on long press of the items shows the action mode too but the items are not selectable. But if again I click on the another tab & return back to previous tab, the selection is working properly. The selection of items is working in alternate fashion when I click in another tab.
Can you figure out something???

Pasquale
Friday, July 21st, 2017

The windowActionModeOverlay isn’t wotking

Pasquale
Friday, July 21st, 2017

Sorry, it works 🙂

coriane
Friday, July 28th, 2017

actionmode.finish() fait planter mon appli. Besoin d’aide!!!

Dr. Droid
Friday, August 11th, 2017

Hi Coriane,

Can you please tell me what exception you are getting?

Thanks

harshil
Tuesday, August 22nd, 2017

new MainActivity().getFragment(position) return null in Toolbar_ActionMode_Callback

Dr. Droid
Tuesday, August 22nd, 2017

Hi Harshil,

Please check the position which you are passing may be the position is not valid.

Thanks

harshil
Tuesday, August 22nd, 2017

i have use position 0 that is valid for my viewPagerAdapter
like this: Fragment listFragment = new NewActivity().getFragment(0);

and i have tried this also in my NewActivity().
public Fragment getFragment(int pos) {
/*List fragments = getSupportFragmentManager().getFragments();*/
Fragment frag = viewPagerAdapter.getItem(pos);
// Fragment frag = getSupportFragmentManager().getFragments().get(pos);
// Fragment frag = (Fragment) viewPagerAdapter.instantiateItem(viewPager, viewPager.getCurrentItem());
return frag;
}

all gives me NullPointerException why?
everything work file except this case.

Dr. Droid
Tuesday, August 22nd, 2017

Hi Harshil,

Can you send me your over my mail id or if possible can connect via TeamViewer so that i can fix it.

Thanks

harshil
Tuesday, August 22nd, 2017

finally, i have solved my issue.

Fragment listFragment = new NewActivity().getFragment(0);

In the above case NewActivity every time gives me new object. so all values are null. that’s why NullPointerException occur in my case.

so, i change my code and i remove function getFragment() from NewActivity and directly pass fragment object to getter setter class and pass this object to my each fragments when activity initializing fragments and now i can access the current fragment object.

Thank you.

john
Thursday, February 22nd, 2018

thanks for your effort to explain.

serhii
Sunday, January 13th, 2019

holder.itemView
.setBackgroundColor(mSelectedItemsIds.get(position) ? 0x9934B5E4
: Color.TRANSPARENT);
didn’t work for me . What means itemView? And how can I fix and set background color for selected items?

Dr. Droid
Monday, January 14th, 2019

Hi Serhii,

Here itemView is the root layout view of the item row. You have to get id of your root layout and set the background color to it.

Thanks

saman
Saturday, April 20th, 2019

thank you bro. your example was so useful for me. nice one.
harshil: i had same problem , fixed bye your approach.

Dilip Pashi
Monday, April 29th, 2019

how to implement select all list in this code

Dr. Droid
Tuesday, April 30th, 2019

Hi Dilip,

To do select all you have to make a for loop for your array list and add the positions to mSelectedItemsIds.

Thanks

mydroid
Friday, October 18th, 2019

Thx! u really saved my day! You are the first one who mentions the importance of setting “windowActionModeOverlay” = true. That was the missing part in my code.

Ali Khan
Thursday, March 26th, 2020

Thx! u really saved my day!…… I want to ask you something. If I select some rows from listview fragment and move to recycler view fragment action bar is still visible…..how I can hide this.

Dr. Droid
Friday, March 27th, 2020

Hi Ali,

For this when you switch between tabs you have to call this method to finish action mode: mActionMode.finish(); and also clear the selected list.

Thanks

Post comment

Your email address will not be published. Required fields are marked *