Handle consecutive ViewPager.setCurrentItem calls.
Bug: 25113163
Change-Id: Id4711485a28c20868874e223547c220646406a3d
diff --git a/v4/java/android/support/v4/view/ViewPager.java b/v4/java/android/support/v4/view/ViewPager.java
index dc3cee4..454ac62 100644
--- a/v4/java/android/support/v4/view/ViewPager.java
+++ b/v4/java/android/support/v4/view/ViewPager.java
@@ -144,7 +144,10 @@
private int mRestoredCurItem = -1;
private Parcelable mRestoredAdapterState = null;
private ClassLoader mRestoredClassLoader = null;
+
private Scroller mScroller;
+ private boolean mIsScrollStarted;
+
private PagerObserver mObserver;
private int mPageMargin;
@@ -388,6 +391,10 @@
@Override
protected void onDetachedFromWindow() {
removeCallbacks(mEndScrollRunnable);
+ // To be on the safe side, abort the scroller
+ if ((mScroller != null) && !mScroller.isFinished()) {
+ mScroller.abortAnimation();
+ }
super.onDetachedFromWindow();
}
@@ -829,7 +836,21 @@
setScrollingCacheEnabled(false);
return;
}
- int sx = getScrollX();
+
+ int sx;
+ boolean wasScrolling = (mScroller != null) && !mScroller.isFinished();
+ if (wasScrolling) {
+ // We're in the middle of a previously initiated scrolling. Check to see
+ // whether that scrolling has actually started (if we always call getStartX
+ // we can get a stale value from the scroller if it hadn't yet had its first
+ // computeScrollOffset call) to decide what is the current scrolling position.
+ sx = mIsScrollStarted ? mScroller.getCurrX() : mScroller.getStartX();
+ // And abort the current scrolling.
+ mScroller.abortAnimation();
+ setScrollingCacheEnabled(false);
+ } else {
+ sx = getScrollX();
+ }
int sy = getScrollY();
int dx = x - sx;
int dy = y - sy;
@@ -849,7 +870,7 @@
final float distance = halfWidth + halfWidth *
distanceInfluenceForSnapDuration(distanceRatio);
- int duration = 0;
+ int duration;
velocity = Math.abs(velocity);
if (velocity > 0) {
duration = 4 * Math.round(1000 * Math.abs(distance / velocity));
@@ -860,6 +881,9 @@
}
duration = Math.min(duration, MAX_SETTLE_DURATION);
+ // Reset the "scroll started" flag. It will be flipped to true in all places
+ // where we call computeScrollOffset().
+ mIsScrollStarted = false;
mScroller.startScroll(sx, sy, dx, dy, duration);
ViewCompat.postInvalidateOnAnimation(this);
}
@@ -1642,6 +1666,7 @@
@Override
public void computeScroll() {
+ mIsScrollStarted = true;
if (!mScroller.isFinished() && mScroller.computeScrollOffset()) {
int oldX = getScrollX();
int oldY = getScrollY();
@@ -1822,15 +1847,18 @@
if (needPopulate) {
// Done with scroll, no longer want to cache view drawing.
setScrollingCacheEnabled(false);
- mScroller.abortAnimation();
- int oldX = getScrollX();
- int oldY = getScrollY();
- int x = mScroller.getCurrX();
- int y = mScroller.getCurrY();
- if (oldX != x || oldY != y) {
- scrollTo(x, y);
- if (x != oldX) {
- pageScrolled(x);
+ boolean wasScrolling = !mScroller.isFinished();
+ if (wasScrolling) {
+ mScroller.abortAnimation();
+ int oldX = getScrollX();
+ int oldY = getScrollY();
+ int x = mScroller.getCurrX();
+ int y = mScroller.getCurrY();
+ if (oldX != x || oldY != y) {
+ scrollTo(x, y);
+ if (x != oldX) {
+ pageScrolled(x);
+ }
}
}
}
@@ -1964,6 +1992,7 @@
mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
mIsUnableToDrag = false;
+ mIsScrollStarted = true;
mScroller.computeScrollOffset();
if (mScrollState == SCROLL_STATE_SETTLING &&
Math.abs(mScroller.getFinalX() - mScroller.getCurrX()) > mCloseEnough) {