如何使用 Kotlin 通过数据绑定在 RecyclerView Adapter 中实现 onClick

How to implement onClick in RecyclerView Adapter with databinding using Kotlin

我使用数据绑定创建了一个 RecyclerView 适配器,我正在尝试处理此适配器内的 Click 事件,但我不知道具体如何操作。我找到了不同的主题,但仍无法解决我的问题。谢谢! 我应该在哪里(在 Adapter class 内)实现 onClick 函数?

适配器Class

class RemovableContactsAdapter(val viewModel: GroupDetailsViewModel,val callback:GroupContactsCallback) : RecyclerView.Adapter<RemovableContactsViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RemovableContactsViewHolder {
    val binding: ViewDataBinding =
        DataBindingUtil.inflate(LayoutInflater.from(parent.context), viewType, parent, false)
    return RemovableContactsViewHolder(binding)
}

override fun onBindViewHolder(holder: RemovableContactsViewHolder, position: Int) {
    holder.bind(viewModel, callback, position)

}

override fun getItemCount(): Int {
    return viewModel.currentGroup.value?.contacts?.size ?: 0
}

override fun getItemViewType(position: Int): Int {
    return R.layout.removable_contact_layout
}
}

class RemovableContactsViewHolder(val binding: ViewDataBinding) :
RecyclerView.ViewHolder(binding.root) {

fun bind(viewModel: GroupDetailsViewModel, callback: GroupContactsCallback, position: Int) {
    binding.root.selected_contact_iv.apply {
        visibility = if (viewModel.currentGroup.value?.contacts!![position].selected) {
            View.VISIBLE
        } else {
            View.GONE
        }
    }
    binding.setVariable(BR.contact, viewModel.currentGroup.value?.contacts?.get(position))
    binding.setVariable(BR.callback, callback)
    binding.executePendingBindings()
   }
}

Fragment中的回调接口class:

interface GroupContactsCallback {
   fun selectContact(contact: ContactModel)
}

编辑

我更新了 RemovableContactsViewHolder 中的绑定函数,但仍然无法正常工作。

class RemovableContactsViewHolder(val binding: ViewDataBinding) :
RecyclerView.ViewHolder(binding.root) {

fun bind(viewModel: GroupDetailsViewModel, callback: GroupContactsCallback, position: Int) {
    itemView.setOnClickListener {
        viewModel.currentGroup.value?.contacts?.get(position)!!.selected = !viewModel.currentGroup.value?.contacts?.get(position)!!.selected
        callback.selectContact(viewModel.currentGroup.value?.contacts?.get(position)!!)
    }

    binding.root.selected_contact_iv.apply {
        visibility = if (viewModel.currentGroup.value?.contacts!![position].selected) {
            View.VISIBLE
        } else {
            View.GONE
        }
    }

    binding.setVariable(BR.contact, viewModel.currentGroup.value?.contacts?.get(position))
    binding.setVariable(BR.callback, callback)
    binding.executePendingBindings()
}
override fun onBindViewHolder(holder: RemovableContactsViewHolder, position: Int) {
holder.bind(viewModel, callback, position)

holder.binding.your_view_like_button.setOnClickListener {
// do something 
}
}
  • for example

      class AppointTimeSloatAdapter(
          private var mOptionList: List<String>,
          var context: Context,
          var appointmentDate: String,
      ) : RecyclerView.Adapter<AppointTimeSloatAdapter.ViewHolder>() {
          private var checkedRadioButton: CompoundButton? = null
    
          override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
              val viewProductCategoryBinding: AdapterAppointmentTimeSloteBinding =
                  AdapterAppointmentTimeSloteBinding.inflate(
                      LayoutInflater.from(parent.context),
                      parent,
                      false
                  )
              return ViewHolder(viewProductCategoryBinding)
          }
    
    
          override fun onBindViewHolder(holder: ViewHolder, position: Int) {
              val option = getItem(position)
              holder.binding.radioBtn.text = option.toString()
    
              holder.binding.radioBtn.setOnCheckedChangeListener(checkedChangeListener)
              if (holder.binding.radioBtn.isChecked) checkedRadioButton = holder.binding.radioBtn
    
              holder.binding.radioBtn.setOnClickListener {
                  var intent = Intent(context, NewAppointmentActivity::class.java)
                  intent.putExtra("time",holder.binding.radioBtn.text.toString())
                  intent.putExtra("appointmentDate", appointmentDate)
                  context.startActivity(intent)
              }
    
    
          }
    
          private val checkedChangeListener =
              CompoundButton.OnCheckedChangeListener { compoundButton, isChecked ->
                  checkedRadioButton?.apply { setChecked(!isChecked) }
                  checkedRadioButton = compoundButton.apply { setChecked(isChecked) }
              }
    
          fun updateList(list: ArrayList<String>) {
              mOptionList = list
              notifyDataSetChanged()
          }
    
    
          private fun getItem(index: Int): String {
              return mOptionList[index]
          }
    
          override fun getItemCount(): Int {
              return mOptionList.size
          }
    
    
          inner class ViewHolder(val binding: AdapterAppointmentTimeSloteBinding) :
              RecyclerView.ViewHolder(binding.root), View.OnClickListener {
              override fun onClick(v: View?) {
                  ////
              }
          }
    
      }
    

应用以下方法。

在你的适配器中class

class RemovableContactsAdapter(val viewModel: GroupDetailsViewModel,val callback:GroupContactsCallback) : RecyclerView.Adapter<RemovableContactsViewHolder>() {
private var onClickListener: OnClickListener?=null
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RemovableContactsViewHolder {
    val binding: ViewDataBinding =
        DataBindingUtil.inflate(LayoutInflater.from(parent.context), viewType, parent, false)
    return RemovableContactsViewHolder(binding)
}

override fun onBindViewHolder(holder: RemovableContactsViewHolder, position: Int) {
    holder.bind(viewModel, callback, position)

holder.itemView.setOnClickListener {
            if(onClickListener!=null){
                onClickListener!!.onClick(position)
            }
        }

}

override fun getItemCount(): Int {
    return viewModel.currentGroup.value?.contacts?.size ?: 0
}

override fun getItemViewType(position: Int): Int {
    return R.layout.removable_contact_layout
}
}

class RemovableContactsViewHolder(val binding: ViewDataBinding) :
RecyclerView.ViewHolder(binding.root) {

fun bind(viewModel: GroupDetailsViewModel, callback: GroupContactsCallback, position: Int) {
    binding.root.selected_contact_iv.apply {
        visibility = if (viewModel.currentGroup.value?.contacts!![position].selected) {
            View.VISIBLE
        } else {
            View.GONE
        }
    }
    binding.setVariable(BR.contact, viewModel.currentGroup.value?.contacts?.get(position))
    binding.setVariable(BR.callback, callback)
    binding.executePendingBindings()
   }

 fun setOnClickListener(onClickListener: OnClickListener){
        this.onClickListener=onClickListener
    }

    interface OnClickListener{
        fun onClick(position: Int)
    }
}

在你Activity/Fragmentclass创建一个名为adapter的对象然后

val adapter=RemovableContactsAdapter(viewModel,callback)
adapter.setOnClickListener(object :SettingAdapter.OnClickListener{
            override fun onClick(position: Int){
                //position is your clicked view position
            }
        })

我已经在我的答案中修改了你的代码,继续吧,希望问题能得到解决。

在适配器内部处理点击不是一个好习惯。并且不要为此使用接口。请改用它。

class YourRecyclerViewAdapter(private val onSelect: (YourDataType?) -> Unit) : RecyclerView.Adapter<YourRecyclerViewAdapter.YourViewHolder>() {

    override fun onBindViewHolder(holder: YourViewHolder, position: Int) {
        holder.bind(getItem(position), onSelect)
    }

    class ViewHolder(private val binding: YourViewBinding) : RecyclerView.ViewHolder(binding.root) {

        fun bind(yourDataType: YourDataType?, onSelect: (YourDataType?) -> Unit) {

           // bind your view here
           binding.root.setOnClickListener {
               onSelect(yourDataType)
           }
        }
    }
}

在你的Fragment/Activity

// Set this adapter to your recycler view
val adapter = YourRecyclerViewAdapter { yourDataType-> 
    // Handle click here
}