I'm trying to create a horizontal recyclerview with a single selection. The code below works but if you scroll, then 2 or more objects can be selected, even though I specify the single selection. I guess it's because the onBindViewHolder is not called if the item is off the screen but when I call the notifyDataSetChanged the behavior is still the same. The callbacks are correct, but the selector background, shows behind multiple objects.
class CategoryAdapter(private val listener: CategoryListener) :
ListAdapter<CategoryListing, CategoryAdapter.ViewHolder>(CategoryListing.DIFF_COMPARATOR) {
init {
setHasStableIds(true)
}
var tracker: SelectionTracker<Long>? = null
...
override fun getItemId(position: Int): Long = position.toLong()
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
tracker?.let {
if (!it.hasSelection() && position == 0) {
it.select(0)
}
}
holder.bind(
currentList[position],
listener,
tracker?.isSelected(position.toLong()) ?: false
)
}
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bind(
category: CategoryListing,
listener: CategoryListener,
isSelected: Boolean
) {
if (isSelected) selector.show() else selector.hide()
itemView.setOnClickListener {
tracker?.clearSelection() // this doesn't seem to do anything
// notifyDataSetChanged() // neither this
// tracker?.select(adapterPosition.toLong()) // or this
listener.onItemClicked(category, adapterPosition)
}
}
fun getItemDetails(): ItemDetailsLookup.ItemDetails<Long> =
object : ItemDetailsLookup.ItemDetails<Long>() {
override fun getPosition() = adapterPosition
override fun getSelectionKey() = itemId
}
}
Fragment:
rv_categories.adapter = categoryAdapter
rv_categories.setHasFixedSize(true)
selectionTracker = SelectionTracker.Builder<Long>(
CardsFragment::javaClass.name,
rv_categories,
CategoryItemKeyProvider(rv_categories),
CategoryDetailsLookup(rv_categories),
StorageStrategy.createLongStorage()
).withSelectionPredicate(SelectionPredicates.createSelectSingleAnything()).build()
categoryAdapter.tracker = selectionTracker
selectionObserver = CategorySelectionObserver(selectionTracker) { selectedPosition ->
onSelectionChanged(selectedPosition)
}
selectionTracker.addObserver(selectionObserver)
...
override fun onItemClicked(category: CardCategoryListing, position: Int) {
// load the data for that category
}
private fun onSelectionChanged(selectedItemPosition: Long) {
rv_categories.findViewHolderForAdapterPosition(selectedItemPosition.toInt())?.itemView?.performClick()
}
Can anyone help?