Reputation: 3156
I am trying to use the recyclerview-selection library in my project. I followed this tutorial:
https://proandroiddev.com/a-guide-to-recyclerview-selection-3ed9f2381504
Everything workes fine. But I have a problem. If I tap/touch any blank space inside the RecyclerView
, all the selected elements got deselected! I don't find any method or solution to disable this. What should I do?
I am using implementation 'androidx.recyclerview:recyclerview-selection:1.1.0-rc01'
in my project.
Edit 1:
I set the RecyclerView
background red to describe my problem. Here, blue items are selected items. If I click any red area, then all the selected items got unselected! The select and deselect should only be done by clicking the items. So, I need to disable this feature (or bug!), that unselect all items!
Example project: https://github.com/ImaginativeShohag/multiselection
Upvotes: 4
Views: 1222
Reputation: 255
Solution is to have an out of context selection item like:
class ItemLookup(private val recyclerView: RecyclerView) : ItemDetailsLookup<Long>() {
private val outOfContextSelection = object : ItemDetails<Long>() {
override fun getPosition(): Int = OUT_OF_CONTEXT_POSITION.toInt()
override fun getSelectionKey() = OUT_OF_CONTEXT_POSITION
}
override fun getItemDetails(e: MotionEvent): ItemDetails<Long>? {
recyclerView.findChildViewUnder(e.x, e.y)?.let {
return (recyclerView.getChildViewHolder(it) as? SelectorBarAdapter.SelectorBarViewHolder)?.itemDetails
}
return outOfContextSelection
}
companion object {
const val OUT_OF_CONTEXT_POSITION = 10000L
}
}
So that when a view which is not one of our clickable elements is clicked we can identify further on a predicate like follows:
class SingleSelectionPredicate : SelectionTracker.SelectionPredicate<Long>() {
override fun canSetStateForKey(key: Long, nextState: Boolean): Boolean {
// warranties that an item can't be unselected on click
// warranties that clicks out of the item's scope are disabled
return nextState && key != ItemLookup.OUT_OF_CONTEXT_POSITION
}
override fun canSetStateAtPosition(position: Int, nextState: Boolean) = true
override fun canSelectMultiple() = false
}
Upvotes: 2
Reputation: 142
You create your own SelectionTracker.SelectionPredicate<Long>
.
Override the method canSetStateForKey(key: Long, nextState: Boolean)
like this:
override fun canSetStateForKey(@NonNull key: Long, nextState: Boolean): Boolean {
rv.findViewHolderForItemId(key)?.let { holder -> adapter.canSetStateForItem(holder as YourItemHolder<YourItem>, nextState)}
return true
}
and in your ViewHolder
check if the item is already selected if so return false
or vice versa.
Edit:
You can also define a "Selection Hotspot" by inSelectionHotspot(e: MotionEvent)
in your ItemDetailsLookup.ItemDetails
.
In your ViewHolder
you can then check if the TouchEvent
is in an area that requires a select or unselect.
for example:
override fun inSelectionHotspot(e: MotionEvent): Boolean {
val rect = Rect()
itemView.getGlobalVisibleRect(rect)
if (rect.contains(e.rawX.toInt(), e.rawY.toInt())) {
// in select region
} else {
// not in select region
}
}
Upvotes: -1