Android Recyclerview selection:createSelectSingleAnything在滚动时选择多个

Android Recyclerview selection:createSelectSingleAnything在滚动时选择多个,android,kotlin,android-recyclerview,Android,Kotlin,Android Recyclerview,我正在尝试创建一个带有单个选择的水平回收视图。下面的代码可以工作,但如果滚动,则可以选择2个或更多对象,即使我指定了单个选择。我猜这是因为如果项目不在屏幕上,则不会调用onBindViewHolder,但当我调用notifyDataSetChanged时,行为仍然相同。回调是正确的,但选择器背景显示在多个对象后面 class CategoryAdapter(private val listener: CategoryListener) : ListAdapter<CategoryListi

我正在尝试创建一个带有单个选择的水平回收视图。下面的代码可以工作,但如果滚动,则可以选择2个或更多对象,即使我指定了单个选择。我猜这是因为如果项目不在屏幕上,则不会调用onBindViewHolder,但当我调用notifyDataSetChanged时,行为仍然相同。回调是正确的,但选择器背景显示在多个对象后面

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
        }
}
class CategoryAdapter(私有val侦听器:CategoryListener):
ListAdapter(CategoryList.DIFF_比较器){
初始化{
SetHassTableId(真)
}
变量跟踪器:SelectionTracker?=null
...
重写getItemId(position:Int):Long=position.toLong()
覆盖BindViewHolder(holder:ViewHolder,位置:Int){
追踪器?,让我来{
如果(!it.hasSelection()&&position==0){
选择(0)
}
}
持有者绑定(
当前列表[位置],
听众,
跟踪器?.isSelected(position.toLong())?:false
)
}
内部类ViewHolder(视图:视图):RecyclerView.ViewHolder(视图){
有趣的绑定(
类别:类别列表,
听众:CategoryListener,
isSelected:布尔值
) {
if(isSelected)selector.show()else selector.hide()
itemView.setOnClickListener{
tracker?.clearSelection()//这似乎没有任何作用
//notifyDataSetChanged()//此
//tracker?.select(adapterPosition.toLong())//或
listener.onItemClicked(类别、适配器位置)
}
}
趣味getItemDetails():ItemDetailsLookup.ItemDetails=
对象:ItemDetailsLookup.ItemDetails(){
覆盖getPosition()=适配器位置
覆盖getSelectionKey()=itemId
}
}
片段:

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()

}
rv_categories.adapter=categoryAdapter
rv_类别。setHasFixedSize(真)
selectionTracker=selectionTracker.Builder(
CardsFragment::javaClass.name,
rv_类别,
类别项目密钥提供者(rv_类别),
分类详细目录(rv_类别),
StorageStrategy.createLongStorage()
).withSelectionPredicate(SelectionPredicates.createSelectSingleAnything()).build()
categoryAdapter.tracker=selectionTracker
selectionObserver=类别selectionObserver(selectionTracker){selectedPosition->
OnSelection已更改(selectedPosition)
}
selectionTracker.addObserver(selectionObserver)
...
已单击(类别:CardCategoryList,位置:Int){
//加载该类别的数据
}
更改了选择中的私人乐趣(selectedItemPosition:Long){
rv_categories.findViewHolderForAdapterPosition(selectedemposition.toInt())?.itemView?.performClick()
}

有人能帮忙吗?

我对特定的API和Kotlin了解得不够,但是,有三件事可能有用:1:在
onSelectionChanged
中,您调用
performClick
。2:注释掉的方法调用有副作用,因此它们的顺序很重要。3:您直接调用
select
onBindViewHolder
,而不仅仅是在回调中。如果我从
onSelectionChanged
注释掉onclick,我仍然会得到相同的行为。当我更改注释掉的调用的顺序时也是一样的(当然,除了
listener.onItemClicked(category,adapterPosition)
)如果您注释掉:
tracker?。让{if(!it.hasSelection()&&position==0){it.select(0)}
?也尝试一下:(谢谢@MelvinWM。选择器就是视图,我应该写出来。选择正确,视图更新不正确。谢谢上面的链接。我也看到了,但没有一个答案是使用recyclerview选择器。我想我也会改为手动解决方案。我对具体的a不太了解PIs和Kotlin,但是,有三件事情可能是有用的:1:在
onSelectionChanged
中,您调用
performClick
。2:注释掉的方法调用有副作用,因此它们的顺序很重要。3:您直接调用
select
onBindViewHolder,而不仅仅是在回调中。如果我注释掉从
onSelectionChanged
中单击,我仍然会得到相同的行为。当我更改已注释掉的调用的顺序时也是如此(当然,除了
listener.onItemClicked(category,adapterPosition)
),如果您注释掉:
tracker?.let{if(!it.hasSelection()&&position==0){it.select(0)}
?也尝试过:(谢谢@MelvinWM。选择器就是视图,我应该写出来。选择正确,视图更新不正确。谢谢上面的链接。我也看到了。但是没有一个答案是使用recyclerview选择器。我想我也会改为手动解决方案