RecyclerView itemClickListener in Kotlin

kotlin recyclerview onitemclicklistener github
recyclerview item click listener in activity android
recyclerview item click listener in fragment android
recyclerview onclick position
intent in recyclerview adapter kotlin
recyclerview onitemclicklistener example github
recyclerview onclicklistener to new activity
recyclerview onclicklistener in fragment

I'm writing my first app in Kotlin after 3 years of experience with Android. Just confused as to how to utilize itemClickListener with a RecyclerView in Kotlin.

I have tried the trait (edit: now interface) approach, very Java-like

public class MainActivity : ActionBarActivity() {

  protected override fun onCreate(savedInstanceState: Bundle?) {

    // set content view etc go above this line

    class itemClickListener : ItemClickListener {
      override fun onItemClick(view: View, position: Int) {
        Toast.makeText(this@MainActivity, "TEST: " + position, Toast.LENGTH_SHORT).show()
      }
    }

    val adapter = DrawerAdapter(itemClickListener())
    mRecyclerView.setAdapter(adapter)
 }

  trait ItemClickListener {
    fun onItemClick(view: View, position: Int)
  }
}

That seemed very redundant so I tried the inner class approach:

inner class ItemClickListener {
    fun onItemClick(view: View, position: Int) {
        startActivityFromFragmentForResult<SelectExerciseActivity>(SELECT_EXERCISES)
    }
}

And then just setting the adapter's click listener like this:

val adapter = WorkoutsAdapter(ItemClickListener())

But I'm still not satisfied with this because I think there might be a better, cleaner way. I'm trying to essentially achieve something like this: RecyclerView onClick

Any suggestions?

Ended up going with a variation of the approved answer

Defined the function in the activity:

val itemOnClick: (View, Int, Int) -> Unit = { view, position, type ->
    Log.d(TAG, "test")
}

Passed the function itself on to the adapter like this:

class ExercisesAdapter(val itemClickListener: (View, Int, Int) -> Unit) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
      // other stuff up here
      val vhExercise = ExerciseVH(view) // view holder
      // on to the view holder through the extension function
      vhExercise.onClick(itemClickListener)
    }
}

Extension function by Loop in the approved answer below.

fun <T : RecyclerView.ViewHolder> T.onClick(event: (view: View, position: Int, type: Int) -> Unit): T {
    itemView.setOnClickListener {
        event.invoke(it, getAdapterPosition(), getItemViewType())
    }
    return this
}

I have a little bit different approach. You can create an extension for your ViewHolder

fun <T : RecyclerView.ViewHolder> T.listen(event: (position: Int, type: Int) -> Unit): T {
    itemView.setOnClickListener {
        event.invoke(getAdapterPosition(), getItemViewType())
    }
    return this
}

Then use it in adapter like this

class MyAdapter : RecyclerView.Adapter<MyAdapter.MyViewHolder>() {

    val items: MutableList<String> = arrayListOf()

    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): MyViewHolder? {
        val inflater = LayoutInflater.from(parent!!.getContext())
        val view = inflater.inflate(R.layout.item_view, parent, false)
        return MyViewHolder(view).listen { pos, type ->
            val item = items.get(pos)
            //TODO do other stuff here
        }
    }

    override fun onBindViewHolder(holder: MyViewHolder?, position: Int) {

    }

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


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

    }
}

I am working with my colleagues on library providing such extensions.

Set a click listener to a RecyclerView, If you've used a RecyclerView, you may know that they don't have a `​setOnItemClickListener` as `ListView` had, private final List items; private final OnItemClickListener listener; public ContentAdapter(List items, Want to learn Kotlin? RecyclerView Item Click Listener the Right Way. Ngenge Senior. (Select the Kotlin support option) and name your activity, MainActivity. Do not bother much if you do not know Kotlin. It is just


My solution is like a combination of the previous ones with a super clean call from the activity.

ContactAdapter:

class ContactAdapter @Inject constructor() : RecyclerView.Adapter<ContactAdapter.ViewHolder>() {

    var onItemClick: ((Contact) -> Unit)? = null
    var contacts: List<Contact> = emptyList()

    ...

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val contact = contacts[position]

        holder.email.text = contact.email
    }

    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        val email: TextView = itemView.email

        init {
            itemView.setOnClickListener {
                onItemClick?.invoke(contacts[adapterPosition])
            }
        }
    }
}

ContactActivity:

override fun setupRecyclerAdapter() {
    recyclerView.adapter = contactAdapter
    recyclerView.layoutManager = LinearLayoutManager(this)

    contactAdapter.onItemClick = { contact ->

        // do something with your item
        Log.d("TAG", contact.email)
    }
}

RecyclerView Item Click Listener the Right Way, From Android Studio, create an empty android project(Select the Kotlin support option) and name val itemClickListener: OnItemClickListener):RecyclerView. When the user later clicks on an item in the RecyclerView, the click listener is executed. As parameter, the listener gets the item that was clicked, to react accordingly. Traditionally, you would have implemented this with an Interface and Listeners. In Kotlin, you can greatly simplify the code through function parameters and lambda expressions.


In case anyone is looking for a more no-frills answer, I tried the following - which is very similar to the solution from AfzalivE:

In my Adapter class I passed the clickListener as a parameter. On onBindViewHolder, I've used setOnClickListener to call clickListener and handle click event.

MyAdapter.kt:

class MyAdapter constructor(objects: ArrayList<MyObject>, val clickListener: (MyObject) -> Unit) : RecyclerView.Adapter<MyAdapter.Holder>() {

    private var mObjects : ArrayList<MyObject> = ArrayList<MyObject>()

    init {
        mObjects = objects
    }

    override fun onBindViewHolder(holder: Holder?, position: Int) {
        var item : MyObject = objects[position]

        // Calling the clickListener sent by the constructor
        holder?.containerView?.setOnClickListener { clickListener(item) }
    }

    // More code (ViewHolder definitions and stuff)...

}

Note: I needed a reference from my list item's container (the root view), which in this case is containerView

Then I passed my object as parameter without need for searching it on a list again and handle it directly on my Activity class, in the moment I set the adapter:

MyActivity.kt:

myRecyclerView?.adapter = MyAdapter(mObjects) {
    Log.e("Activity", "Clicked on item ${it.itemName}")
}  

Update

If you need to get the position of the clicked item, just define it as parameter on the callback and then send it back later. Notice the val clickListener: (MyObject, Int) -> Unit below:

MyAdapter.kt

class MyAdapter constructor(objects: ArrayList<MyObject>, val clickListener: (MyObject, Int) -> Unit) : RecyclerView.Adapter<MyAdapter.Holder>() {
    // Rest of the code...

Then on onBindViewHolder() you pass the position when calling the callback method:

override fun onBindViewHolder(holder: Holder?, position: Int) {
    var item : MyObject = objects[position]

    // Calling the clickListener sent by the constructor
    holder?.containerView?.setOnClickListener { clickListener(item, position) }
}

And on MyActivity.kt, you'll have to change the way you set the adapter so you can get the position. Like this:

myRecyclerView?.adapter = MyAdapter(mObjects) { itemDto: MyObject, position: Int ->
        Log.e("MyActivity", "Clicked on item  ${itemDto.someItemPropertyLikeName} at position $position")
    }

Android RecyclerView onItemClickListener & getAdapterPosition , I know you must have already found a way to get onItemClickListener() for your RecyclerView Adapter. But sometimes the way we think is not always the correct​  Kotlin RecyclerView Example Creating a New Project. So first create a new Android Studio project using Kotlin. Once the project is loaded come inside the activity_main.xml and remove the Hello World TextView. Adding RecyclerView. Now search for RecyclerView and drag it to your activity_main.xml (See the image for help).


Sorry for the delay, Got an awesome answer from this link and it was in Java.. Did some Homework and converted it to Kotlin..

Now it is working Properly.. Here is the Code,

Create a class named RecyclerItemClickListenr,

class RecyclerItemClickListenr(context: Context, recyclerView: RecyclerView, private val mListener: OnItemClickListener?) : RecyclerView.OnItemTouchListener {

private val mGestureDetector: GestureDetector

interface OnItemClickListener {
    fun onItemClick(view: View, position: Int)

    fun onItemLongClick(view: View?, position: Int)
}

init {

    mGestureDetector = GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() {
        override fun onSingleTapUp(e: MotionEvent): Boolean {
            return true
        }

        override fun onLongPress(e: MotionEvent) {
            val childView = recyclerView.findChildViewUnder(e.x, e.y)

            if (childView != null && mListener != null) {
                mListener.onItemLongClick(childView, recyclerView.getChildAdapterPosition(childView))
            }
        }
    })
}

override fun onInterceptTouchEvent(view: RecyclerView, e: MotionEvent): Boolean {
    val childView = view.findChildViewUnder(e.x, e.y)

    if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
        mListener.onItemClick(childView, view.getChildAdapterPosition(childView))
    }

    return false
}

override fun onTouchEvent(view: RecyclerView, motionEvent: MotionEvent) {}

override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {}}

and access it from Activity/Fragment as

recyclerView.addOnItemTouchListener(RecyclerItemClickListenr(this, recyclerView, object : RecyclerItemClickListenr.OnItemClickListener {

        override fun onItemClick(view: View, position: Int) {
            //do your work here..
        }
        override fun onItemLongClick(view: View?, position: Int) {
            TODO("do nothing")
        }
    }))

How to add RecyclerView item onItemClickListener in Kotlin, In this android kotlin source code example, we are going to add RecyclerView item onItemClickListener in Kotlin. You can copy and adopt this source code Instead of creating a custom ItemClickListener interface to getAdapterPosition () inside your Activity/Fragment/View and end up creating multiple Anonymous Classes under the hood for each item. Better pass the RecyclerView. ViewHolder using view. setTag () inside your ViewHolder and then getAdapterPosition () (…and many other things) from


Slightly different, based on denwehrle

To use on a fragment, inside OnCreateView

 adapter.onItemClick = {it ->
    //do something
 }

Add in the adapter class:

var onItemClick: ((Contact)->Unit) ?= null
...

inner class contactViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView){
        val myItemView: TextView = itemView.findViewById(R.id.textView)

        init{
            itemView.setOnClickListener {
                onItemClick?.invoke(contact[adapterPosition])
            }
        }
}

Add addOnItemClickListener easily to a RecyclerView using Kotlin , import android.support.v7.widget.RecyclerView. import android.view.View. interface OnItemClickListener {. fun onItemClicked(position: Int, view: View). }. If you’ve used a RecyclerView, you may know that they don’t have a setOnItemClickListener as ListView had, so we have to create our own way to do it. Many people asked me how to do this, so that’s why I decided to write about it. There are many ways to achieve this, but I will show you the way I usually do it.


Set OnItemClickListener on RecycleView Android Kotlin · GitHub, class Adapter(private var hospitalList: ArrayList<MapsHospital>,. private var listener: OnItemClickListener). : RecyclerView.Adapter<MapsHospitalAdapter. In this android kotlin source code example, we are going to add RecyclerView item onItemClickListener in Kotlin. You can copy and adopt this source code example to your Kotlin android project without reinventing the wheel. Below is a step by step source code to add RecyclerView item onItemClickListener in Kotlin.


Defining item click listener for RecyclerView in Android, How do I implement onClick event in activity class in RecyclerView in Android?


What is difference between listview and recyclerview in Android , Use Lambda Expressions and function parameters to assign a click listener to items in a RecyclerView on Android. You don't need to define