Is there any way to set an onClickListener
on a RecyclerView
?
I have a RecyclerView
with some children in it, and setting an <
Is there any way to set an
onClickListener
on aRecyclerView
?
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 MotionEvent
s 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.