Reputation: 8355
I am using SelectionTracker to implement a multiple selection RecyclerView. the select/unselect feature works as expected if I do it manually (Item is on the screen and I change its state by tapping) but if I try to unselect all items, some of which are off screen, using clearSelection method of selection tracker it only unselects the items which are currently visible on the screen.
This is how I am building the SelectionTracker
tracker = SelectionTracker.Builder<Long>(
"mySelection",
recyclerView,
MyKeyProvider(recyclerView),
MyItemDetailsLookup(recyclerView),
StorageStrategy.createLongStorage()
).withSelectionPredicate(
SelectionPredicates.createSelectAnything()
).build()
recyclerAdapter.tracker = tracker
Following is bindItem
and onBindViewHolder
methods of ViewHolder
and adapter
respectively
fun bindItems(model: Model, isActivated: Boolean) {
itemView.isActivated = isActivated
if(itemView.isActivated){
/* Do something */
}
else{
/* Do something */
}
}
override fun onBindViewHolder(holder: RecyclerAdapter.ViewHolder, position: Int) {
val number = displayList[position]
tracker?.let {
holder.bindItems(number, it.isSelected(position.toLong()))
}
}
I call the clear selection method on click of a menu item
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
if((selectionMode) && (item?.itemId==android.R.id.home)){
tracker.clearSelection()
}
return super.onOptionsItemSelected(item)
}
Edit: This seems to be a bug in the Library, I have encountered the same issue while using the Android Gmail app, Which I think must be using SelectionTracker
Upvotes: 3
Views: 1993
Reputation: 1065
I encountered this issue and finally found a solution in this answer.
Turns out this is a library bug. To resolve it, a solution is to override the onViewAttachedToWindow
method in your adapter.
According to the documentation, this method is called when a previously unseen view is about to become visible. You can use it to update the state of the item so that it correctly renders your selected state, like this:
override fun onViewAttachedToWindow(holder: LexemeViewHolder) {
val isSelected = tracker?.isSelected(holder.itemId)
if(isSelected != null)
holder.setItemSelected(isSelected)
}
You also need to define the setItemSelected
method in your ViewHolder
:
fun bindItems(model: Model, isActivated: Boolean) {
setItemSelected(isActivated)
}
fun setItemSelected(isSelected: Boolean) {
itemView.isActivated = isActivated
if (itemView.isActivated){
/* Do something */
}
else {
/* Do something */
}
}
While this may not be the most efficient solution due to potential additional processing, it effectively addresses the problem without requiring a full adapter refresh.
Upvotes: 0