Free Android app covering all aspects of addiction, including prevention and treatment

Android RecyclerView. Multiple selections. Part 2

  • Written by  Clive

Choosing multiple items in a RecyclerView list: part 2

RecyclerView choice mode multiple selections tutorial

We’re going to show you how to select multiple items in a RecyclerView list and then save all the selected items’ details at the press of a button.

You’ll easily be able to customise the code to suite your needs.

Have you seen part 1 where we lay the foundation?

The RecyclerView

We won’t discuss, in any detail, how to use a RecyclerView.

Check out this tutorial, Android’s RecyclerView and CardView widgets, if you need to know more about using the RecyclerView in your app?  

Here are the basics on using a RecyclerView:

  • Get a reference to the RecyclerView
  • Add a listener to it so that we can react to the user’s touch
  • Get an adapter to feed our list of ItemData to the RecyclerView
  • Set the adapter on our RecyclerView
  • Set the layout manager for our RecyclerView to manage the positioning and recycling of views within the RecyclerView

The RecyclerView Adapter

We pass the data that we want to display to the adapter. The adapter feeds this data to the RecyclerView, managing the positioning and recycling of views within the RecyclerView.

We’ve created our own custom RecyclerView Adapter, MyRecyclerViewAdapter and instantiate it in the MainActivity, passing its constructor the activity’s context as well as our data, a list of ItemData containing an id and associated text string.

We use the adapter to bind our data to the views displayed in the RecyclerView.

Want to blow your mind? Check out this tutorial, Android Adapters: What are Adapters?

Our custom RecyclerView adapter uses a custom view holder to display each item in a single row.

The Custom ViewHolder

Here’s the custom view holder’s code:

Android RecyclerView choice mode adapter custom ViewHolder

The view holder contains the views for each item that is displayed in a row

The CustomViewHolder contains the views for each item. Each item is displayed in a row and contains three text views:

  • itemIdTextView – displays an id for the item
  • itemTextView – displays a line of text for each item
  • choiceModeTextView – displays the green asterisk (*) indicating that the RecyclerView list is now in action mode and the user can make multiple selections

Creating the view holder: onCreateViewHolder()

We create a view holder, which will contain one of our data items, in the adapter’s onCreateViewHolder() method. This is where we inflate the layout for each of the displayed rows.

The view holder will be reused for each of the rows.

Here’s the row_layout.xml  file:

Android RecyclerView choice mode adapter custom ViewHolder row layout

The row_layout.xml layout file is inflated in the adapter’s onCreateViewHolder() method. We use it to display each row in the RecyclerView

Putting the data in the view: onBindViewHolder()

This is where all the magic happens.

The RecyclerView calls the onBindViewHolder() method to display a row at the position passed as a parameter. It replaces the current item in the view holder with the one specified by position (the item of data in the adapter at the given adapter position).

So here’s a breakdown of the onBindViewHolder() methods’ code:

Android RecyclerView choice mode adapter onBindViewHolder()

  • Get the data at the given adapter position out of our ItemData list and set these values in the view holders’ text views
  • Next, call setItemUnSelected(holder) to make sure that all of the displayed itemTextView views (each row) is deselected (displayed as black text)

Here’s the next bit of the onBindViewHolder() methods’ code:

Android RecyclerView choice mode adapter onBindViewHolder() code

This code is at the heart of our action mode. It takes care of changing the selected items text colour as well as displaying the action mode indicator

So what’s happening here?

  • We check whether the list of selected items contains selected ids. If it does:
    • Then we make sure that the green action mode indicator is showing by calling setViewIndicatingChoiceMode(holder)
    • Then we check if the item that we are about to display is in the selected item list:
      • If it is then we set its text colour to red by calling setItemSelected()
      • If not then we do nothing (we leave the text colour black)
  • If there are no selected items then we make sure that the action mode indicator is not showing by calling setViewIndicatingNormalMode(holder)

The action mode indicator: setViewIndicatingChoiceMode(holder)

This method gets a reference to the choiceModeIndicator text view and makes it visible. This lets the user know that they can now make multiple selections.

Android RecyclerView choice mode indicator

Show the user that the app is in action mode by calling setViewIndicatingChoiceMode()

Marking an item as selected: setItemSelected(holder)

Call setItemSelected() to mark an item as selected.

This method gets a reference to the itemText TextView and sets its colour to red.

Android RecyclerView choice mode select item

Call setItemSelected() to mark an item as selected

Unselecting an item

Call setItemUnselected() to deselect a selected item.

This method simply sets the selected TextView’s colour to black.

So how do we go about selecting items?

Check out our Free Clip Art Gold and Open Images Gold apps which copy Google’s Photos app’s way of showing selections:

Android RecyclerView choice mode deselect item

Deselected items

Android RecyclerView choice mode select item

Selected items

The image size is reduced by adding padding. An empty circle displays indicating that we’re in action mode and the selected item’s circle includes a blue tick

And here’s a simple version of how we did it in this tutorial:

Android RecyclerView choice mode deselect item

Deselected item

Android RecyclerView choice mode select item

Selected item

A green asterisk (*) displays, indicating that we’re in action mode and the selected item’s text colour changes to red

Listening for the user’s touch: The listener

We need to listen for when the user touches the text in one of the RecyclerView rows.

To do this, we create a custom touch listener, MyRecyclerViewOnItemTouchListener which implements the RecyclerView.OnItemTouchListener class, which allows us to do this.

Add the custom listener to the RecyclerView

Android RecyclerView choice mode select item addOnItemTouchListener()

Add our custom listener to our RecyclerView

Our custom listener has three required methods:

Android RecyclerView choice mode select item onInterceptTouchEvent()

The RecyclerView.OnItemTouchListener’s required methods

We’re only interested in the onInterceptTouchEvent() method which listens for all touch events.

The onInterceptTouchEvent() method intercepts the touch and passes it on to our custom listener’s  gesture detector’s onTouchEvent() method to process.

The gesture detector

The gesture detector detects gestures and motion events from the event that is passed to it via the listener’s onInterceptTouchEvent() method .

We’re using the support library so we use the GestureDetectorCompat class for our gesture detector, gestureDetectorCompat.

The gesture detector’s onTouchEvent() method analyses the touch event and passes it on to its listener’s appropriate callback method.

Our gesture detector uses the SimpleOnGestureListener() which has a number of callback methods. We’re really only interested in two of them:

  • onSingleTapConfirmed() - which is triggered by single touches
  • onLongPress() - which is triggered by long-presses

Selecting an item for the first time: making that first selection

Long-pressing an item for the first time puts the RecyclerView into action mode, allowing the user to make multiple selections.

This is what happens when the user selects an item for the first time:

  • The app enters action mode
  • The toolbar changes into an action mode toolbar
  •  The Save action menu item icon replaces the overflow menu

Nothing happens if the user touches an item if the app is not in action mode.

So what happens in the onLongPress() method?

Long-pressing an item for the first time:

  • The RecyclerView.OnItemTouchListener’s onInterceptTouchEvent() method grabs the touch event and passes it on to the gestureDetectorCompat.onTouchEvent(e) method
  • The gesture detector recognises the event as a long press and triggers the SimpleOnGestureListener() callback, onLongPress() method

Let’s have a look at the code:

Android RecyclerView choice mode select item onInterceptTouchEvent() long-press

Long-pressing an item for the first time enables action mode

So what’s happening here?

  • isInChoiceMode – the app is in normal mode by default (the normal toolbar is showing and nothing is selected) and isInChoiceMode is set to false. We now set isInChoiceMode to true. Nothing will happen from now on if the user long-presses an item
  • showActionModeToolbar() - we show the action mode toolbar by calling showActionModeToolbar()
  • findChildViewUnder() – we get the selected view contained in the touch event
  • setHapticFeedbackEnabled() and performHapticFeedback() ensures that the device vibrates and emits a sound when the view is touched. We use the LONG_PRESS flag so that the feedback is triggered on a long press
  • getChildAdapterPosition() – gets the position of the selected item in the adapter. We’ll use this to find the selected item in our list of items supplied to the adapter
  • we use an if statement to check whether it’s a valid position
  • addItemIdToSelectedList() – we then add the selected item to the selected list of items (see more on the addItemIdToSelectedList())
  • notifyDataSetChanged() – we call notifyDataSetChanged() to force the RecyclerView to rebind and relayout its views. This changes the selected text colour and displays the green asterisk indicating that the app is now in action mode
  • updateToolbar() – updates the selected items counter in the toolbar
  • The user can now make more selections or deselect selected items by single-touching an item. Long-pressing will not work as isInChoiceMode is true

So what happens when the user single-taps an item? The onSingleTapConfirmed() method

Single-touching an item selects or deselects it.

Here’s the code:

Android RecyclerView choice mode select item onInterceptTouchEvent() onSingleTapConfirmed()

Single-touching an item selects or deselects it

So what’s happening here?

  • isInChoiceMode – single-touch will only work if isInChoiceMode is true
  • findChildViewUnder() – we get the selected view contained in the touch event
  • setHapticFeedbackEnabled() and performHapticFeedback() ensures that the device vibrates and emits a sound when the view is touched. We use the FLAG_IGNORE_VIEW_SETTING  flag so that the feedback is triggered when the view is touched, no matter what the current feedback settings are for that view
  • getChildAdapterPosition() – gets the position of the selected item in the adapter. We’ll use this to find the selected item in our list of items supplied to the adapter
  • We use an if statement to check whether it’s a valid position
  • addItemIdToSelectedList() – we then add the selected item to the selected list of items (see more on the addItemIdToSelectedList())
  • notifyDataSetChanged() – we call notifyDataSetChanged() to force the RecyclerView to rebind and relayout its’ views. This changes the selected text colour and displays the green asterisk indicating that the app is now in action mode
  • updateToolbar() – updates the selected items counter in the toolbar
  • The user can now make more selections or deselect selected items by single-touching an item. Long-pressing will not work as isInChoiceMode is true
  • Deselecting the last selected item disables the action mode

Adding an item to the list of selected items: The addItemIdToSelectedList() method

The selectedItemIdList list contains the ids of the selected items.

We use the selectedItemIdList list in the RecyclerView adapter’s onBindViewHolder() method to:

  • set the action mode indicator (the green asterisk) to show the user that we are in action mode
  • change the selected items’ text colour to indicate whether or not it has been selected

We use the addItemIdToSelectedList() method to add or remove the selected item’s id to the selectedItemIdList list.

Here’s the code:

Android RecyclerView choice mode select item adding selected item

Call addItemIdToSelectedList() method to add or remove selected items

So what happens here?

  • We pass this addItemIdToSelectedList() method the selected items’ id
  • Then we check whether or not the id is already in our selected items list of ids, adding the id to the list if it’s not already in the list
  • If the id is already in the list, then we need to remove it as the user has deselected it
  • Finally, if the list is empty then we need to exit the action mode and show the normal toolbar. We do this by setting isInChoiceMode to false and calling showNormalToolbar()

Updating the selected items counter: The updateToolbar() method

The updateToolbar() method updates the selected item counter displayed in the toolbar.

Android RecyclerView choice mode select item updating toolbar

Update the counter by making the TextViews visible and then display the size of the selected items counter list

So what’s happening here?

  • selectedItemsCounter – get the size of the selected items list. This represents the number of selected items
  • if there is at least 1 selected item then we can go ahead and display the total in the toolbar
  • textViewCounter – set this TextView to visible
  • textViewTitle – set this TextView to visible
  • show the total number of selected items in the textViewCounter TextView

That’s it. I hope that you have found this tutorial helpful.

Download the project's code here download35