当前位置: 首页 > 知识库问答 >
问题:

Kotlin中的RecyclerView itemClickListener[关闭]

梁马鲁
2023-03-14

我写我的第一个应用程序在静态编程语言后,与Android的3年经验。只是困惑于如何利用itemClickListener与静态编程语言回收视图。

我已经尝试了trait(edit: now界面)方法,非常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)
  }
}

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

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

然后设置适配器的click listener,如下所示:

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
}

共有3个答案

钮鸿煊
2023-03-14

如果有人想要一个更简单的答案,我尝试了以下方法——这与AfzalivE的解决方案非常相似:

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

我的适配器。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

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

MyActivity.kt:

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

使现代化

如果需要获取单击项的位置,只需在回调中将其定义为参数,然后稍后将其发送回。注意val clickListener:(MyObject,Int)-

我的适配器。kt

class MyAdapter constructor(objects: ArrayList<MyObject>, val clickListener: (MyObject, Int) -> Unit) : RecyclerView.Adapter<MyAdapter.Holder>() {
    // Rest of the code...

然后在onBindViewHolder()调用回调方法时传递位置:

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

还有我的活动。kt,你必须改变你设置适配器的方式,这样你才能得到位置。这样地:

myRecyclerView?.adapter = MyAdapter(mObjects) { itemDto: MyObject, position: Int ->
        Log.e("MyActivity", "Clicked on item  ${itemDto.someItemPropertyLikeName} at position $position")
    }

宋育
2023-03-14

我有一点不同的方法。您可以为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) {

    }
}

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

方安怡
2023-03-14

我的解决方案就像是将之前的方案与活动中的超级清洁通话相结合。

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

联系活动:

override fun setupRecyclerAdapter() {
    recyclerView.adapter = contactAdapter
    recyclerView.layoutManager = LinearLayoutManager(this)

    contactAdapter.onItemClick = { contact ->

        // do something with your item
        Log.d("TAG", contact.email)
    }
}
 类似资料:
  • 我试图理解继承与委派的斗争,以及如何实现这两者。我的问题是为什么我要用Kotlin的方式用by关键字实现委派?我觉得太过分了。 让我给你举个例子。我们有一个可以点餐的应用程序。这款应用名为DeliveryQueen。 下面是Java示例: Kotlin示例#1没有明确使用by关键字:

  • 在为android开发时,我有时会遇到类似这样的事情: 我不明白关键字有什么意义。

  • 我有一个按钮和编辑文本。当用户在编辑文本中完成输入并按下按钮时,我想关闭我的软键盘。 或它的任何指南或参考链接。

  • 下面的代码在无法通过条件颜色时编译。深色和彩色。浅色,因为这两个类是抽象的。 我错过什么了吗?

  • 我们可以编写包含或不包含的代码,如下所示。 或 的实际用途是什么?。这是内存效率更高还是可读性更强?

  • 我试图理解静态编程语言对泛型的理解,尤其是和关键字。我写了这篇简单的文章,希望能说明我的困惑点。 这是看起来可行的方法; 在这里,IDE给出了一个提示,说明for循环正在迭代的项目类型是。这很好。 上面方法的另一个版本乍一看似乎不太对劲(因为它是一个“消费者”)。但是我想做的就是阅读一个形状列表,这就是中