Skip to content

Instantly share code, notes, and snippets.

@marlonlom
Created December 3, 2018 02:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save marlonlom/21fdcf28911cd6774c6d6db0762f4743 to your computer and use it in GitHub Desktop.
Save marlonlom/21fdcf28911cd6774c6d6db0762f4743 to your computer and use it in GitHub Desktop.
A helper class for handling click events on a RecyclerView
/**
* Created by Rany Albeg Wein on 07/11/2015.
* Since we currently don't have a LongItemClick listener for the {@link RecyclerView}
* this is an implementation that uses a {@link GestureDetector} to notify us for long click events on one of
* {@link RecyclerView}'s child views. It also handles single-tap-up ( a click ) and a double-click on a child view.
*/
public class RecyclerViewItemTouchListener extends RecyclerView.SimpleOnItemTouchListener {
/**
* A listener that will be invoked on item click events.
*/
private OnItemClickEventListener mOnItemClickListener;
/**
* A gesture detector to detect and capture click events.
*/
private GestureDetector mGestureDetector;
/**
* The child on which a click event happened.
*/
private View mChildView;
/**
* The position of #mChildView in the adapter.
*/
private int mChildViewAdapterPosition;
public RecyclerViewItemTouchListener(Context context, OnItemClickEventListener listener) {
mGestureDetector = new GestureDetector(context, new GestureDelegator());
mOnItemClickListener = listener;
}
@Override
public boolean onInterceptTouchEvent(RecyclerView recyclerView, MotionEvent motionEvent) {
float x = motionEvent.getX();
float y = motionEvent.getY();
mChildView = recyclerView.findChildViewUnder(x, y);
if (mChildView != null) {
int pos = recyclerView.getChildAdapterPosition(mChildView);
mChildViewAdapterPosition = pos;
mGestureDetector.onTouchEvent(motionEvent);
}
return false;
}
/**
* A listener for {@link RecyclerView} click events.
*/
public interface OnItemClickEventListener {
/**
* Called when an item is long clicked.
* @param longClickedView The long clicked view.
* @param adapterPosition The position of the long clicked view in the adapter.
*/
void onItemLongClick(View longClickedView, int adapterPosition);
/**
* Called when an item is clicked.
* @param clickedView The clicked view.
* @param adapterPosition The position of the clicked view in the adapter.
*/
void onItemClick(View clickedView, int adapterPosition);
/**
* Called when an item is double clicked.
* @param doubleClickedView The clicked view.
* @param adapterPosition The position of the clicked view in the adapter.
*/
void onItemDoubleClick(View doubleClickedView, int adapterPosition);
}
/**
* An implementation of a {@link GestureDetector.SimpleOnGestureListener} that will handle
* {@link GestureDetector.SimpleOnGestureListener#onLongPress(MotionEvent)}
* {@link GestureDetector.SimpleOnGestureListener#onSingleTapConfirmed(MotionEvent)}, and
* {@link GestureDetector.SimpleOnGestureListener#onDoubleTap(MotionEvent)}
* methods and will invoke
* {@link OnItemClickEventListener#onItemLongClick(View, int)}
* {@link OnItemClickEventListener#onItemClick(View, int)}, and
* {@link OnItemClickEventListener#onItemDoubleClick(View, int)}
* accordingly.
*/
private class GestureDelegator extends SimpleOnGestureListener {
@Override
public void onLongPress(MotionEvent e) {
if (mOnItemClickListener != null) {
if (mChildView != null) {
mOnItemClickListener.onItemLongClick(mChildView, mChildViewAdapterPosition);
}
}
}
@Override
public boolean onDoubleTap(MotionEvent e) {
if (mOnItemClickListener != null) {
if (mChildView != null) {
mOnItemClickListener.onItemDoubleClick(mChildView, mChildViewAdapterPosition);
return true;
}
}
return false;
}
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
/**
* Unlike OnGestureListener.onSingleTapUp(MotionEvent), this will only be called after the detector
* is confident that the user's first tap is not followed by a second tap leading to a double-tap gesture.
*/
if (mOnItemClickListener != null) {
if (mChildView != null) {
mOnItemClickListener.onItemClick(mChildView, mChildViewAdapterPosition);
return true;
}
}
return false;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment