问题:
What's the correct way to create a click listener for an item in a RecyclerView adapter? This tutorial says it should be done in onBindViewHolder but others have said in on...
可以将文章内容翻译成中文,广告屏蔽插件会导致该功能失效:
问题:
What's the correct way to create a click listener for an item in a RecyclerView
adapter? This tutorial says it should be done in onBindViewHolder
but others have said in onCreateViewHolder
and I've not seen any tutorials for the latter hence I'm perplexed.
class MyRVAdapter(private val myList: ArrayList<Item>) : RecyclerView.Adapter<MyRVAdapter.ViewHolder>() {
override fun getItemCount(): Int {
return myList.size
}
class ViewHolder (itemView : View):RecyclerView.ViewHolder(itemView) {
// val myButton = itemView.findViewById<Button>(R.id.btn_A)!!
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.myButton.text = (myList[position].btnTitle)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.my_cv, parent, false)
return ViewHolder(v)
val myButton = v.findViewById<Button>(R.id.btn_A)!!
myButton.setOnClickListener {
customView = View.inflate(holder.itemView.context, R.layout.fragment_dialog, null)
val builder = AlertDialog.Builder(holder.itemView.context)
builder.setIconAttribute(R.attr.imgInfo)
builder.setTitle(R.string.dialog_title)
builder.setView(customView)
builder.setPositiveButton(android.R.string.ok){ dialog, _ -> dialog.dismiss() }
builder.show()
}
}
}
回答1:
In Kotlin
In Kotlin you cant implement onClickListener in ViewHolderClass directly. In Kotlin to achieve the same, you have to do onClickListener inside onBindViewHolder
holder.myButton.setOnClickListener {
//do your stuff here
}
or use init function
// I'm not sure this is a correct method or not
class MyRVAdapter : RecyclerView.Adapter<MyRVAdapter.ViewHolder>() {
override fun getItemCount(): Int {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyRVAdapter.ViewHolder {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
var myButton = itemView.findViewById(R.id.button) as Button
// use any of the following declaratons
// val myButton = itemView.findViewById(R.id.button) as Button
// val myButton = itemView.findViewById<Button>(R.id.button)
// var myButton = itemView.findViewById<Button>(R.id.button)
// var myButton:Button = itemView.findViewById(R.id.button)
// val myButton:Button = itemView.findViewById(R.id.button)
// to avoid Expecting Member Declaration is showing in kotlin use constructor
// Expecting Member Declaration is showing because kotlin allows null declaration so a constructor or init is required to avoid this
init {
myButton.setOnClickListener{
//do your stuff here
}
}
}
}
In Java
onBindViewHolder
will be executed whenever there is a change in data. So it is good to write the onClickListener
in The ViewHolderClass
.
myButton.setOnClickListener {
//do your stuff here
}
回答2:
The correct way is to make it work in its simplest form.
Can you assign the listener "ahead" from onCreateViewHolder
, and if so why wouldn't you?
Consider the fact that onBindViewHolder
will get repeatedly executed.
Unless you obtain new data affecting your view after the viewholder creation, there should be no reason to change your listener "during the execution" from recurrent onBindViewHolder
calls.
回答3:
onBindViewHolder()
will be called all the time when your Views appear on the screen so it is called more that your items' count. You will create lots of duplicate listeners when you scroll. Setting listener in ViewHolder will create one listener per holder. Here is the code:
class MyRVAdapter() : RecyclerView.Adapter<MyRVAdapter.ViewHolder>() {
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.myButton.text = "set here all except listener"
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.my_cv, parent, false)
return ViewHolder(v)
}
override fun getItemCount(): Int {
return myList.size
}
class ViewHolder (itemView: View) : RecyclerView.ViewHolder(itemView) {
var myButton: Button = itemView.findViewById(R.id.btn_A)
init {
myButton.setOnClickListener {
val customView = View.inflate(itemView.context, R.layout.fragment_dialog, null)
val builder = AlertDialog.Builder(itemView.context)
builder.setIconAttribute(R.attr.imgNight)
builder.setTitle(R.string.dialog_title)
builder.setView(customView)
builder.setPositiveButton(android.R.string.ok){ dialog, _ -> dialog.dismiss() }
builder.show()
val tabLayout = customView.findViewById(R.id.mTabLayout)
val viewPager = customView.findViewById(R.id.mViewPager)
val adapter = TabbedDialogAdapter(childFragmentManager)//i dont understand how you get this but it is another question
adapter.addFragment("Tab A", TabbedDialogFragment.createInstance("Description A"))
adapter.addFragment("Tab B", TabbedDialogFragment.createInstance("Description B"))
adapter.addFragment("Tab C", TabbedDialogFragment.createInstance("Description C"))
viewPager.adapter = adapter
tabLayout.setupWithViewPager(viewPager)
}
}
}
}