How to get clicks on RecyclerView (NOT the children)

前端 未结 4 1187
我在风中等你
我在风中等你 2021-01-17 17:23

Is there any way to set an onClickListener on a RecyclerView?

I have a RecyclerView with some children in it, and setting an <

4条回答
  •  独厮守ぢ
    2021-01-17 17:52

    Is there any way to set an onClickListener on a RecyclerView?

    No. That is, you can set an OnClickListener, but RecyclerView will never call it. RecyclerView intercepts all touch events, but never calls performClick(), which is how View invokes its listener.

    You can, however, simulate an OnClickListener with an OnTouchListener and a GestureDetector. For the GestureDetector's listener, we can use a SimpleOnGestureListener, implementing just the onSingleTapUp() method.

    class ClickListener extends GestureDetector.SimpleOnGestureListener {
        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            Toast.makeText(HelloActivity.this, "Clicked", 0).show();
            return true;
        }
    };
    

    Then we just need to feed the GestureDetector the MotionEvents from an OnTouchListener, and check the return to decide whether to consume the event, so as to not interfere with scrolling, dragging, etc.

    final GestureDetector detector = new GestureDetector(HelloActivity.this, new ClickListener());
    
    mRecyclerView.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if(detector.onTouchEvent(event)) {
                    return true;
                }
                return false;
            }
        }
    );
    

    Please note that the above solution works with pretty much only a "simple" RecyclerView, like the one described and given in the question. If you're using more involved item handling, like drag and drop or swipe, we'll need to handle our gesture detection a little further up the touch event chain.

    To do this, we can subclass RecyclerView and perform the detection in the dispatchTouchEvent() method. If a single tap is detected, we simply call performClick(), which will fire the RecyclerView's OnClickListener.

    public class ClickableRecyclerView extends RecyclerView {
    
        private final GestureDetectorCompat detector;
    
        public ClickableRecyclerView(Context context) {
            this(context, null);
        }
    
        public ClickableRecyclerView(Context context, AttributeSet attrs) {
            super(context, attrs);
            detector = new GestureDetectorCompat(context, new ClickListener());
        }
    
        private class ClickListener extends GestureDetector.SimpleOnGestureListener {
            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                performClick();
                return true;
            }
        };
    
        @Override
        public boolean dispatchTouchEvent(MotionEvent e) {
            detector.onTouchEvent(e);
            return super.dispatchTouchEvent(e);
        }
    }
    

    Just use this subclass in place of your regular RecyclerView, and set an OnClickListener on it as you normally would. Additional constructors may be necessary, depending on how you're instantiating this.

提交回复
热议问题