I am trying to implement a use-case where I need to scroll RecyclerView normally (Android LayoutManager scroll) when the user scrolls with a low velocity and scroll by a certain extra amount when the user scrolls above a certain velocity.
I have implemented a LinearLayoutManager as follows:
public class ScrollLayoutManager extends LinearLayoutManager {
// constructors
@Override
public void onAttachedToWindow(RecyclerView recyclerView) {
Log.d(TAG, "onAttachedToWindow");
super.onAttachedToWindow(recyclerView);
mRecyclerView = recyclerView;
mRecyclerView.addOnItemTouchListener(new ThresholdDetector());
}
private final class ThresholdDetector implements RecyclerView.OnItemTouchListener {
@Override
public boolean onInterceptTouchEvent(RecyclerView recyclerView, MotionEvent e) {
// some calculations
return true;
}
@Override
public void onTouchEvent(final RecyclerView view, final MotionEvent e) {
final int action = e.getActionMasked();
mVelocityTracker.addMovement(e);
if(action == MotionEvent.ACTION_MOVE) {
if (thresholdMet) {
// Custom scroll
mRecyclerView.scrollBy(calculatedAmount)
} else {
// Scroll normally as per Android LinearLayoutManager
}
}
}
}
}
If threshold is not met, I need Android to handle the scroll, otherwise I am not able to smooth scroll. I tried the following in else (when threshold is not met), but it does not quite work.
mRecyclerView.post(new Runnable() {
@Override
public void run() {
mRecyclerView.smoothScrollBy(-(int)getDeltaX(motionEvent), 0);
}
});
Without seeing the entirety of the ThresholdDetector
class, it will be impossible to know for sure what the best solution is. That said, I believe the problem is that you are always returning true
from onInterceptTouchEvent()
.
In the documentation for the return value of onInterceptTouchEvent()
:
Returns:
true
if thisOnItemTouchListener
wishes to begin intercepting touch events,false
to continue with the current behavior and continue observing future events in the gesture.
And in the description for onTouchEvent()
:
Process a touch event as part of a gesture that was claimed by returning
true
from a previous call toonInterceptTouchEvent()
.
In other words, onTouchEvent()
will only be invoked whenever you return true
for a given event from onInterceptTouchEvent()
. If you want the RecyclerView to perform its default behavior, simply return false
from onInterceptTouchEvent()
when the scroll velocity is below your threshold.