Last active
March 3, 2022 17:18
-
-
Save okmanideep/ecccd38787fa8e287a3f18bcd9867189 to your computer and use it in GitHub Desktop.
A RecyclerView that intercepts the scroll only if the user is scrolling in that direction
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class BetterRecyclerView extends RecyclerView{ | |
private static final int INVALID_POINTER = -1; | |
private int mScrollPointerId = INVALID_POINTER; | |
private int mInitialTouchX, mInitialTouchY; | |
private int mTouchSlop; | |
public BetterRecyclerView(Context context) { | |
this(context, null); | |
} | |
public BetterRecyclerView(Context context, @Nullable AttributeSet attrs) { | |
this(context, attrs, 0); | |
} | |
public BetterRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) { | |
super(context, attrs, defStyle); | |
final ViewConfiguration vc = ViewConfiguration.get(getContext()); | |
mTouchSlop = vc.getScaledTouchSlop(); | |
} | |
@Override | |
public void setScrollingTouchSlop(int slopConstant) { | |
super.setScrollingTouchSlop(slopConstant); | |
final ViewConfiguration vc = ViewConfiguration.get(getContext()); | |
switch (slopConstant) { | |
case TOUCH_SLOP_DEFAULT: | |
mTouchSlop = vc.getScaledTouchSlop(); | |
break; | |
case TOUCH_SLOP_PAGING: | |
mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(vc); | |
break; | |
default: | |
break; | |
} | |
} | |
@Override | |
public boolean onInterceptTouchEvent(MotionEvent e) { | |
final int action = MotionEventCompat.getActionMasked(e); | |
final int actionIndex = MotionEventCompat.getActionIndex(e); | |
switch (action) { | |
case MotionEvent.ACTION_DOWN: | |
mScrollPointerId = MotionEventCompat.getPointerId(e, 0); | |
mInitialTouchX = (int) (e.getX() + 0.5f); | |
mInitialTouchY = (int) (e.getY() + 0.5f); | |
return super.onInterceptTouchEvent(e); | |
case MotionEventCompat.ACTION_POINTER_DOWN: | |
mScrollPointerId = MotionEventCompat.getPointerId(e, actionIndex); | |
mInitialTouchX = (int) (MotionEventCompat.getX(e, actionIndex) + 0.5f); | |
mInitialTouchY = (int) (MotionEventCompat.getY(e, actionIndex) + 0.5f); | |
return super.onInterceptTouchEvent(e); | |
case MotionEvent.ACTION_MOVE: { | |
final int index = MotionEventCompat.findPointerIndex(e, mScrollPointerId); | |
if (index < 0) { | |
return false; | |
} | |
final int x = (int) (MotionEventCompat.getX(e, index) + 0.5f); | |
final int y = (int) (MotionEventCompat.getY(e, index) + 0.5f); | |
if (getScrollState() != SCROLL_STATE_DRAGGING) { | |
final int dx = x - mInitialTouchX; | |
final int dy = y - mInitialTouchY; | |
final boolean canScrollHorizontally = getLayoutManager().canScrollHorizontally(); | |
final boolean canScrollVertically = getLayoutManager().canScrollVertically(); | |
boolean startScroll = false; | |
if (canScrollHorizontally && Math.abs(dx) > mTouchSlop && (Math.abs(dx) >= Math.abs(dy) || canScrollVertically)) { | |
startScroll = true; | |
} | |
if (canScrollVertically && Math.abs(dy) > mTouchSlop && (Math.abs(dy) >= Math.abs(dx) || canScrollHorizontally)) { | |
startScroll = true; | |
} | |
return startScroll && super.onInterceptTouchEvent(e); | |
} | |
return super.onInterceptTouchEvent(e); | |
} | |
default: | |
return super.onInterceptTouchEvent(e); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment