Search code examples
androidkotlinandroid-recyclerviewlistener

How to handle both OnTouchListener event and OnClickListener event


I have RecyclerView and I set to each item OnTouchListener and OnClickListener

OnTouchListener:

override fun onBindViewHolder(holder: ItemListViewHolder, position: Int) {
    val item = getItem(position)
    holder.bind(item)
    holder.itemView.cardview.setOnTouchListener { v, event ->
        if (event.action == MotionEvent.ACTION_DOWN) {
            Log.d(TAG, "onBindViewHolder: $event.buttonState")
            this.startDragListener.onStartDrag(holder)
        }
        return@setOnTouchListener true
    }
}

OnClickListener:(inside the view holder)

 init {
    itemView.setOnClickListener(this)
}

 override fun onClick(v: View?) {
        onItemClickListener.onItemClick(adapterPosition)
    }

The problem is when I click on the item, only the startDragListener triggered, but the on click event never triggered.

I read some similar question on stackoverflow about this problem, but most of them are very old/deprecated method

How can I solve this problem and handle both touch listeners and click listeners?


Solution

  • See, onClickListener won't work with onTouchListener. You will have to implement some logic to differentiate between click and drag in onTouchListener. I did something like this, code is in java but you can get an idea.

    switch (motionEvent.getAction()) {
            case MotionEvent.ACTION_DOWN:
                x = motionEvent.getX();
                y = motionEvent.getY();
                return true;
    
            case MotionEvent.ACTION_UP:
                // PUT ON CLICK LOGIC HERE
                break;
            case MotionEvent.ACTION_MOVE:
                if ((motionEvent.getX() - x) > 80 || (x - motionEvent.getX()) > 80
                        || (motionEvent.getY() - y) > 50 || (y - motionEvent.getY()) > 60) {
                        view.startDrag(data, new View.DragShadowBuilder(view) {
                            @Override
                            public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
                                shadowSize.set(view.getWidth(), view.getHeight());
                                shadowTouchPoint.set((int) motionEvent.getX(), (int) motionEvent.getY());
                            }
                        }, view, 0);
                }
                return true;
    
        }