Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RecyclerView itemClickListener in Kotlin [closed]

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 } 
like image 941
Afzal N Avatar asked Apr 03 '15 01:04

Afzal N


1 Answers

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)     } } 
like image 130
denwehrle Avatar answered Sep 21 '22 04:09

denwehrle