【问题标题】:RecyclerView itemClickListener in Kotlin [closed]Kotlin 中的 RecyclerView itemClickListener [关闭]
【发布时间】:2015-06-08 02:47:02
【问题描述】:

在拥有 3 年的 Android 经验后,我正在使用 Kotlin 编写我的第一个应用程序。 只是对如何在 Kotlin 中使用带有 RecyclerView 的 itemClickListener 感到困惑。

我已经尝试过 trait (edit: now interface) 方法,非常类似于 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)
    }
}

然后像这样设置适配器的点击监听器:

val adapter = WorkoutsAdapter(ItemClickListener())

但我仍然对此不满意,因为我认为可能有更好、更清洁的方法。我试图从本质上实现这样的目标: RecyclerView onClick

有什么建议吗?

最终选择了批准答案的变体

在activity中定义函数:

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

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

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

【问题讨论】:

  • 在你的activity中如何调用扩展函数onClick
  • 您在 Adapter 的构造函数中设置了 itemClickListener(本例中为 itemOnClick)。 ViewHolder 调用它。事后看来,这仍然有效,我可能应该更多地使用它,哈哈。这些天,每次都继续制作手动 onClick 方法。
  • 您也可以采用 Rx 或 LiveData 方法来避免使用回调来传递您的事件。

标签: android android-recyclerview kotlin


【解决方案1】:

我的解决方案就像以前的解决方案与来自活动的超级干净调用的组合。

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

【讨论】:

  • 不错,我喜欢这个
  • 我也是,它在我更新 UI 时解决了一个问题,非常感谢
  • 记得清除 onDestroyView 的引用,因为这可能会泄漏。
  • 谢谢,@denwehrle。我也喜欢 iOS 中的这种风格。
  • 这是什么override fun setupRecyclerAdapter?它从哪里覆盖?
【解决方案2】:

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

    }
}

我正在与我的同事一起在 library 上提供此类扩展。

【讨论】:

  • 这在适配器中被调用。如何在 mainActivity 中使用 this 作为回调?
  • @bpolat 你可以创建一个回调,例如 MyAdapter(private val itemClickedListener: (String) -> Unit),并在监听函数中用 itemClickedListener.invoke(item) 调用它。在你的活动中,你实例化适配器 = MyAdapter { /*在这里处理你的 cb*/ }
  • 如何处理longOnClickListener?
  • 通过这种方式onClick方法并不是每次都被调用。
  • 我注意到如果在方法onCreateViewHolder 中添加OnClickListener,那么有时它不起作用。所以我建议在方法onBindViewHolder中添加OnClickListener
【解决方案3】:

如果有人在寻找更简洁的答案,我尝试了以下方法 - 这与 AfzalivE 的解决方案非常相似:

在我的适配器类中,我将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}")
}  

更新

如果需要获取被点击项的位置,只需将其定义为回调中的参数,然后再将其发送回来。注意下面的val clickListener: (MyObject, Int) -&gt; Unit

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

MyActivity.kt 上,您必须更改设置适配器的方式,以便获得位置。像这样:

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

【讨论】:

  • @YLS 刚刚编辑了带有更新的帖子。在上面检查:)
  • 我喜欢这种简单易懂的方式
  • 我喜欢它!非常简洁的答案。
  • 应该避免这种方法,因为点击监听器应该在创建持有人时设置一次。通过这样做,你会触发很多 setOnClickListeners
  • 您可以使用ListAdapter 代替 RecyclerView.Adapter 并使用getItem(position) 检索当前项目而不是传递整个对象列表。
【解决方案4】:

抱歉耽搁了,从this 链接得到了一个很棒的答案,它是用 Java 编写的。 做了一些作业并将其转换为 Kotlin..

现在它可以正常工作了。这是代码,

创建一个名为 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(e.x, e.y)

            if (childView != null && mListener != null) {
                mListener.onItemLongClick(childView, recyclerView.getChildAdapterPosition(childView))
            }
        }
    })
}

override fun onInterceptTouchEvent(view: RecyclerView, e: MotionEvent): Boolean {
    val childView = view.findChildViewUnder(e.x, e.y)

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

并从 Activity/Fragment 访问它

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

【讨论】:

  • 当您可以在项目视图上设置点击侦听器时,为什么还需要手势检测器和触摸事件处理?
  • @EpicPandaForce ,这种基于 Activity 的点击的点击监听方式,而不是在适配器中。
  • @Sam 感谢您的反馈。
  • 这是一个了不起的人,你为我节省了一天的时间,而且也很有风格:)
  • 这是个好人...
【解决方案5】:

在onBindViewHolder fun上添加ClickListener代码

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
}

【讨论】:

  • 最简单但最好的答案!
  • 完美!感谢分享!
  • 在使用这种方法时如何显示 Toast 或使用 Intent?它抛出一个错误
  • @RaheelKhan 您需要使用holder.itemView.context 获取上下文,然后您也可以使用toast 和intent。例如:Toast.makeText(holder.itemView.context, list[position].toString(), Toast.LENGTH_SHORT).show()
  • 这种方法有什么缺点吗?在“位置”直接可用的地方设置监听器似乎是合乎逻辑的。
【解决方案6】:

略有不同,基于 denwehrle

在 OnCreateView 内部的片段上使用

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

在适配器类中添加:

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】:

于 05 - 2019 年更新

我认为最优雅的解决方案是将这个责任交给 recyclerView 而不是查看甚至调整它。

为此我们需要:

1:创建 RecyclerItemClickListener 文件

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:为 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:最后是使用(我想你使用 kotlinx)

import kotlinx.android.synthetic.main.{your_layout_name}.*

class FragmentName : Fragment() {

    override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
        recycler.affectOnItemClick { position, view -> /*todo*/ }
    }
}

【讨论】:

  • 有人能详细说明为什么这是一个好的解决方案吗?我是 Android 开发新手,这对我来说似乎非常冗长和样板。
  • 这是一个解决方案,但你的直觉是正确的——这里有太多的样板。虽然理解 kotlin 语法需要经过几次,但可以在这里找到一个不错的方法:antonioleiva.com/recyclerview-adapter-kotlin
【解决方案8】:

您不需要为 ViewHolder 或类似的东西编写扩展函数。
最佳实践;使用高阶函数

MainRecyclerAdapter

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

只需添加一个高阶函数。像 itemClickListener 然后转到 ViewHolder 类。将此函数作为参数写入您的绑定函数并将其设置为 itemView 就像这样:

MainRecyclerAdapter.ViewHolder

 class ViewHolder(val view: View) : RecyclerView.ViewHolder(view) {

        fun bind(newsItem: JSONObject,itemClickListener:(Int)->Unit) {
            //Some Stuff here..

            itemView.setOnClickListener { itemClickListener(adapterPosition) }

        }
    }

在BindViewHolder上使用这个方法

OnBindViewHolder

 override fun onBindViewHolder(holder: MainRecyclerAdapter.ViewHolder, position: Int) {

        holder.bind(news.getJSONObject(position),itemClickListener)
    }

现在您可以在任何活动或片段中编写您的 onClick 函数。只需作为参数。

活动或片段

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)

【讨论】:

  • 我的救主!我尝试了所有其他方法,只有这个对我有用。谢谢
【解决方案9】:

您可以通过使用界面轻松实现此目的

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

来自您的 MainActivity

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

【讨论】:

  • 这是迄今为止最简单、最优雅的解决方案。我不知道 WTF Google 在他们从 RecyclerView 中省略 onClickListener 时在想什么,但基于 StackOverflow 上的许多 CLOSED 线程,他们真的搞砸了。
【解决方案10】:

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

【讨论】:

    【解决方案11】:

    适配器构造函数声明

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

    Adapter::onBindViewHolder

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

    如何使用

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

    基本上,您将在 lambda 参数中收到作为 it 的 ItemObject。

    【讨论】:

      【解决方案12】:

      我的简单解决方案使用高阶函数和let 作用域函数仅在设置了itemAction 时设置监听器

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

      在活动/片段中

      adapter.setItemAction { // <- it is Item
        // do something with it
      }
      

      【讨论】:

      • 就像以前用于单击侦听器的 java 接口一样。我想要这个 kotlin 的解决方案,谢谢你的代码。
      【解决方案13】:

      这是一种不使用接口的简单方法,只需在您的适配器中创建一个 init 块在 viewholder 类中。像这样

       class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
          init {
              itemView.setOnClickListener{
          //your code here---
            }
          }
      

      }

      【讨论】:

      • 我希望人们不要再回答这个问题了。它不需要24个答案。尤其是看到这个问题有多老了,当 trait 是 Kotlin 的东西时。
      • 你绝不能在你的适配器中使用点击监听器!我从不重复!
      【解决方案14】:

      你可以试试这样的:

      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*/ })
              [...]
          }
      }
      

      【讨论】:

      • 添加完整示例以便更好地理解。
      【解决方案15】:

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

      【讨论】:

      • 很好的解决方案,这个对我很有用。谢谢。
      • 这里的listViewItem是属于什么的?
      【解决方案16】:

      最后,这是一个不错的解决方案:

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

      【讨论】:

      • 未解决的参考:clickable_view
      • @ykonda clickable_view 必须是您在 R.layout.my_item 中添加点击监听器的视图的 ID。
      【解决方案17】:

      //第一步制作一个类似的界面

      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 步在您的活动/片段中

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

      【讨论】:

        【解决方案18】:

        科特林

        像这样制作你的适配器构造函数

            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
                }
        

        在您的 Fragment 中,按如下方式实现

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

        【讨论】:

        • 如何制作两个或多个单元?或者如何通过视图? private val listener: ((DataFile, View) -> Unit)?,因为我需要知道。适配器上的视图,嗯
        • 类型不匹配。必需:((ArrFilesItem, View) → Unit)?找到:() → 单位
        • 我明白了,attachmentAdapter = AttachmentAdapter(attachmentMutableList) { 它:ArrFilesItem,视图:视图 ->
        【解决方案19】:

        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(e.x, e.y)
                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) {}
        }
        

        对于活动:

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

        对于片段:

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

        【讨论】:

          【解决方案20】:

          这是我的 MainActivity.kt 类,它使用 recyclerview 填充位置数据。它有一个简单的项目点击监听器接口,您可以实现它。

              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
              }
          

          【讨论】:

            【解决方案21】:

            如果有人对旧方式的实现感兴趣..

            我发布了完整的示例,它也减少了您的适配器代码。它使用获取回调的旧模式..

            项目级分级

            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

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

            【讨论】:

              【解决方案22】:

              您可以通过两种方式在 kotlin 中访问 recyclerview,首先您可以直接在适配器中声明 OnClickListener 并在其中进行重定向,第二种方法是您可以将 onclick 重定向到您设置了回收器适配器的片段/活动

              1.

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

              第二种方法是将您的适配器点击重定向到片段/活动,然后从那里重定向您的活动,而不是从适配器重定向

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

              【讨论】:

                【解决方案23】:

                哦,到底有人会喜欢这个 我们都将编辑和垃圾箱图像放在 recyclerview 中,并希望在单击它们时发生一些事情。这是我们的 Kotlin 示例

                这是在适配器中膨胀的卡片视图

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

                然后在Adapter中我们做一些绑定

                    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
                }
                

                简单快速可靠的享受

                【讨论】:

                • 很好,但请不要在其中使用相对布局
                【解决方案24】:

                我想出了这个解决方案,使用伴随对象和界面在单击行时打开一个活动。该活动是从主要活动中打开的,因为我必须在离开前保存列表状态。

                适配器

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

                【讨论】:

                  猜你喜欢
                  • 2020-12-31
                  • 2023-01-30
                  • 2021-05-23
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多