Created
June 23, 2016 17:39
-
-
Save Tagakov/5d2469732d036490242a3e264ea7468c to your computer and use it in GitHub Desktop.
This file contains 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 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