如何处理对 RecyclerView 列表项内部视图的点击。使用数据绑定和 kotlin
Posted
技术标签:
【中文标题】如何处理对 RecyclerView 列表项内部视图的点击。使用数据绑定和 kotlin【英文标题】:How to handle clicks on a view inside of a RecyclerView list item. Using data binding and kotlin 【发布时间】:2022-01-10 19:38:33 【问题描述】:我找到的所有资源都使用 Java 或仅涵盖单击列表项本身而不是列表项内部的视图。我相信我应该在 ViewHolder 类中设置它,但我不确定如何设置。这是我的 ViewHolder 类。
class ItemListAdapter(val clickListener : ItemListListener) : ListAdapter<Item , ItemListAdapter.ItemViewHolder>(DiffCallback)
class ItemViewHolder(private var binding : ItemListItemBinding) :
RecyclerView.ViewHolder(binding.root)
fun bind(item : Item, clickListener : ItemListListener)
binding.item = item
binding.clickListener = clickListener
// button that inside listItem that I want to respond to clicks
// binding.addOneButton ???????
binding.executePendingBindings()
还有我的听众
class ItemListListener(val clickListener : (singleItem : Item) -> Unit)
fun onClick(item : Item)
clickListener(item)
其他相关的方法调用
override fun onBindViewHolder(holder : ItemViewHolder , position : Int)
val item = getItem(position)
holder.bind(item, clickListener)
companion object DiffCallback : DiffUtil.ItemCallback<Item>()
override fun areItemsTheSame(oldItem : Item , newItem : Item) : Boolean
return oldItem == newItem
override fun areContentsTheSame(oldItem : Item , newItem : Item) : Boolean
return oldItem.itemId == newItem.itemId
override fun onCreateViewHolder(
parent : ViewGroup ,
viewType : Int
) : ItemViewHolder
return ItemViewHolder(ItemListItemBinding.inflate(LayoutInflater.from(parent.context)))
【问题讨论】:
什么是binding.clickListener
?你的 XML 中有这个名字的东西吗?
这是我上面第二个代码组中的 ItemListListener。
我的意思是你是如何在你的 XML 中使用它的?有没有设置成xml按钮的onClick
属性?
设置为onClick
,用于列表项的根视图,一个ConstraintLayout。
你想要两个点击监听器吗?一个用于根视图,一个用于addOneButton
?
【参考方案1】:
如果它点击你可以在onBindViewHolder
上设置的项目
holder.itemView.setOnClickListener
clickListener.onClick(getItem(position)
如果您需要在项目内的特定视图上,您可以在 bind
函数上设置
fun bind(item : Item, clickListener : ItemListListener)
binding.item = item
binding.addOneButton.setOnClickListener
clickListener.onClick(item)
binding.executePendingBindings()
【讨论】:
我实际上已经尝试过了,但奇怪的是,点击最终只在回收站视图的第一个列表项上注册。【参考方案2】:首先,Listener 应该是一个接口。
interface ItemListListener
fun onClick(item: Item,actionType:String)
然后在Activity/Fragment类中,实现这个接口。 初始化适配器。
recyclerView.adapter = ItemListAdapter(this)
您可以使用以下代码更新您的 ItemViewHolder 类。将其设为 inner 类,则无需传递 clickListener 实例。并且点击监听器应该注册在 View Holder 类的 init 方法中。
inner class ItemViewHolder(private val binding : ItemListItemBinding) :
RecyclerView.ViewHolder(binding.root)
init
binding.addOneButton.setOnClickListener
clickListener.onClick(getItem(adapterPosition),"button")
binding.root.setOnClickListener
clickListener.onClick(getItem(adapterPosition),"root")
fun bind(item : Item)
binding.item = item
binding.executePendingBindings()
** 更新 **
经过一番研究,我得到了您问题的答案。 这是解决方案。 您可以将高阶函数传递给适配器类,而不是接口。
class ItemListAdapter(val clickListener : (Item,String) -> Unit ):ListAdapter<Item , ItemListAdapter.ItemViewHolder>(DiffCallback)
在 View Holder 类中
binding.addOneButton.setOnClickListener
clickListener(getItem(adapterPosition),"button")
binding.root.setOnClickListener
clickListener(getItem(adapterPosition),"root")
在活动/片段中
recyclerview.adapter = ItemListAdapter(item, action->
)
您也可以使用 Binding 来做到这一点。
【讨论】:
我试图避免做一个界面。我听说在 Kotlin 中有一种不同的实现方式。 @brandNoob 接口或 XML 中的绑定侦听器是两种方法。我不知道你说的另一种方式。此外,如果您想分别处理根视图单击和 addOneButton 单击。然后可以在接口类的 onClick 方法中再添加一个参数。我已经更新了你可以查看的答案。以上是关于如何处理对 RecyclerView 列表项内部视图的点击。使用数据绑定和 kotlin的主要内容,如果未能解决你的问题,请参考以下文章