Kotlin Android Studio - handle button click inside recyclerView adapter

孤街浪徒 提交于 2020-03-20 06:46:48

问题


I have a recyclerView adapter named ArticleAdapter

import kotlinx.android.synthetic.main.articlerecycler_item.view.*


class ArticleAdapter(private val controller: IController) : RecyclerView.Adapter<ArticleViewHolder>() {

  override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ArticleViewHolder {
      val view = LayoutInflater.from(parent.context).inflate(R.layout.articlerecycler_item, parent, false)
      return ArticleViewHolder(view)


  }
    // How implement a button click for `btnSave`
    /** Called when the user taps the Save button  */
     btnSave.setOnClickListener(){
        (R.layout.articlerecycler_item)
        AlertDialog.Builder(this)
                .setMessage("Article Saved.")
                .create()
                .show()
        // Do something in response to button click
    }

  override fun getItemCount(): Int {
      return controller.articles.size
  }

  override fun onBindViewHolder(holder: ArticleViewHolder, position: Int) {

      val article: Article = controller.articles[position]

      if(article.title.length > 100) {
        holder.itemView.titleTv.text = "${article.title.substring(0, 99)}..."
      } else {
        holder.itemView.titleTv.text = article.title
      }

      holder.itemView.authorTv.text = article.author
  }

}
class ArticleViewHolder(view: View?) : RecyclerView.ViewHolder(view)

Then in my recyclerView layout I have a button

<Button
    android:id="@+id/btnSave"
    android:layout_width="70dp"
    android:layout_height="40dp"
    android:onClick="btnSave"
    android:text="@string/save"
    android:textAlignment="center" />

Do I handle the event inside onBindViewHolder? I'm not sure how to implement the listener within my recyclerView adapter


回答1:


A good solution to handle the items click of an adapter is to pass them to the activity or fragment which has created them.

With kotlin you can use function definition instead of an interface for this simple work, so inside your adapter class add a var of a function type:

private var listener: ((item: DataClass) -> Unit)? = null

fun setOnItemClickListener(listener: (item: DataClass) -> Unit) {
    this.listener = listener
}

And inside the ViewHolder class set the listener, something like below:

class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    init {
        itemView.btn_save.setOnClickListener { listener?.invoke(data[adapterPosition]) }
    }

    // ...
}

Finally inside your activity or fragment you can easily access the items by adding a new listener:

adapter.setOnItemClickListener { it -> TODO() }

Notice that setting listeners inside ViewHolder constructor(init) is more efficient as it is not necessary to set a listener for every data binding.




回答2:


I suppose you should add an extension lister. Here's https://dzone.com/articles/click-listener-for-recyclerview-adapter. Also, you must add the custom lister for the save button.

override fun onBindViewHolder(holder: ArticleViewHolder, position: Int) {

  val article: Article = controller.articles[position]

  if(article.title.length > 100) {
    holder.itemView.titleTv.text = "${article.title.substring(0, 99)}..."
  } else {
    holder.itemView.titleTv.text = article.title
  }

  holder.itemView.authorTv.text = article.author


  *holder.btnSave.setOnClickListener(){_ ->
    **yourCustomListener**.OnClick(data/position) }*
}



回答3:


You have to handle it in onBindViewHolder() but logic which is responsible for creating and showing AlertDialog shouldn't be located in RecyclerView. You need to create an interface, which will be responsible for passing onClick() event information from your adapter to activity/fragment, and there you should show AlertDialog.

class ArticleAdapter(private val controller: IController) : RecyclerView.Adapter<ArticleViewHolder>() {

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ArticleViewHolder {
    val view = LayoutInflater.from(parent.context).inflate(R.layout.articlerecycler_item, parent, false)
    return ArticleViewHolder(view)
}

override fun getItemCount(): Int {
    return controller.articles.size
}

override fun onBindViewHolder(holder: ArticleViewHolder, position: Int) {
    val article: Article = controller.articles[position]

    if(article.title.length > 100) {
        holder.itemView.titleTv.text = "${article.title.substring(0, 99)}..."
    } else {
        holder.itemView.titleTv.text = article.title
    }

    btnSave.setOnClickListener {
        listener?.onSaveButtonClick()
    }

    holder.itemView.authorTv.text = article.author
}

private var listener: OnClickListener? = null

fun setListener(listener: OnClickListener) {
    this.listener = listener
}

}

interface OnClickListener {
    fun onSaveButtonClick()
}

class ArticleViewHolder(view: View?) : RecyclerView.ViewHolder(view)

Now pass the instance of OnClickListener from your activity to your adapter by setListener() method.



来源:https://stackoverflow.com/questions/53696176/kotlin-android-studio-handle-button-click-inside-recyclerview-adapter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!