RecyclerView itemClickListener in Kotlin

I am writing my first application in Kotlin after 3 years of Android experience. Just confused how to use itemClickListener with RecyclerView in Kotlin.

I tried an approach (edit: now interface) very similar to Java

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) } } 

This seemed very redundant, so I tried using the inner class:

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

And then just configure the adapter click listener as follows:

 val adapter = WorkoutsAdapter(ItemClickListener()) 

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

Any suggestions?

Finished with change approved answer

The function in activity is defined:

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

Transferring the function itself to the adapter as follows:

 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 with Loop in the 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 } 
+37
android kotlin android-recyclerview
source share
23 answers

I have a slightly 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 an 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 work with library colleagues to provide such extensions.

+21
source share

My solution is similar to combining the previous ones with a super clean call from 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) } } 
+37
source share

Sorry for the delay, Got a great response from this link, and he was in Java .. Did the homework and converted it to Kotlin ..

Now it works properly .. Here is the code,

Create a class called 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(ex, ey) if (childView != null && mListener != null) { mListener.onItemLongClick(childView, recyclerView.getChildAdapterPosition(childView)) } } }) } override fun onInterceptTouchEvent(view: RecyclerView, e: MotionEvent): Boolean { val childView = view.findChildViewUnder(ex, ey) 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") } })) 
+10
source share

In case anyone is looking for a more carefree answer, I tried the following: this is very similar to the solution from AfzalivE :

In my adapter class, I passed clickListener as a parameter. In onBindViewHolder I used setOnClickListener to call the clickListener and handle the 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 need a link from my container of list items (root view), which in this case is equal to containerView

Then I passed my object as a parameter without having to search it again in the list and processed it directly in my Activity class at the time the adapter was installed:

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 a parameter in the callback, and then send it later. Pay attention to 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, onBindViewHolder() you pass the position when you call 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 in MyActivity.kt you will have to change the way the adapter is installed so that 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") } 
+8
source share

A little different, based on denwehrle

Use on fragment inside OnCreateView

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

Add to 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]) } } } 
+7
source share

Updated on 05 - 2019

I think the most elegant solution is to assign this responsibility to recyclerView, rather than view or even adapt it.

for this we need:

1: Create RecyclerItemClickListener File

 class RecyclerItemClickListener( private val mRecycler: RecyclerView, private val clickListener: ((position: Int, view: View) -> Unit)? = null, private val longClickListener: ((position: Int, view: View) -> Unit)? = null ) : RecyclerView.OnChildAttachStateChangeListener { override fun onChildViewDetachedFromWindow(view: View) { view.setOnClickListener(null) view.setOnLongClickListener(null) } override fun onChildViewAttachedToWindow(view: View) { view.setOnClickListener { v -> setOnChildAttachedToWindow(v) } } private fun setOnChildAttachedToWindow(v: View?) { if (v != null) { val position = mRecycler.getChildLayoutPosition(v) if (position >= 0) { clickListener?.invoke(position, v) longClickListener?.invoke(position, v) } } } } 

2. Creating / adding extensions for RecyclerView:

 import android.support.v7.widget.RecyclerView import com.app.manager.internal.common.RecyclerItemClickListener @JvmOverloads fun RecyclerView.affectOnItemClicks(onClick: ((position: Int, view: View) -> Unit)? = null, onLongClick: ((position: Int, view: View) -> Unit)? = null) { this.addOnChildAttachStateChangeListener(RecyclerItemClickListener(this, onClick, onLongClick)) } 

3: And finally, use (I assume you are using kotlinx)

 import kotlinx.android.synthetic.main.{your_layout_name}.* class FragmentName : Fragment() { override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { recycler.affectOnItemClick { position, view -> /*todo*/ } } } 
+5
source share

Adapter constructor declaration

 class YourAdapter(private val mListener: (ItemObject) -> Unit) : RecyclerView.Adapter<ViewHolder>() 

Adapter :: onBindViewHolder

 holder.itemView.setOnClickListener { mListener.invoke(item) // <- item instance of ItemObject } 

How to use

 mTypesWasteAdapter = YourAdapter({ it.something()}) 

Basically, you get ItemObject as it in the lambda argument.

+3
source share

You can try something like:

 public class MainActivity : ActionBarActivity() { protected override fun onCreate(savedInstanceState: Bundle?) { [...] val adapter = DrawAdapter(::onItemClick) [...] } } fun onItemClick(view: View, position: Int) { //Do work } 

and SAM conversion only works as in Java 8, so just use lambda:

 public class MainActivity : ActionBarActivity() { protected override fun onCreate(savedInstanceState: Bundle?) { [...] val adapter = DrawAdapter({view, position -> /*Do work*/ }) [...] } } 
+2
source share

Add ClickListener code to onBindViewHolder

 override fun onBindViewHolder(holder: ViewHolder, position: Int) { holder.vieww.textView.setText(arr.get(position)) holder.vieww.setOnClickListener {(holder.vieww.textView.setTextColor(Color.GREEN))} // click event } 
+2
source share

You do not need to write an extension function for ViewHolder or something like that.
Best practice; use a higher order function

MainRecyclerAdapter

 class MainRecyclerAdapter(val news: JSONArray, private val itemClickListener: (Int) -> Unit) : RecyclerView.Adapter<MainRecyclerAdapter.ViewHolder>() {} 

Just add a higher order function. like itemClickListener, and then go to the ViewHolder class. Write this function to your binding function as a parameter and set itemView for it

MainRecyclerAdapter.ViewHolder

  class ViewHolder(val view: View) : RecyclerView.ViewHolder(view) { fun bind(newsItem: JSONObject,itemClickListener:(Int)->Unit) { //Some Stuff here.. itemView.setOnClickListener { itemClickListener(adapterPosition) } } } 

Use this method onBindViewHolder

OnBindViewHolder

  override fun onBindViewHolder(holder: MainRecyclerAdapter.ViewHolder, position: Int) { holder.bind(news.getJSONObject(position),itemClickListener) } 

And now you can write your onClick function in any activity or snippet. Just specify as a parameter.

Activity or fragment

 val itemOnClick: (Int) -> Unit = { position -> newsRecyclerView.adapter!!.notifyDataSetChanged() Toast.makeText(this.context,"$position. item clicked.",Toast.LENGTH_SHORT).show() } newsRecyclerView.adapter = MainRecyclerAdapter(news,itemClickListener = itemOnClick) 
+2
source share

Finally, here is a good working solution:

MyRecyclerAdapter.kt

 class MyRecyclerAdapter(val context: Context, val items : ArrayList<Item>, val clickListener: (Int) -> Unit) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { override fun onCreateViewHolder(parent: ViewGroup, p1: Int): RecyclerView.ViewHolder { return MyViewHolder(LayoutInflater.from(context).inflate(R.layout.my_item, parent, false)) } override fun getItemCount(): Int { return items.size } override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { (holder as MyViewHolder).clickableView.setOnClickListener { clickListener(position) } } } class MyViewHolder (view: View) : RecyclerView.ViewHolder(view) { val clickableView = view.clickable_view } 

MainActivity.kt

 fun appClickListener(position: Int) { // You got the position of ArrayList } my_recyclerview.adapter = MyRecyclerAdapter(this, myList, clickListener = { appClickListener(it) }) 
+2
source share

You can easily achieve this using the interface.

 class ExercisesAdapter constructor(val mItemClickListener:ItemClickListener) : RecyclerView.Adapter<RecyclerView.ViewHolder>() { interface ItemClickListener{ fun onItemClick(position: Int) fun onLongClick(position: Int) } inner class MyViewHolder(view:View): RecyclerView.ViewHolder(view){ init { view.setOnClickListener{ mItemClickListener.onItemClick(adapterPosition) } view.setOnLongClickListener{ mItemClickListener.onLongClick(adapterPosition) return@setOnLongClickListener true } } } } 

From your core business

 public class MainActivity : ActionBarActivity(), ExercisesAdapter.ItemClickListener { protected override fun onCreate(savedInstanceState: Bundle?) { // set content view etc go above this line mAdapter = ExercisesAdapter(this) } override fun onItemClick(position: Int) { Toast.makeText(this@MainActivity, "TEST: " + position, Toast.LENGTH_SHORT).show() } override fun onLongClick(position: Int) { //do long click here } } 
+2
source share

In RecyclerView, you can click on the bloated view inside the ViewHolder class and call it from the onBindViewHolder of the onBindViewHolder callback, for example:

 class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { val view = view val tv_message = view.tv_message val tv_address = view.tv_address fun bind(listViewItem: ListViewItem) { view.setOnClickListener(View.OnClickListener { Toast.makeText( view.context, "Name: " + listViewItem.name + "/n Address: " + listViewItem.address, Toast.LENGTH_LONG).show() }) } } } 

You can call from the onBindViewHolder() adapter:

 override fun onBindViewHolder(holder: ViewHolder, position: Int) { val listViewItem: ListViewItem = mListViewItems[position] holder.tv_message.text = listViewItem.name holder.tv_address.text = listViewItem.address holder.bind(mListViewItems[position]); } 
+1
source share

RecyclerItemClickListener

 package com.mypackage.custom import android.content.Context import android.support.v7.widget.RecyclerView import android.view.GestureDetector import android.view.MotionEvent import android.view.View @Suppress("DEPRECATION") class RecyclerItemClickListener(context: Context, private val mListener: OnItemClickListener?) : RecyclerView.OnItemTouchListener { private var mGestureDetector: GestureDetector = GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() { override fun onSingleTapUp(e: MotionEvent): Boolean { return true } }) interface OnItemClickListener { fun onItemClick(view: View, position: Int) } override fun onInterceptTouchEvent(view: RecyclerView, e: MotionEvent): Boolean { val childView = view.findChildViewUnder(ex, ey) if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) { mListener.onItemClick(childView, view.getChildPosition(childView)) return true } return false } override fun onTouchEvent(view: RecyclerView, motionEvent: MotionEvent) {} override fun onRequestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {} } 

For activities:

  recyclerView!!.addOnItemTouchListener( RecyclerItemClickListener(this!!, object : RecyclerItemClickListener.OnItemClickListener { override fun onItemClick(view: View, position: Int) { //Write your code here } }) 

For fragment:

 recyclerView!!.addOnItemTouchListener( RecyclerItemClickListener(this!!.activity!!, object : RecyclerItemClickListener.OnItemClickListener { override fun onItemClick(view: View, position: Int) { //Write your code here } }) 
+1
source share

My simple solution using a higher order function and let visibility function to set the listener only if itemAction been set

 // Adapter private var itemAction: ((Item) -> Unit)? = null fun setItemAction(action: (Item) -> Unit) { this.itemAction = action } inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { fun setItem(item: Item) { // ... itemAction?.let { itemView.setOnClickListener { it(item) } } } } 

and in action / fragment

 adapter.setItemAction { // <- it is Item // do something with it } 
+1
source share

Two ways to access recyclerview in kotlin is first you can directly declare OnClickListener in the adapter and do a redirection inside it, and secondly, you can redirect your onclick to the fragment / activity where you installed the recycler adapter

one.

  class CartAdapter(context: Context) : RecyclerView.Adapter<CartAdapter.ViewHolder>() { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { return ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.layout_cart, parent, false)); } override fun getItemCount(): Int { return 10; } override fun onBindViewHolder(holder: ViewHolder, position: Int) { holder.itemView.rtbProductRating.setOnClickListener{ var iNavigation= Intent(context,MainActivity::class.java) iNavigation.flags= Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT context.startActivity(iNavigation) // directly redirect your activity from adapter } } class ViewHolder(itemView: View?) : RecyclerView.ViewHolder(itemView) } 

The second way you can use is to redirect your adapter, click on a fragment / action, and then redirect your activity there instead of redirecting from the adapter

  class CartAdapter(context: Context, onClickListener: View.OnClickListener) : RecyclerView.Adapter<CartAdapter.ViewHolder>() { var context = context var onClickListener = onClickListener override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { return ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.layout_cart, parent, false)); } override fun getItemCount(): Int { return 10; } override fun onBindViewHolder(holder: ViewHolder, position: Int) { //set your position to the view holder.itemView.rtbProductRating.tag = position //redirect click to the fragment holder.itemView.rtbProductRating.setOnClickListener { onClickListener.onClick(holder.itemView.rtbProductRating) } // holder.itemView.tv_waybill_count.text = holder.itemView.context.getString(R.string.waybills,5) } class ViewHolder(itemView: View?) : RecyclerView.ViewHolder(itemView) } Your fragment will look like: class CartFragment: BaseFragment(),View.OnClickListener { override val layout= R.layout.frg_cart override fun onClick(v: View?) { var position=v?.tag as Int if(position==0){ var iNavigation= Intent(this,MainActivity::class.java) iNavigation.flag=Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT startActivity(iNavigation) } } override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) listener() } private fun listener() { cart_rv.adapter=CartAdapter(activity,this) } } 
0
source share

Oh my gosh, someone might like this. We all put editing and the trash in our re-view window and would like something to happen when they are clicked. Here is our Kotlin example

This is in the form of a card that inflates in the adapter

  <RelativeLayout android:id="@+id/editCLICK" android:layout_width="60dp" android:layout_height="60dp" android:layout_marginStart="370dp" android:paddingLeft="6dp" android:paddingRight="6dp" android:paddingTop="12dp"> <ImageView android:id="@+id/ivEdit" android:layout_width="30dp" android:layout_height="30dp" android:background="@color/color_Transparent" android:src="@drawable/ic_edit" android:tint="@color/color_lightBlue" /> </RelativeLayout> 

then in the adapter we do some bindings

  override fun onBindViewHolder(holder: ParentViewHolder, position: Int) { val items = parentList[position] holder.item.text = items.dept holder.editCLICK.setOnClickListener { val i = Intent(context, EnterParentActivity::class.java) i.putExtra("FROM", "U") i.putExtra("MainActId",items.idD) i.putExtra("PFK",items.fkD) i.putExtra("ET",items.dept) i.flags = Intent.FLAG_ACTIVITY_NEW_TASK context.startActivity(i) } } inner class ParentViewHolder(view: View):RecyclerView.ViewHolder(view){ var item: TextView = view.findViewById(R.id.tvDept) as TextView var editCLICK: RelativeLayout = view.findViewById(R.id.editCLICK) as RelativeLayout } 

Simple quick and reliable enjoyment

0
source share

Here is my MainActivity.kt class that uses recyclerview to populate location data. It has a simple element click listener interface that you can implement.

  class MainActivity : AppCompatActivity() { private lateinit var recyclerView: RecyclerView private lateinit var viewAdapter: RecyclerView.Adapter<*> private lateinit var viewManager: RecyclerView.LayoutManager private var locationArrayList = arrayListOf<Location>() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) //create locations var ny = Location("New York") var la = Location("Los Angeles") locationArrayList.addAll(listOf(ny, la)) viewManager = LinearLayoutManager(this) viewAdapter = LocationsAdapter(locationArrayList) recyclerView = findViewById<RecyclerView>(R.id.recyclerView).apply { // use this setting to improve performance if you know that changes // in content do not change the layout size of the RecyclerView setHasFixedSize(true) // use a linear layout manager layoutManager = viewManager // specify an viewAdapter adapter = viewAdapter } //recycler view click listener implement recyclerView.addOnItemClickListener(object: OnItemClickListener { override fun onItemClicked(position: Int, view: View) { // Your logic Toast.makeText(this@MainActivity, locationArrayList[position].locationName, Toast.LENGTH_SHORT).show() } }) } //on item click interface interface OnItemClickListener { fun onItemClicked(position: Int, view: View) } fun RecyclerView.addOnItemClickListener(onClickListener: OnItemClickListener) { this.addOnChildAttachStateChangeListener(object: RecyclerView.OnChildAttachStateChangeListener { override fun onChildViewDetachedFromWindow(view: View?) { view?.setOnClickListener(null) } override fun onChildViewAttachedToWindow(view: View?) { view?.setOnClickListener({ val holder = getChildViewHolder(view) onClickListener.onItemClicked(holder.adapterPosition, view) }) } }) } //end of interface } 
0
source share

If someone is interested in implementing the old method ..

I posted a complete example that also reduces the code of your adapter. It uses the old callback receiving pattern.

Project level gradle

 buildscript { ext.kotlin_version = '1.3.10' repositories { google() mavenCentral() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.2.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"//newly added classpath 'com.google.gms:google-services:4.1.0' // google-services plugin // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } } allprojects { repositories { google() mavenCentral() jcenter() } } task clean(type: Delete) { delete rootProject.buildDir } 

Gradle Application Level

 apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-kapt' apply plugin: 'kotlin-android-extensions' apply plugin: 'org.jetbrains.kotlin.android.extensions'//it is used for @Percelize android { compileSdkVersion 28 dataBinding { enabled = true } androidExtensions { experimental = true } defaultConfig { applicationId 'broadpeak.firebase.learning' minSdkVersion 19 targetSdkVersion 27 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" multiDexEnabled true } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } productFlavors { } } /*kapt { generateStubs = true }*/ dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'com.android.support:design:28.0.0' implementation 'com.android.support.constraint:constraint-layout:1.1.3' implementation 'com.google.firebase:firebase-core:16.0.5' implementation 'com.google.firebase:firebase-firestore:17.1.3' implementation 'com.google.firebase:firebase-auth:16.0.5' implementation 'com.google.firebase:firebase-messaging:17.3.4' implementation 'com.google.code.gson:gson:2.8.5' implementation 'com.firebaseui:firebase-ui-auth:4.1.0' implementation 'com.github.bumptech.glide:glide:4.8.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0' ////kapt "com.android.databinding:compiler:$android_plugin_version"\ // not required above 3.2.0 ///kapt "com.android.databinding:compiler:3.1.4" testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' } // ADD THIS AT THE BOTTOM apply plugin: 'com.google.gms.google-services' 

SubjectListActivity.class

 class SubjectListActivity : BaseActivity() { var subjects = mutableListOf<SubjectBO>() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.question_list_activity) recycler_view.itemAnimator = DefaultItemAnimator() recycler_view.setHasFixedSize(true) recycler_view.layoutManager = LinearLayoutManager(this@SubjectListActivity) db.collection("tagCollection").get().addOnSuccessListener { querySnapshot -> if (querySnapshot.isEmpty()) { Log.d(TAG, "onSuccess: LIST EMPTY") } else { // Convert the whole Query Snapshot to a list // of objects directly! No need to fetch each document. subjects = querySnapshot.toObjects(SubjectBO::class.java) if(subjects.size > 0){ recycler_view.adapter = SubjectAdapter(subjects, object : OnRecyclerItemClickListener { override fun onItemClicked(view: View?, position: Int) { var intent = Intent(this@SubjectListActivity,McqActivity::class.java) intent.putExtra("keyTagBO",subjects.get(position)) startActivity(intent) } }); } } }.addOnFailureListener { exception -> exception.printStackTrace() } } 

SubjectAdapter.class

 class SubjectAdapter(items: List<SubjectBO>, onRecyclerItemClickListener: OnRecyclerItemClickListener) : BaseAdapter<SubjectBO, SubjectViewHolder>(items, onRecyclerItemClickListener) { override fun onCreateViewHolder(parent: ViewGroup, p1: Int): SubjectViewHolder { return SubjectViewHolder(parent, R.layout.item_subject, onRecyclerItemClickListener) } } 

SubjectViewHolder.class

 class SubjectViewHolder(parent: ViewGroup, itemLayoutId: Int, onRecyclerItemClickListener: OnRecyclerItemClickListener) : BaseViewHolder<SubjectBO>(parent, itemLayoutId, onRecyclerItemClickListener) { override fun bindData(data: SubjectBO) { itemView.tvTitle.setText(data.tagName) } } 

BaseAdapter.class

 abstract class BaseAdapter<T, U : BaseViewHolder<T>> (var items: List<T>, var onRecyclerItemClickListener: OnRecyclerItemClickListener) : RecyclerView.Adapter<U>() { override fun getItemCount(): Int { return items.size } override fun onBindViewHolder(holder: U, pos: Int) { holder.bindData(items.get(pos)) } } 

BaseViewHolder.class

 abstract class BaseViewHolder<T : BaseModel>(parent: ViewGroup, @LayoutRes itemLayoutId: Int, var onRecyclerItemClickListener: OnRecyclerItemClickListener) : RecyclerView.ViewHolder(LayoutInflater.from(parent.context).inflate(itemLayoutId, parent, false)), View.OnClickListener { override fun onClick(v: View?) { onRecyclerItemClickListener.onItemClicked(v, adapterPosition) } abstract fun bindData(data: T) init { itemView.setOnClickListener(this) } } 

OnRecyclerItemClickListener.class

 interface OnRecyclerItemClickListener{ fun onItemClicked(view: View?, position: Int) } 
0
source share

// 1

 interface RecyclerViewClickListener { fun onItemClick(position: String) fun onLongClick(position: Int) } 

2 Adapter ,

 class ModelAdapter(var item_list: ArrayList<UploadDocument>,var mItemClickListener:RecyclerViewClickListener) : RecyclerView.Adapter<ModelAdapter.ViewHolder>() { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ModelAdapter.ViewHolder { // create a new view val view = LayoutInflater.from(parent.context).inflate(R.layout.upload_document_row_item, null) // create ViewHolder return ViewHolder(view) } override fun onBindViewHolder(holder: ModelAdapter.ViewHolder, position: Int) { holder.txtRegistrationDoc?.setText(item_list[position].getdocName()) holder.txtCertificate?.setText(item_list[position].getcertificateName()) holder.txtFileSize?.setText(item_list[position].getfileSize()) holder.txtCreatedOn?.setText(item_list[position].getcreatedOn()) holder.txtModifiedOn?.setText(item_list[position].getModifiedDate()) //holder.chkSelected.isChecked = item_list[position].isSelected() holder.chkSelected.tag = item_list[position].getdocName() holder. chkSelected!!.setOnCheckedChangeListener { buttonView, isChecked -> if(isChecked) { System.out.println("position>>>"+buttonView.tag.toString()) mItemClickListener.onItemClick(buttonView.tag.toString()) } } //(context as UploadDocumentActivity::class.java).onClickCalled("your argument here") /* holder.btn_delete.setOnClickListener(object : View.OnClickListener() { override fun onClick(v: View) { deleteItemFromList(v, position) } })*/ } override fun getItemCount(): Int { return item_list.size } /*// confirmation dialog box to delete an unit private fun deleteItemFromList(v: View, position: Int) { val builder = AlertDialog.Builder(v.getContext()) //builder.setTitle("Dlete "); builder.setMessage("Delete Item ?") .setCancelable(false) .setPositiveButton("CONFIRM", DialogInterface.OnClickListener { dialog, id -> item_list.remove(position) notifyDataSetChanged() }) .setNegativeButton("CANCEL", DialogInterface.OnClickListener { dialog, id -> }) builder.show() }*/ class ViewHolder( itemLayoutView: View) : RecyclerView.ViewHolder(itemLayoutView) { var item_name: TextView var txtRegistrationDoc: TextViewNormal?=null var txtCertificate: TextViewNormal?=null var txtFileSize: TextViewNormal?=null var txtCreatedOn: TextViewNormal?=null var txtModifiedOn: TextViewNormal?=null var chkSelected: CheckBox init { item_name = itemLayoutView.findViewById(R.id.txt_Name) txtRegistrationDoc = itemLayoutView.findViewById(R.id.txtRegistrationDoc) txtCertificate = itemLayoutView.findViewById(R.id.txtCertificate) txtFileSize = itemLayoutView.findViewById(R.id.txtFileSize) txtCreatedOn = itemLayoutView.findViewById(R.id.txtCreatedOn) txtModifiedOn = itemLayoutView.findViewById(R.id.txtModifiedOn) //btn_delete = itemLayoutView.findViewById(R.id.btn_delete_unit) chkSelected = itemLayoutView.findViewById(R.id.chk_selected) } } } 

// 3 /Frgament

 recyclerView?.adapter = ModelAdapter(documentList,object : 'in'.mobilepedia.com.gicgwaliarincubationcentre.RecyclerViewClickListener { override fun onItemClick(position: String) { System.out.println("Position>>>>>"+position) } override fun onLongClick(position: Int) { } }) 
0
source share

, , . , .

 class MyAdapter( val dataList: List<objects.ListObject>, val listener: ItemClickListener ) : RecyclerView.Adapter<MyAdapter.ListViewHolder>() { companion object { var mClickListener: ItemClickListener? = null } interface ItemClickListener { fun clickRow(position: Int) } override fun onBindViewHolder(holder: MyAdapter.ListViewHolder, position: Int) { holder.bindData( ... ) mClickListener = listener holder.itemView.setOnClickListener { view -> mClickListener?.clickRow(position) } } ... } 

 val context = this private lateinit var mMyAdapter: MyAdapter fun initList() { mMyAdapter = MyAdapter(dataList, object : MyAdapter.ItemClickListener { override fun clickRow(position: Int) { openActivityListItems(position) } } ) } fun openActivityListItems(position : Int) { recyclerViewState = mListView.getLayoutManager()?.onSaveInstanceState() val intent = Intent(context, ListItems::class.java) intent.putExtra("Parameter1", dataList[position].Parameter1) intent.putExtra("Parameter2", dataList[position].Parameter2) context.startActivity(intent) } 
0
source share

Kotlin

,

  class ViewAdapter( private val context: Context, private val mListener: (DataClass) -> Unit ) : RecyclerView.Adapter<WeekRecyclerViewAdapter.ViewHolder>() { // Your adapter code goes here } 

onBindViewHolder ,

 holder.binding.parentLayout.setOnClickListener { mListener.invoke(items[position]) // <- item instance of ItemObject } 

,

 class YourFragment : Fragment(), (DataClass) -> Unit { override fun invoke(p1: DataClass) { //You will get the selected item here } 
0
source share

3 :

1. :

 class ListAdapter(private val mListener: (ListItemDataClass) -> Unit) 

2. onBindViewHolder

 override fun onBindViewHolder(holder: YourViewHolder, position: Int) { val item = getItem(position) holder.itemView.setOnClickListener { item?.let { it1 -> mListener.invoke(it1) } } } 

3.

 val adapter = ListAdapter { Toast.makeText(this, it.title, Toast.LENGTH_SHORT).show() } 
0
source share

All Articles