Search code examples
androidkotlinandroid-recyclerviewonclicklistenerandroid-viewholder

Android RecyclerView card menu button onClick not triggered with SelectionTracker


Context

I have a list of RecyclerView cards that are selectable by clicking on them. I'm using SelectionTracker and ItemDetailsLookup to keep track of which cards have been selected. Everything is working great.

Now I added an overflow context menu button at the top-right corner of the card. But when I click on the menu button, the card gets de/selected. What I want instead is for the button's onClickListener to trigger the menu popup.

Please help, what am I missing?

Fragment

class ProductsFragment : Fragment() {
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {

        val tracker = SelectionTracker.Builder( ... ).build()
        adapter.tracker = tracker
        tracker.addObserver(
            object : SelectionTracker.SelectionObserver<String>() {
                override fun onSelectionChanged() { ... }
            }
        )
    }
}

RecyclerView.Adapter

class ProductsAdapter : RecyclerView.Adapter<ProductsAdapter.ViewHolder>() {
    var tracker: SelectionTracker<String>? = null

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val product= products[position]
        holder.menuButton.setOnClickListener {
            showMenu(holder)
        }
    }

    inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        val menuButton: MaterialButton = view.findViewById(R.id.menu)
        fun getItemDetails(): ItemDetails<String> = object : ItemDetails<String>() {
                override fun getPosition(): Int = absolutePosition
                override fun getSelectionKey(): String = getItem(absolutePosition).product.id.toString()
            }
}

Solution

  • Add the following in the ViewHolder inner class:

    init {
        menuButton.setOnTouchListener { v, _ ->
            v.parent.requestDisallowInterceptTouchEvent(true)
            false
        }
    }
    

    Android studio will issue a warning: onTouch lambda should call View#performClick when a click is detected. You can suppress this by adding the following annotation right before the ViewHolder class definition:

    @SuppressLint("ClickableViewAccessibility")