All of the resources I've found are either in Java or only cover clicking the list item itself not a view inside of the list item. I believe I am supposed to set this up inside the ViewHolder class but I am not sure how. This is my ViewHolder class.
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()
}
}
And my listener
class ItemListListener(val clickListener : (singleItem : Item) -> Unit) {
fun onClick(item : Item){
clickListener(item)
}
}
Other method calls in case they are relevant
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)))
}
First of All, Listener is supposed to be an Interface.
interface ItemListListener {
fun onClick(item: Item,actionType:String)
}
Then in Activity/Fragment class,implement this interface. Initialize adapter.
recyclerView.adapter = ItemListAdapter(this)
You can update your ItemViewHolder class with following code. Make it inner class, Then you'll not need to pass clickListener instance. And click listener should be registered in init method of View Holder class.
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()
}
}
** Update **
After some research I got answer to your question. Here's the solution. Instead of an interface, You can pass Higher Order function to Adapter class.
class ItemListAdapter(val clickListener : (Item,String) -> Unit ):ListAdapter<Item , ItemListAdapter.ItemViewHolder>(DiffCallback)
In View Holder class
binding.addOneButton.setOnClickListener {
clickListener(getItem(adapterPosition),"button")
}
binding.root.setOnClickListener {
clickListener(getItem(adapterPosition),"root")
}
In Activity/Fragment
recyclerview.adapter = ItemListAdapter({item, action->
})
You can do it with Binding as well.