RecyclerView --SelectionTracker limit selection size to 10 items

962 Views Asked by At

I want to limit my RecyclerView SelectionTracker selection size to 10 items (max).

SelectionTracker init code:

val selectionTracker = SelectionTracker.Builder(
                        "my_selection_tracker_id",
                        myRecyclerView,
                        MyItemKeyProvider(),
                        MyItemLookup(myRecyclerView),
                        StorageStrategy.createParcelableStorage(MyItemModel::class.java)
                ).withSelectionPredicate(SelectionPredicates.createSelectAnything())
                .build()
2

There are 2 best solutions below

0
On BEST ANSWER

Answer

After reading SelectionTracker documentation again, I found this one:

In order to limit the number of items that can be selected,
use {@link #canSetStateForKey(Object, boolean)} and
{@link #canSetStateAtPosition(int, boolean)}.

So, I override canSetStateForKey() method from SelectionPredicate
and add if condition which check item nextState (selected/deselected) and selected items size.

From documentation about canSetStateForKey():

@return true if the item at {@code id} can be set to {@code nextState}

Condition which limit selection size to 10:

if(nextState && selectionTracker.selection.size() >= 10) {
    return false
} else {
    return true
}


Full SelectionTracker initialization:

val selectionTracker = SelectionTracker.Builder(
                        "my_selection_tracker_id",
                        myRecyclerView,
                        MyItemKeyProvider(),
                        MyItemLookup(myRecyclerView),
                        StorageStrategy.createParcelableStorage(MyItemModel::class.java)
                ).withSelectionPredicate(object : SelectionTracker.SelectionPredicate<AttachmentMediaModel>() {
                    override fun canSelectMultiple(): Boolean {
                        return true
                   }
                   override fun canSetStateForKey(key: AttachmentMediaModel, nextState: Boolean): Boolean {
                       if(nextState && selectionTracker.selection.size() >= 10) { // 10 - max selection size
                           return false // Can't select when 10 items selected
                       }
                       return true // When selection size < 10 - allow selection
                   }
                   override fun canSetStateAtPosition(position: Int, nextState: Boolean): Boolean {
                       return true
                   }
               }).build()
0
On

I used this but I changed it a bit where the tracker will unselect the oldest selection to "make room" for the new selection. Similar (mine is java and I'm only using a long key)

@Override
public boolean canSetStateForKey(@NonNull Long key, boolean nextState) {
    if (nextState && tracker.getSelection().size() >= MAX_SELECTIONS) {
        // Deselect the first selection and return true to allow the new item to be selected
        tracker.deselect(tracker.getSelection().iterator().next());
    }
    return true;

}