Chromium Code Reviews| Index: chrome/android/java/src/org/chromium/chrome/browser/widget/ToolbarProgressBar.java |
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/ToolbarProgressBar.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/ToolbarProgressBar.java |
| index 26ff6fb7818d294679d0970135cc1cb708fa104c..c0dd06524abceb796a896960bc8ea00f2f4bcd66 100644 |
| --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/ToolbarProgressBar.java |
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/ToolbarProgressBar.java |
| @@ -4,21 +4,50 @@ |
| package org.chromium.chrome.browser.widget; |
| +import android.animation.TimeAnimator; |
| +import android.animation.TimeAnimator.TimeListener; |
| import android.content.Context; |
| +import android.text.TextUtils; |
| import android.util.AttributeSet; |
| +import org.chromium.base.CommandLine; |
| import org.chromium.base.VisibleForTesting; |
| +import org.chromium.chrome.browser.ChromeSwitches; |
| import org.chromium.ui.interpolators.BakedBezierInterpolator; |
| /** |
| * Progress bar for use in the Toolbar view. |
| */ |
| public class ToolbarProgressBar extends ClipDrawableProgressBar { |
| - private long mAlphaAnimationDurationMs = 130; |
| + |
| + /** |
| + * Interface for progress bar animation interpolation logics. |
| + */ |
| + interface AnimationLogic { |
| + /** |
| + * Resets internal data. It must be called on every loading start. |
| + */ |
| + void reset(); |
| + |
| + /** |
| + * Returns interpolated progress for animation. |
| + * |
| + * @param targetProgress Actual page loading progress. |
| + * @param frameTimeSec Duration since the last call. |
| + * @param resolution Resolution of the displayed progress bar. Mainly for rounding. |
| + */ |
| + float updateProgress(float targetProgress, float frameTimeSec, int resolution); |
| + } |
| + |
| + private static final long PROGRESS_FRAME_TIME_CAP_MS = 50; |
| + private long mAlphaAnimationDurationMs = 140; |
| private long mHidingDelayMs = 100; |
| private boolean mIsStarted; |
| + private float mTargetProgress; |
| private float mTargetAlpha = 0.0f; |
| + AnimationLogic mAnimationLogic; |
| + |
| private final Runnable mHideRunnable = new Runnable() { |
| @Override |
| public void run() { |
| @@ -26,6 +55,29 @@ public class ToolbarProgressBar extends ClipDrawableProgressBar { |
| } |
| }; |
| + private final TimeAnimator mProgressAnimator = new TimeAnimator(); |
| + { |
| + mProgressAnimator.setTimeListener(new TimeListener() { |
| + @Override |
| + public void onTimeUpdate(TimeAnimator animation, long totalTimeMs, long deltaTimeMs) { |
| + // Cap progress bar animation frame time so that it doesn't jump too much even when |
| + // the animation is janky. |
| + ToolbarProgressBar.super.setProgress(mAnimationLogic.updateProgress( |
| + mTargetProgress, |
| + Math.max(deltaTimeMs, PROGRESS_FRAME_TIME_CAP_MS) * 0.001f, |
| + getWidth())); |
| + |
| + if (getProgress() == mTargetProgress) { |
| + if (mTargetProgress == 1.0f && !mIsStarted) { |
| + postDelayed(mHideRunnable, mHidingDelayMs); |
| + } |
| + mProgressAnimator.end(); |
| + return; |
| + } |
| + } |
| + }); |
| + } |
| + |
| /** |
| * Creates a toolbar progress bar. |
| * |
| @@ -38,10 +90,28 @@ public class ToolbarProgressBar extends ClipDrawableProgressBar { |
| } |
| /** |
| + * Initializes animation based on command line configuration. This must be called when native |
| + * library is ready. |
| + */ |
| + public void initializeAnimation() { |
| + assert mAnimationLogic == null; |
| + |
| + String animation = CommandLine.getInstance().getSwitchValue( |
| + ChromeSwitches.PROGRESS_BAR_ANIMATION); |
| + if (TextUtils.equals(animation, "smooth")) { |
| + mAnimationLogic = new ProgressAnimationSmooth(); |
| + } else if (TextUtils.equals(animation, "fast-start")) { |
| + mAnimationLogic = new ProgressAnimationFastStart(); |
| + } |
| + } |
| + |
| + /** |
| * Start showing progress bar animation. |
| */ |
| public void start() { |
| mIsStarted = true; |
| + super.setProgress(0.0f); |
| + if (mAnimationLogic != null) mAnimationLogic.reset(); |
| removeCallbacks(mHideRunnable); |
| animateAlphaTo(1.0f); |
| } |
| @@ -53,10 +123,8 @@ public class ToolbarProgressBar extends ClipDrawableProgressBar { |
| public void finish(boolean delayed) { |
| mIsStarted = false; |
| - removeCallbacks(mHideRunnable); |
| - |
| if (delayed) { |
| - postDelayed(mHideRunnable, mHidingDelayMs); |
| + updateVisibleProgress(); |
|
jdduke (slow)
2015/08/03 23:35:35
Silly ignorant question: Is finish() allowed to be
Kibeom Kim (inactive)
2015/08/04 02:08:44
Yeah currently finish() can be called multiple tim
|
| } else { |
| mTargetAlpha = 0.0f; |
| setAlpha(0.0f); |
| @@ -93,11 +161,25 @@ public class ToolbarProgressBar extends ClipDrawableProgressBar { |
| } |
| } |
| + private void updateVisibleProgress() { |
| + if (mAnimationLogic == null) { |
| + super.setProgress(mTargetProgress); |
| + if (!mIsStarted) { |
| + postDelayed(mHideRunnable, mHidingDelayMs); |
| + } |
| + } else { |
| + if (!mProgressAnimator.isStarted()) mProgressAnimator.start(); |
| + } |
| + } |
| + |
| // ClipDrawableProgressBar implementation. |
| @Override |
| public void setProgress(float progress) { |
| assert mIsStarted; |
| - super.setProgress(progress); |
| + assert getProgress() <= progress; |
| + |
| + mTargetProgress = progress; |
| + updateVisibleProgress(); |
| } |
| } |