RetrlerView itemClickListener在Kotlin中

在Android 3年的经验之后,我在Kotlin写了我的第一个应用程序。 只是混淆了如何在Kotlin中使用带有RecyclerView的itemClickListener。

我已经尝试了特质的方法,

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

这似乎很冗余,所以我尝试了内部类的方法:

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

然后设置适配器的点击监听器,如下所示:

 val adapter = WorkoutsAdapter(ItemClickListener()) 

但是我还是不满意,因为我觉得可能会有更好,更干净的方式。 我试图从本质上实现这样的事情: RecyclerView onClick

有什么建议么?

结束了与批准的答案的变化

在活动中定义了函数:

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

将其传递到适配器,如下所示:

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

在下面批准的答案中通过循环扩展功能。

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

我有一个不同的方法。 您可以为您的ViewHolder创建一个扩展

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

我正在和图书馆的同事一起提供这样的扩展。

你可以尝试像这样:

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

和SAM转换就像在Java 8中工作,所以只需使用lambda:

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

如果有人正在寻找一个更简洁的答案,我尝试了以下 – 这非常类似于AfzalivE的解决方案:

在我的Adapter类中,我传递了clickListener作为参数。 在onBindViewHolder ,我使用setOnClickListener来调用clickListener并处理单击事件。

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

注意 :我需要从我的列表项的容器(根视图),在这种情况下是containerView视图的参考

然后我传递我的对象作为参数,而不需要再次在列表中搜索它,直接在我的Activity类中处理它,在我设置适配器的那一刻:

MyActivity.kt

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

在RecyclerView中,你可以点击viewholder类中的充气视图,并从onBindViewHolder回调方法调用它,例如:

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

你可以调用适配器onBindViewHolder方法…例如:

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