0

I have heard it is good practice to implement the onClickListener inside of the ViewHolder. However, I am not sure how to access the item that is associated with the ViewHolder inside of the onClickListener.

For example:

import android.content.Context
import androidx.recyclerview.widget.RecyclerView
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import kotlinx.android.synthetic.main.post.view.*

import rstudio.vedantroy.swarm.MainActivity.Companion.TAG

class PostAdapter(private val items : List<Post>, private val contex: Context) : RecyclerView.Adapter<MyViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        return MyViewHolder(LayoutInflater.from(contex).inflate(R.layout.post, parent, false))
    }

    override fun getItemCount(): Int {
        return items.size
    }

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        holder.bodyContent.text = items[position].content
    }
}


class MyViewHolder(view: View): RecyclerView.ViewHolder(view), View.OnClickListener {

    override fun onClick(v: View?) {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

    val bodyContent : TextView = view.bodyContent

}

How do I access items, and how do I find out the current index of the ViewHolder?

I looked at this example: Recyclerview(Getting item on Recyclerview), but there was no explanation of where mDataSource comes from.

Foobar
  • 7,458
  • 16
  • 81
  • 161

2 Answers2

0

I managed to implement this behavior by moving the location of PostViewHolder. However, I am not sure if inner class will break something.

package rstudio.vedantroy.swarm

import android.content.Context
import androidx.recyclerview.widget.RecyclerView
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.cardview.widget.CardView
import kotlinx.android.synthetic.main.post.view.*

import rstudio.vedantroy.swarm.MainActivity.Companion.TAG

class PostAdapter(private val items : List<Post>, private val contex: Context) : RecyclerView.Adapter<PostAdapter.PostViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PostViewHolder {
        return PostViewHolder(LayoutInflater.from(contex).inflate(R.layout.post, parent, false))
    }

    override fun getItemCount() = items.size

    override fun onBindViewHolder(holder: PostViewHolder, position: Int) {
        holder.bodyContent.text = items[position].content
    }

    inner class PostViewHolder(view: View): RecyclerView.ViewHolder(view) {
        val bodyContent : TextView = view.bodyContent

        init {
            view.apply {
                setOnClickListener {
                    isClickable = false
                    Log.d(TAG, "Clicked!")
                }
            }

        }

    }
}
Foobar
  • 7,458
  • 16
  • 81
  • 161
0

Personally what I find is a good solution is to set the OnClickListener within the onBindViewHolder.

For example,

// ... adapter class ...

override fun onBindViewHolder(holder: ViewHolder, position: Int) {

    holder.view.apply {

        bodyContent.text = items[position].content

        setOnClickListener {
            // TODO Handle onClick
        }
    }
}

class ViewHolder(val view: View) : RecyclerView.ViewHolder(view)

Also I find just storing the view within the ViewHolder makes it very easy to access any elements within the layout.

advice
  • 5,778
  • 10
  • 33
  • 60
  • 1
    Can I just use `holder.itemView` instead of storing the `view` within the `ViewHolder`? – Foobar Jan 28 '19 at 23:48
  • You may need to add `val` to your `View` you're passing to your `ViewHolder`. – advice Jan 28 '19 at 23:50
  • Also, I was specifically wondering how to implement the `onClickListener` in the `ViewHolder` itself (while also having access to the associated item) instead of in `onBindViewHolder` – Foobar Jan 28 '19 at 23:56
  • Yeah I was just suggesting what I personally do and think is a good solution. This keeps all the view setup logic together. I haven't heard of binding it within the `ViewHolder`. Just throwing out an example. – advice Jan 29 '19 at 00:03