Index: chrome/android/java/src/org/chromium/chrome/browser/widget/ToolbarProgressBarAnimatingView.java |
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/ToolbarProgressBarAnimatingView.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/ToolbarProgressBarAnimatingView.java |
index 71a01accf8fce0496cb91b3fcd316080619cebfb..ca48561a49a67a9c0f8fce78e2dad1ba7a475f4d 100644 |
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/ToolbarProgressBarAnimatingView.java |
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/ToolbarProgressBarAnimatingView.java |
@@ -5,6 +5,7 @@ |
package org.chromium.chrome.browser.widget; |
import android.animation.Animator; |
+import android.animation.Animator.AnimatorListener; |
import android.animation.AnimatorListenerAdapter; |
import android.animation.AnimatorSet; |
import android.animation.ValueAnimator; |
@@ -27,20 +28,35 @@ public class ToolbarProgressBarAnimatingView extends ImageView { |
/** The drawable inside this ImageView. */ |
private final ColorDrawable mAnimationDrawable; |
- /** The amount of time the fast part of the animation should take in ms. */ |
- private static final int FAST_ANIMATION_DURATION_MS = 900; |
+ /** The fraction of the total time that the slow animation should take. */ |
+ private static final float SLOW_ANIMATION_FRACTION = 0.60f; |
- /** The amount of time the slow part of the animation should take in ms. */ |
- private static final int SLOW_ANIMATION_DURATION_MS = 1600; |
+ /** The fraction of the total time that the fast animation delay should take. */ |
+ private static final float FAST_ANIMATION_DELAY = 0.02f; |
+ |
+ /** The fraction of the total time that the fast animation should take. */ |
+ private static final float FAST_ANIMATION_FRACTION = 0.38f; |
/** The time between animation sequences. */ |
private static final int ANIMATION_DELAY_MS = 1000; |
/** The width of the animating bar relative to the current width of the progress bar. */ |
- private static final float ANIMATING_BAR_SCALE = 0.5f; |
+ private static final float ANIMATING_BAR_SCALE = 0.3f; |
+ |
+ /** |
+ * The width of the animating bar relative to the current width of the progress bar for the |
+ * first half of the slow animation. |
+ */ |
+ private static final float SMALL_ANIMATING_BAR_SCALE = 0.1f; |
+ |
+ /** The fraction of overall completion that the small animating bar should be expanded at. */ |
+ private static final float SMALL_BAR_EXPANSION_COMPLETE = 0.6f; |
+ |
+ /** The maximum size of the animating view. */ |
+ private static final float ANIMATING_VIEW_MAX_WIDTH_DP = 400; |
/** Interpolator for enter and exit animation. */ |
- private final BakedBezierInterpolator mBezier = BakedBezierInterpolator.TRANSFORM_CURVE; |
+ private final BakedBezierInterpolator mBezier = BakedBezierInterpolator.FADE_OUT_CURVE; |
/** The current width of the progress bar. */ |
private float mProgressWidth = 0; |
@@ -48,6 +64,12 @@ public class ToolbarProgressBarAnimatingView extends ImageView { |
/** The set of individual animators that constitute the whole animation sequence. */ |
private final AnimatorSet mAnimatorSet; |
+ /** The animator controlling the fast animation. */ |
+ private final ValueAnimator mFastAnimation; |
+ |
+ /** The animator controlling the slow animation. */ |
+ private final ValueAnimator mSlowAnimation; |
+ |
/** Track if the animation has been canceled. */ |
private boolean mIsCanceled; |
@@ -60,11 +82,11 @@ public class ToolbarProgressBarAnimatingView extends ImageView { |
/** The last fraction of the animation that was drawn. */ |
private float mLastAnimatedFraction; |
- /** |
- * If the animation is currently running. This is needed because Animator.isStarted() is not |
- * reliable on JellyBean. |
- */ |
- private boolean mIsAnimationRunning; |
+ /** The last animation that received an update. */ |
+ private ValueAnimator mLastUpdatedAnimation; |
+ |
+ /** The ratio of px to dp. */ |
+ private float mDpToPx; |
/** |
* An animation update listener that moves an ImageView across the progress bar. |
@@ -72,8 +94,9 @@ public class ToolbarProgressBarAnimatingView extends ImageView { |
private class ProgressBarUpdateListener implements AnimatorUpdateListener { |
@Override |
public void onAnimationUpdate(ValueAnimator animation) { |
+ mLastUpdatedAnimation = animation; |
mLastAnimatedFraction = animation.getAnimatedFraction(); |
- updateAnimation(mLastAnimatedFraction); |
+ updateAnimation(mLastUpdatedAnimation, mLastAnimatedFraction); |
} |
} |
@@ -85,6 +108,7 @@ public class ToolbarProgressBarAnimatingView extends ImageView { |
super(context); |
setLayoutParams(layoutParams); |
mIsRtl = LocalizationUtils.isLayoutRtl(); |
+ mDpToPx = getResources().getDisplayMetrics().density; |
mAnimationDrawable = new ColorDrawable(Color.WHITE); |
@@ -93,28 +117,44 @@ public class ToolbarProgressBarAnimatingView extends ImageView { |
mListener = new ProgressBarUpdateListener(); |
mAnimatorSet = new AnimatorSet(); |
- ValueAnimator fastAnimation = new ValueAnimator(); |
- fastAnimation.setFloatValues(0.0f, 1.0f); |
- fastAnimation.setDuration(FAST_ANIMATION_DURATION_MS); |
- fastAnimation.addUpdateListener(mListener); |
+ mSlowAnimation = new ValueAnimator(); |
+ mSlowAnimation.setFloatValues(0.0f, 1.0f); |
+ mSlowAnimation.addUpdateListener(mListener); |
+ |
+ mFastAnimation = new ValueAnimator(); |
+ mFastAnimation.setFloatValues(0.0f, 1.0f); |
+ mFastAnimation.addUpdateListener(mListener); |
- ValueAnimator slowAnimation = new ValueAnimator(); |
- slowAnimation.setFloatValues(0.0f, 1.0f); |
- slowAnimation.setDuration(SLOW_ANIMATION_DURATION_MS); |
- slowAnimation.addUpdateListener(mListener); |
+ updateAnimationDuration(); |
- mAnimatorSet.playSequentially(fastAnimation, slowAnimation); |
+ mAnimatorSet.playSequentially(mSlowAnimation, mFastAnimation); |
- slowAnimation.addListener(new AnimatorListenerAdapter() { |
+ AnimatorListener listener = new AnimatorListenerAdapter() { |
@Override |
public void onAnimationEnd(Animator a) { |
// Replay the animation if it has not been canceled. |
if (mIsCanceled) return; |
// Repeats of the animation should have a start delay. |
mAnimatorSet.setStartDelay(ANIMATION_DELAY_MS); |
- mAnimatorSet.start(); |
+ updateAnimationDuration(); |
+ // Only restart the animation if the last animation is ending. |
+ if (a == mFastAnimation) mAnimatorSet.start(); |
} |
- }); |
+ }; |
+ |
+ mSlowAnimation.addListener(listener); |
+ mFastAnimation.addListener(listener); |
+ } |
+ |
+ /** |
+ * Update the duration of the animation based on the width of the progress bar. |
+ */ |
+ private void updateAnimationDuration() { |
+ // Total duration: logE(progress_dp) * 200 * 1.3 |
+ long totalDuration = (long) (Math.log(mProgressWidth / mDpToPx) / Math.log(Math.E)) * 260; |
+ mSlowAnimation.setDuration((long) (totalDuration * SLOW_ANIMATION_FRACTION)); |
+ mFastAnimation.setStartDelay((long) (totalDuration * FAST_ANIMATION_DELAY)); |
+ mFastAnimation.setDuration((long) (totalDuration * FAST_ANIMATION_FRACTION)); |
} |
/** |
@@ -122,8 +162,8 @@ public class ToolbarProgressBarAnimatingView extends ImageView { |
*/ |
public void startAnimation() { |
mIsCanceled = false; |
- if (!mIsAnimationRunning) { |
- mIsAnimationRunning = true; |
+ if (!mAnimatorSet.isStarted()) { |
+ updateAnimationDuration(); |
// Set the initial start delay to 0ms so it starts immediately. |
mAnimatorSet.setStartDelay(0); |
@@ -141,18 +181,36 @@ public class ToolbarProgressBarAnimatingView extends ImageView { |
/** |
* Update the animating view. |
+ * @param animator The current running animator. |
* @param animatedFraction The current fraction of completion for the animation. |
*/ |
- private void updateAnimation(float animatedFraction) { |
+ private void updateAnimation(ValueAnimator animator, float animatedFraction) { |
+ if (mIsCanceled) return; |
float bezierProgress = mBezier.getInterpolation(animatedFraction); |
// Left and right bound change based on if the layout is RTL. |
float leftBound = mIsRtl ? -mProgressWidth : 0.0f; |
float rightBound = mIsRtl ? 0.0f : mProgressWidth; |
+ float barScale = ANIMATING_BAR_SCALE; |
+ |
+ // If the current animation is the slow animation, the bar slowly expands from 20% of the |
+ // progress bar width to 30%. |
+ if (animator == mSlowAnimation && animatedFraction <= SMALL_BAR_EXPANSION_COMPLETE) { |
+ float sizeDiff = ANIMATING_BAR_SCALE - SMALL_ANIMATING_BAR_SCALE; |
+ |
+ // Since the bar will only expand for the first 60% of the animation, multiply the |
+ // animated fraction by 1/0.6 to get the fraction completed. |
+ float completeFraction = (animatedFraction / SMALL_BAR_EXPANSION_COMPLETE); |
+ |
+ barScale = SMALL_ANIMATING_BAR_SCALE + sizeDiff * completeFraction; |
+ } |
+ |
// Include the width of the animating bar in this computation so it comes from |
// off-screen. |
- float animatingWidth = mProgressWidth * ANIMATING_BAR_SCALE; |
+ float animatingWidth = Math.min(ANIMATING_VIEW_MAX_WIDTH_DP * mDpToPx, |
+ mProgressWidth * barScale); |
+ |
float animatorCenter = |
((mProgressWidth + animatingWidth) * bezierProgress) - animatingWidth / 2.0f; |
if (mIsRtl) animatorCenter *= -1.0f; |
@@ -186,7 +244,6 @@ public class ToolbarProgressBarAnimatingView extends ImageView { |
*/ |
public void cancelAnimation() { |
mIsCanceled = true; |
- mIsAnimationRunning = false; |
// Reset position and alpha. |
setScaleX(0.0f); |
setTranslationX(0.0f); |
@@ -200,8 +257,11 @@ public class ToolbarProgressBarAnimatingView extends ImageView { |
* @param progressWidth The width of the contaiing progress bar. |
*/ |
public void update(float progressWidth) { |
+ // Since the progress bar can become visible before current progress is sent, the width |
+ // needs to be updated even if the progess bar isn't showing. The result of not having |
+ // this is most noticable if you rotate the device on a slow page. |
mProgressWidth = progressWidth; |
- updateAnimation(mLastAnimatedFraction); |
+ updateAnimation(mLastUpdatedAnimation, mLastAnimatedFraction); |
} |
/** |