RecyclerVer elementoClickListener en Kotlin

Estoy escribiendo mi primera aplicación en Kotlin después de 3 años de experiencia con Android. Sólo confundido en cuanto a la forma de utilizar itemClickListener con un RecyclerView en Kotlin.

He intentado el acercamiento del rasgo,

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

Eso parecía muy redundante así que intenté el acercamiento de la clase interna:

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

Y luego simplemente configurar el oyente de clics del adaptador de esta manera:

 val adapter = WorkoutsAdapter(ItemClickListener()) 

Pero todavía no estoy satisfecho con esto porque creo que podría haber una manera mejor y más limpia. Estoy intentando lograr algo como esto: RecyclerView onClick

¿Alguna sugerencia?

Terminó con una variación de la respuesta aprobada

Definición de la función en la actividad:

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

Se lo pasó al adaptador como este:

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

Función de extensión por Loop en la respuesta aprobada a continuación.

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

Tengo un enfoque un poco diferente. Puede crear una extensión para su ViewHolder

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

A continuación, utilícelo en un adaptador como este

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

Estoy trabajando con mis colegas en la biblioteca que proporciona tales extensiones.

Usted podría intentar algo como:

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

Y la conversión SAM sólo funciona como en Java 8, por lo que sólo tiene que utilizar un lambda:

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

En caso de que alguien está buscando una respuesta más sin lujos , he intentado lo siguiente – que es muy similar a la solución de AfzalivE :

En mi clase de adaptador pasé el clickListener como un parámetro. En onBindViewHolder , he utilizado setOnClickListener para llamar a clickListener y manejar el evento de clic.

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

Nota : Necesitaba una referencia del contenedor de mi elemento de lista (la vista raíz), que en este caso es containerView

Luego pasé mi objeto como parámetro sin necesidad de buscarlo en una lista de nuevo y manejarlo directamente en mi clase de Activity , en el momento en que configuro el adaptador:

MyActivity.kt :

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

En RecyclerView puede poner clic en la vista inflada dentro de la clase del visor y llamarla desde el método de devolución de llamada onBindViewHolder, por ejemplo:

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

Puede llamar desde el método onBindViewHolder del adaptador … por ejemplo:

  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]); } 
  • Recyclerview no llama aCreateViewHolder
  • No se puede usar getLayoutPosition () o getAdapterPosition () en RecyclerView
  • ¿Cómo saber si un RecyclerView / LinearLayoutManager se desplaza hacia arriba o abajo?
  • ¿Cómo realizar un seguimiento de los elementos seleccionados en un RecyclerView en Android?
  • ListSelector para RecyclerView en el dispositivo táctil libre (usando onKey Listener)
  • ¿Cómo detectar si RecyclerView está vacío?
  • Android recyclerView findViewHolderForAdapterPosition devuelve null
  • Recyclerview no cambia de tamaño después de girar la pantalla
  • ¿Cómo agregar un botón al final de RecyclerView?
  • Diferencia entre android.support.v7.app.AlertController.RecycleListView y android.support.v7.widget.RecyclerView
  • Agregue una vista dinámicamente al elemento del RecyclerView
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.