How to get clicks on RecyclerView (NOT the children)

前端 未结 4 1156
我在风中等你
我在风中等你 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:50

    Here is a trick, It's open for comments.

    You can have 2 children items in a FrameLayout. The first being the RecyclerView and the second a View

        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/recycler"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"/>
            <View
                android:id="@+id/over_view"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                />
        </FrameLayout>
    

    Since its a FrameLayout the View would be on top of the RecyclerView and you can set an onClickListener to the View and it would behave as if it was the RecyclerView that was clicked

    over_view.setOnClickListener {
        .....
    }
    
    0 讨论(0)
  • 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.

    0 讨论(0)
  • 2021-01-17 17:55

    This is how I have done in Kotlin style

    fun RecyclerView.enableClickListener(){
        val gesture = object : GestureDetector.SimpleOnGestureListener(){
            override fun onSingleTapConfirmed(e: MotionEvent?): Boolean {
                this@enableClickListener.performClick()
                return super.onSingleTapConfirmed(e)
            }
        }
        val detector = GestureDetector(this.context, gesture)
        this.setOnTouchListener { v, event -> detector.onTouchEvent(event) }
    }
    

    And this is how to use it

    yourRecyclerView.apply {
            enableClickListener()
            setOnClickListener {
               // Do what you want  ...
            }
        }
    

    Enjoy :)

    0 讨论(0)
  • 2021-01-17 18:00

    a click event on RecycleView ? try like this:

    //set android:descendantFocusability="blocksDescendants" on parent layout 
    //then setOnClickListener
    
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    **android:descendantFocusability="blocksDescendants"**
    android:layout_height="match_parent">
    
    <android.support.v7.widget.RecyclerView
      android:layout_width="match_parent"
      android:layout_height="match_parent">
    </android.support.v7.widget.RecyclerView>
    
    </LinearLayout>
    
    0 讨论(0)
提交回复
热议问题