Fix tab indicator getting out of sync

Caused when the indicator is animating to a
position, but a re-layout happens during the
animation moving the target position.

BUG: 23004032
Change-Id: If9ab0f7e6ea088b28ceca7666a8fde40d5e715e2
diff --git a/design/base/android/support/design/widget/ValueAnimatorCompat.java b/design/base/android/support/design/widget/ValueAnimatorCompat.java
index 1e33f66..20bebb6 100644
--- a/design/base/android/support/design/widget/ValueAnimatorCompat.java
+++ b/design/base/android/support/design/widget/ValueAnimatorCompat.java
@@ -104,6 +104,7 @@
         abstract void cancel();
         abstract float getAnimatedFraction();
         abstract void end();
+        abstract long getDuration();
     }
 
     private final Impl mImpl;
@@ -191,4 +192,8 @@
     public void end() {
         mImpl.end();
     }
+
+    public long getDuration() {
+        return mImpl.getDuration();
+    }
 }
diff --git a/design/eclair-mr1/android/support/design/widget/ValueAnimatorCompatImplEclairMr1.java b/design/eclair-mr1/android/support/design/widget/ValueAnimatorCompatImplEclairMr1.java
index 42cf086..1c708f5 100644
--- a/design/eclair-mr1/android/support/design/widget/ValueAnimatorCompatImplEclairMr1.java
+++ b/design/eclair-mr1/android/support/design/widget/ValueAnimatorCompatImplEclairMr1.java
@@ -147,6 +147,11 @@
         }
     }
 
+    @Override
+    public long getDuration() {
+        return mDuration;
+    }
+
     private void update() {
         if (mIsRunning) {
             // Update the animated fraction
diff --git a/design/honeycomb-mr1/android/support/design/widget/ValueAnimatorCompatImplHoneycombMr1.java b/design/honeycomb-mr1/android/support/design/widget/ValueAnimatorCompatImplHoneycombMr1.java
index 4f9ea39..5ee272b 100644
--- a/design/honeycomb-mr1/android/support/design/widget/ValueAnimatorCompatImplHoneycombMr1.java
+++ b/design/honeycomb-mr1/android/support/design/widget/ValueAnimatorCompatImplHoneycombMr1.java
@@ -113,4 +113,9 @@
     public void end() {
         mValueAnimator.end();
     }
+
+    @Override
+    public long getDuration() {
+        return mValueAnimator.getDuration();
+    }
 }
diff --git a/design/src/android/support/design/widget/TabLayout.java b/design/src/android/support/design/widget/TabLayout.java
index abbf3bf..069b439 100755
--- a/design/src/android/support/design/widget/TabLayout.java
+++ b/design/src/android/support/design/widget/TabLayout.java
@@ -1327,6 +1327,8 @@
         private int mIndicatorLeft = -1;
         private int mIndicatorRight = -1;
 
+        private ValueAnimatorCompat mCurrentAnimator;
+
         SlidingTabStrip(Context context) {
             super(context);
             setWillNotDraw(false);
@@ -1420,8 +1422,18 @@
         @Override
         protected void onLayout(boolean changed, int l, int t, int r, int b) {
             super.onLayout(changed, l, t, r, b);
-            // If we've been layed out, update the indicator position
-            updateIndicatorPosition();
+
+            if (mCurrentAnimator != null && mCurrentAnimator.isRunning()) {
+                // If we're currently running an animation, lets cancel it and start a
+                // new animation with the remaining duration
+                mCurrentAnimator.cancel();
+                final long duration = mCurrentAnimator.getDuration();
+                animateIndicatorToPosition(mSelectedPosition,
+                        Math.round((1f - mCurrentAnimator.getAnimatedFraction()) * duration));
+            } else {
+                // If we've been layed out, update the indicator position
+                updateIndicatorPosition();
+            }
         }
 
         private void updateIndicatorPosition() {
@@ -1518,6 +1530,7 @@
                     }
                 });
                 animator.start();
+                mCurrentAnimator = animator;
             }
         }