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 }
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) } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With