Drag selection of RecyclerView items
Google Photos is fascinating application, I admire every bit of it. Selection of photos is done right and seamless. Unlike old pal ListView
, RecyclerView
does not have any method or feature for selection (single or multiple), this post will give you insights how to respond on events for multiple item selection using ItemTouchListener
and GestureDetector
.
Selection in short
Material design guidelines suggest that selection of list items should be done by initial long press and dragging over items once the first item is selected with long press .
Code
In this post I will omit the UI aspect after selection, but only discuss the handling the motion event and dispatching for further consuming of the refined events.
For selection session to start we have to wait for long press event to occur on the ViewHolder
using GestureDetector
in onLongPress()
method. We keep reference of it for later, to use it as first condition to start selection on ACTION_MOVE
. Once we have the long pressed ViewHolder
, we have to look for ViewHolder
that is under MotionEvent.getX()
and MotionEvent.getY()
and start selecting each ViewHolder
that lies under these points.
If the
RecyclerView
layout manager isGridLayoutManager
and we have selection in different span index than the long pressed or previously selectedViewHolder
, an attempt is made to select all items within the span indexes. (second demo video)
On ACTION_UP
we are nulling each of long pressed ViewHolder
and other temporary references.
Usage
mRecyclerView.addOnItemTouchListener(new DragSelectionItemTouchListener(this, new OnItemInteractionListener() {
@Override
public void onLongItemClicked(RecyclerView recyclerView, ViewHolder mViewHolderTouched, int position) {
}
@Override
public void onItemClicked(RecyclerView recyclerView, ViewHolder mViewHolderTouched, int position) {
}
@Override
public void onViewHolderHovered(RecyclerView rv, ViewHolder viewHolder) {
}
@Override
public void onMultipleViewHoldersSelected(RecyclerView rv, List<ViewHolder> selection) {
}
}));