It's a simple one class TouchListener
that can be attached to any RecyclerView and handles multi selection in google photos style via long pressing on an item and moving the finger up/down to select more items (it even scrolls if you reach the edges of the RecyclerView
)
Gradle (via JitPack.io)
- add jitpack to your project's
build.gradle
:
repositories {
maven { url "https://jitpack.io" }
}
- add the compile statement to your module's
build.gradle
:
dependencies {
compile 'com.github.MFlisar:DragSelectRecyclerView:0.3'
}
- Create the a touch listener like following
mDragSelectTouchListener = new DragSelectTouchListener()
// check region OnDragSelectListener for more infos
.withSelectListener(onDragSelectionListener)
// following is all optional
.withMaxScrollDistance(distance) // default: 16; defines the speed of the auto scrolling
.withTopOffset(toolbarHeight) // default: 0; set an offset for the touch region on top of the RecyclerView
.withBottomOffset(toolbarHeight) // default: 0; set an offset for the touch region on bottom of the RecyclerView
.withScrollAboveTopRegion(enabled) // default: true; enable auto scrolling, even if the finger is moved above the top region
.withScrollBelowTopRegion(enabled) // default: true; enable auto scrolling, even if the finger is moved below the top region
.withDebug(enabled); // default: false;
- attach it to the
RecyclerView
recyclerView.addOnItemTouchListener(mDragSelectTouchListener);
- on item long press, inform the listener so that it can start doing it's magic
// if one item is long pressed, we start the drag selection like following:
// we just call this function and pass in the position of the first selected item
mDragSelectTouchListener.startDragSelection(position);
You have 3 options:
-
use a simple
DragSelectTouchListener.OnDragSelectListener
=> you get notified over which items the user dragged or dragged backonDragSelectionListener = new DragSelectTouchListener.OnDragSelectListener() { @Override public void onSelectChange(int start, int end, boolean isSelected) { // update your selection // range is inclusive start/end positions } }
-
use a
DragSelectTouchListener.OnAdvancedDragSelectListener
=> this is an extended version of theDragSelectTouchListener.OnDragSelectListener
which will notify you about the start and end of the drag selection as wellonDragSelectionListener = new DragSelectTouchListener.OnAdvancedDragSelectListener() { @Override public void onSelectChange(int start, int end, boolean isSelected) { // update your selection // range is inclusive start/end positions } @Override public void onSelectionStarted(int start) { // drag selection was started at index start } @Override public void onSelectionFinished(int end) { // drag selection was finished at index start } };
-
Preferred option: use the
DragSelectionProcessor
, it implements the above mentioned interface and can be set up with 4 modes:Simple
: simply selects each item you go by and unselects on move backToggleAndUndo
: toggles each items original state, reverts to the original state on move backFirstItemDependent
: toggles the first item and applies the same state to each item you go by and applies inverted state on move backFirstItemDependentToggleAndUndo
: toggles the item and applies the same state to each item you go by and reverts to the original state on move back
The DragSelectionProcessor
will take care to transform each event to the correct select/deselect event that must be handled by you afterwards. Therefore you must provide a ISelectionHandler
in it's constructor. Just implement it's 3 simple functions and you're done.
onDragSelectionListener = new DragSelectionProcessor(new DragSelectionProcessor.ISelectionHandler() {
@Override
public Set<Integer> getSelection() {
// return a set of all currently selected indizes
return selection;
}
@Override
public boolean isSelected(int index) {
// return the current selection state of the index
return selected;
}
@Override
public void updateSelection(int start, int end, boolean isSelected, boolean calledFromOnStart) {
// update your selection
// range is inclusive start/end positions
// and the processor has already converted all events according to it'smode
}
})
// pass in one of the 4 modes, simple mode is selected by default otherwise
.withMode(DragSelectionProcessor.Mode.FirstItemDependentToggleAndUndo);
A demo can be found here: MainActivity.java
- support horizontal RecyclerViews... should be quite simple, but is not yet implemented
This library is heavily inspired and based on https://github.com/weidongjian/AndroidDragSelect-SimulateGooglePhoto