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