Skip to content

Instantly share code, notes, and snippets.

@Tagakov
Created June 23, 2016 17:39
Show Gist options
  • Save Tagakov/5d2469732d036490242a3e264ea7468c to your computer and use it in GitHub Desktop.
Save Tagakov/5d2469732d036490242a3e264ea7468c to your computer and use it in GitHub Desktop.
public class PagerLayoutManager extends LinearLayoutManager {
private static final int SETTLE_DURATION = 600;
private static final float DEFAULT_FLING_THRESHOLD_DP = 10f;
private final int flingThreshold;
private int scrollState;
public PagerLayoutManager(Context context) {
super(context, HORIZONTAL, false);
flingThreshold = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DEFAULT_FLING_THRESHOLD_DP, context.getResources().getDisplayMetrics());
}
@Override
public void onAttachedToWindow(RecyclerView view) {
super.onAttachedToWindow(view);
view.setScrollingTouchSlop(RecyclerView.TOUCH_SLOP_PAGING);
}
@Override
public void onDetachedFromWindow(RecyclerView view, RecyclerView.Recycler recycler) {
super.onDetachedFromWindow(view, recycler);
view.setScrollingTouchSlop(RecyclerView.TOUCH_SLOP_DEFAULT);
}
@Override
public int scrollHorizontallyBy(int dx, RecyclerView.Recycler recycler, RecyclerView.State state) {
if (scrollState == RecyclerView.SCROLL_STATE_SETTLING && !isSmoothScrolling()) {
if (dx > 0) { //forward
if (dx > flingThreshold) {
startSmoothScroll(new PagerScroller(findFirstVisibleItemPosition() + 1));
}
} else if (dx < 0) { //backward
if (dx < -flingThreshold) {
startSmoothScroll(new PagerScroller(findFirstVisibleItemPosition()));
}
} else { //possible impossible case :)
scrollToMostVisibleView(findFirstVisibleItemPosition());
}
}
return super.scrollHorizontallyBy(dx, recycler, state);
}
private void scrollToMostVisibleView(int firstVisibleItemPosition) {
View firstVisibleView = findViewByPosition(firstVisibleItemPosition);
int offscreen = Math.abs(firstVisibleView.getLeft());
int onscreen = Math.abs(firstVisibleView.getRight());
int posToScroll = offscreen <= onscreen ? firstVisibleItemPosition : firstVisibleItemPosition + 1;
startSmoothScroll(new PagerScroller(posToScroll));
}
@Override
public void onScrollStateChanged(int state) {
this.scrollState = state;
if (isSmoothScrolling()) return;
if (state == RecyclerView.SCROLL_STATE_IDLE) {
int firstVisibleItemPosition = findFirstVisibleItemPosition();
View firstVisibleView = findViewByPosition(firstVisibleItemPosition);
if (firstVisibleView.getLeft() != 0) {
scrollToMostVisibleView(firstVisibleItemPosition);
}
}
}
private final static class PagerScroller extends RecyclerView.SmoothScroller {
private final Interpolator interpolator = new Interpolator() {
@Override
public float getInterpolation(float t) {
t -= 1.0f;
return t * t * t * t * t + 1.0f;
}
};
public PagerScroller(int targetPosition) {
setTargetPosition(targetPosition);
}
@Override
protected void onTargetFound(View targetView, RecyclerView.State state, Action action) {
if (targetView.getLeft() != 0) {
action.update(
targetView.getLeft(),
0,
SETTLE_DURATION,
interpolator
);
}
}
@Override protected void onStart() {}
@Override protected void onStop() {}
@Override protected void onSeekTargetStep(int dx, int dy, RecyclerView.State state, Action action) {}
}
@Override
public RecyclerView.LayoutParams generateDefaultLayoutParams() {
return patchLayoutParams(super.generateDefaultLayoutParams());
}
@Override
public RecyclerView.LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) {
return patchLayoutParams(super.generateLayoutParams(lp));
}
@Override
public RecyclerView.LayoutParams generateLayoutParams(Context c, AttributeSet attrs) {
return patchLayoutParams(super.generateLayoutParams(c, attrs));
}
@Override
public boolean checkLayoutParams(RecyclerView.LayoutParams lp) {
return super.checkLayoutParams(lp) && lp.width == getWidth();
}
private RecyclerView.LayoutParams patchLayoutParams(RecyclerView.LayoutParams layoutParams) {
layoutParams.width = getWidth();
return layoutParams;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment