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