如何处理对 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的主要内容,如果未能解决你的问题,请参考以下文章

Falcor 模型如何处理对字符串的引用?

如何处理对 UITableView 的非单元格区域的点击

c#:如何处理对对象进行深度拷贝

如何处理对客户端反应应用程序的外部重定向?

postgres 如何处理对某些列具有假值的视图的查询?

如何处理对尚不存在的对象的 ID 引用的 RestKit 嵌套数组?