How to create onclick event in adapter using inter

2020-03-05 03:28发布

问题:

How can I create on click event using interface?

In my application I've created view click interface to detect clicking on adapter items into parent activity. After creating interface and method into adapter how I can use this interface to call the view listener ?

回答1:

Please check this code, It's working fine for me.

First Create Adapter class.

class ChapterAdapter(private val activity: Activity, val mWords: ArrayList<Chapter>, val btnlistener: BtnClickListener) : RecyclerView.Adapter<ChapterAdapter.ViewHolder>() {

        companion object {
            var mClickListener: BtnClickListener? = null
        }

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

        override fun onBindViewHolder(holder: ViewHolder?, position: Int) {
            mClickListener = btnlistener
            val item = mWords[position]

            holder.layout_chapter_name.setOnClickListener(object : View.OnClickListener {
                override fun onClick(v: View?) {
                    if (mClickListener != null)
                        mClickListener?.onBtnClick(position)
                }
            })
        }

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

        override fun getItemId(position: Int): Long {
            return super.getItemId(position)
        }

        override fun getItemViewType(position: Int): Int {
            return super.getItemViewType(position)
        }

        class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
            val txt_capter_name = view.txt_capter_name
        }

        open interface BtnClickListener {
            fun onBtnClick(position: Int)
        }
    }

After create and declare adapter in your Activity or Fragment.

listAdapter = ChapterAdapter(activity, _arrChapterList, object : ChapterAdapter.BtnClickListener {
                override fun onBtnClick(position: Int, chapter_id: String, chapter_size: String, chapter_name: String) {
                    toast(chapter_id + " = " + chapter_size, Toast.LENGTH_LONG)
                }
            })


回答2:

In Kotlin the proper way doing this, is using callbacks instead of Java Interfaces. Example:

class MyAdapter(private val callback: (YourModel) -> Unit) {

    override fun onBindViewHolder(holder: DataBoundViewHolder<YourModel>, position: Int) {
        bind(holder.binding, items!![position])
        holder.binding.executePendingBindings()
        holder.binding.root.setOnClickListener { callback(binding.model) }
   }
}

And create the adapter somewhere using

MyAdapter myAdapter = MyAdapter( { println{"Clicked $it"} })

Edit: Since the Asker would like to see a full working code i used the code from Sumit and replaced the Interfaces with Kotlin-Callbacks.

class ChapterAdapter(private val activity: Activity, 
     val mWords: ArrayList<Chapter>,
     val callback: (Any) -> Unit) : 
     RecyclerView.Adapter<ChapterAdapter.ViewHolder>() {


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

        override fun onBindViewHolder(holder: ViewHolder?, position: Int) {
            val item = mWords[position]

            holder.layout_chapter_name.setOnClickListener( callback {$it})
        }

        override fun getItemCount(): Int = mWords.size

        override fun getItemId(position: Int): Long = super.getItemId(position)

        override fun getItemViewType(position: Int): Int = super.getItemViewType(position)


        class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
            val txt_capter_name = view.txt_capter_name
        }

and finally creating the Adapter

listAdapter = ChapterAdapter(activity, _arrChapterList, { 
  toast( "Clicked $it", Toast.LENGTH_LONG) 
})


回答3:

I have the same problem, and here is my solution:

package adapter

class MarketplaceListAdapter : RecyclerView.Adapter<MarketplaceListAdapter.ViewHolder> {

    private val marketplaceList: ArrayList<Marketplace>

    constructor(marketplaceList: ArrayList<Marketplace>) : super() {
        this.marketplaceList = marketplaceList
    }

    private var listener: OnItemClickListener? = null

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        // implementation
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        // implementation
    }

    override fun getItemId(position: Int): Long {
        return 0
    }

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

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

    interface OnItemClickListener {
        fun onItemClick(marketplace: Marketplace)
    }

    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView),
        View.OnClickListener {

        var tvTitle: TextView = itemView.findViewById(R.id.tvTitle)
        var ivIcon: ImageView = itemView.findViewById(R.id.ivIcon)

        init {
            itemView.setOnClickListener(this)
        }

        override fun onClick(v: View) {
            listener?.onItemClick(marketplaceList[adapterPosition])
        }

    }

}

And on my fragment:

val list = view.findViewById<RecyclerView>(R.id.list)

list?.let {
    adapter?.let { adapter ->
        list.adapter = adapter

        adapter.setListener(object : MarketplaceListAdapter.OnItemClickListener {
            override fun onItemClick(marketplace: Marketplace) {
                onMarketplaceSelected(marketplace)
            }
        })
    }
}

Hope that it help!