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 5b59f278b9beeb9b228d0ae3f4c6387a5c252b60..9531f53ff4f6d0c8a86ed1d1cf320ac327f5d4a3 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,183 +4,109 @@ |
package org.chromium.chrome.browser.widget; |
-import android.animation.Animator; |
-import android.animation.AnimatorListenerAdapter; |
-import android.animation.ObjectAnimator; |
+import android.animation.TimeAnimator; |
+import android.animation.TimeAnimator.TimeListener; |
import android.content.Context; |
-import android.graphics.drawable.Drawable; |
-import android.graphics.drawable.LayerDrawable; |
import android.util.AttributeSet; |
-import android.view.View; |
import org.chromium.base.VisibleForTesting; |
-import org.chromium.ui.interpolators.BakedBezierInterpolator; |
+import org.chromium.chrome.browser.util.MathUtils; |
/** |
* Progress bar for use in the Toolbar view. |
*/ |
-public class ToolbarProgressBar extends SmoothProgressBar { |
- private static final long PROGRESS_CLEARING_DELAY_MS = 200; |
- private static final int SHOW_HIDE_DURATION_MS = 100; |
- |
- private final Runnable mClearLoadProgressRunnable; |
- private int mDesiredVisibility; |
- private Animator mShowAnimator; |
- private Animator mHideAnimator; |
+public class ToolbarProgressBar extends ClipDrawableProgressBar { |
+ private static final float ALPHA_CHANGE_SPEED_PER_SECOND = 8.0f; |
+ private static final long HIDING_DELAY_MS = 100; |
+ |
+ // Public duration constants are for testing. |
+ public static final long SHOWING_DURATION_MS = |
+ (long) Math.ceil(1.0f / ALPHA_CHANGE_SPEED_PER_SECOND * 1000); |
+ public static final long HIDING_DURATION_MS = HIDING_DELAY_MS |
+ + (long) Math.ceil(1.0f / ALPHA_CHANGE_SPEED_PER_SECOND * 1000); |
+ |
+ private boolean mIsStarted; |
+ private float mTargetAlpha; |
+ private boolean mIsHideRunnablePosted; |
+ private TimeAnimator mAlphaAnimator = new TimeAnimator(); |
+ private final Runnable mHideRunnable = new Runnable() { |
+ @Override |
+ public void run() { |
+ animateAlphaTo(0.0f); |
+ mIsHideRunnablePosted = false; |
+ } |
+ }; |
/** |
* Creates a toolbar progress bar. |
+ * |
* @param context the application environment. |
* @param attrs the xml attributes that should be used to initialize this view. |
*/ |
public ToolbarProgressBar(Context context, AttributeSet attrs) { |
super(context, attrs); |
- // The base constructor will trigger a progress change and alter the expected |
- // visibility, so force a visibility change to reset the state. |
- setVisibility(VISIBLE); |
- |
- mClearLoadProgressRunnable = new Runnable() { |
- @Override |
- public void run() { |
- setProgress(0); |
- } |
- }; |
- |
- // Hide the background portion of the system progress bar. |
- Drawable progressDrawable = getProgressDrawable(); |
- if (progressDrawable instanceof LayerDrawable) { |
- Drawable progressBackgroundDrawable = |
- ((LayerDrawable) progressDrawable) |
- .findDrawableByLayerId(android.R.id.background); |
- if (progressBackgroundDrawable != null) { |
- progressBackgroundDrawable.setVisible(false, false); |
- progressBackgroundDrawable.setAlpha(0); |
- } |
- } |
- } |
- |
- @Override |
- public void setSecondaryProgress(int secondaryProgress) { |
- super.setSecondaryProgress(secondaryProgress); |
- setVisibilityForProgress(); |
- } |
- @Override |
- protected void setProgressInternal(int progress) { |
- super.setProgressInternal(progress); |
+ setAlpha(mTargetAlpha); |
- if (progress == getMax()) { |
- postDelayed(mClearLoadProgressRunnable, PROGRESS_CLEARING_DELAY_MS); |
- } |
+ mAlphaAnimator.setTimeListener(new TimeListener() { |
Ted C
2015/07/15 02:41:12
What is the benefit of the alpha animator?
Doesn'
Kibeom Kim (inactive)
2015/07/15 11:22:46
I like TimeAnimator in general, I don't know why I
|
+ @Override |
+ public void onTimeUpdate(TimeAnimator animation, long totalTimeMs, long deltaTimeMs) { |
+ float alpha = getAlpha(); |
- setVisibilityForProgress(); |
- } |
+ if (alpha == mTargetAlpha) { |
+ mAlphaAnimator.end(); |
+ return; |
+ } |
- @Override |
- public void setVisibility(int v) { |
- mDesiredVisibility = v; |
- setVisibilityForProgress(); |
+ float maxAlphaChange = ALPHA_CHANGE_SPEED_PER_SECOND * deltaTimeMs / 1000.0f; |
+ setAlpha(alpha |
+ + MathUtils.clamp(mTargetAlpha - alpha, -maxAlphaChange, maxAlphaChange)); |
+ } |
+ }); |
} |
- private void setVisibilityForProgress() { |
- if (mDesiredVisibility != VISIBLE) { |
- super.setVisibility(mDesiredVisibility); |
- return; |
- } |
- |
- int progress = Math.max(getProgress(), getSecondaryProgress()); |
- super.setVisibility(progress == 0 ? INVISIBLE : VISIBLE); |
- } |
+ /** |
+ * Start showing progress bar animation. |
+ */ |
+ public void start() { |
+ mIsStarted = true; |
- @Override |
- protected void onSizeChanged(int w, int h, int oldw, int oldh) { |
- super.onSizeChanged(w, h, oldw, oldh); |
- |
- // Some versions of Android have a bug where they don't properly update the drawables with |
- // the correct bounds. setProgressDrawable has been overridden to properly push the bounds |
- // but on rotation they weren't always being set. Forcing a bounds update on size changes |
- // fixes the problem. |
- setProgressDrawable(getProgressDrawable()); |
- } |
+ removeCallbacks(mHideRunnable); |
+ mIsHideRunnablePosted = false; |
- @Override |
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) { |
- super.onLayout(changed, left, top, right, bottom); |
- buildAnimators(); |
- setPivotY(getHeight()); |
+ animateAlphaTo(1.0f); |
} |
- @Override |
- public void setProgressDrawable(Drawable d) { |
- Drawable currentDrawable = getProgressDrawable(); |
- |
- super.setProgressDrawable(d); |
+ /** |
+ * Start hiding progress bar animation. |
+ */ |
+ public void finish() { |
+ mIsStarted = false; |
Ted C
2015/07/15 02:41:12
Is page load finished always going to happen right
Kibeom Kim (inactive)
2015/07/15 11:22:46
I think, regardless of happening right after 100%
Ted C
2015/07/15 17:42:59
Not sure I agree with the "correctness" assertion.
Kibeom Kim (inactive)
2015/07/16 04:45:48
Investigation so far:
In general, progress can be
|
- if (currentDrawable != null && d instanceof LayerDrawable) { |
- LayerDrawable ld = (LayerDrawable) d; |
- for (int i = 0; i < ld.getNumberOfLayers(); i++) { |
- ld.getDrawable(i).setBounds(currentDrawable.getBounds()); |
- } |
- } |
+ removeCallbacks(mHideRunnable); |
+ postDelayed(mHideRunnable, HIDING_DELAY_MS); |
+ mIsHideRunnablePosted = true; |
} |
/** |
- * @return Whether or not this progress bar has animations running for showing/hiding itself. |
+ * @return Whether or not this progress bar has animations running or scheduled for |
+ * showing/hiding itself. |
*/ |
@VisibleForTesting |
- boolean isAnimatingForShowOrHide() { |
- return (mShowAnimator != null && mShowAnimator.isStarted()) |
- || (mHideAnimator != null && mHideAnimator.isStarted()); |
+ public boolean isAnimatingForShowOrHide() { |
+ return mAlphaAnimator.isStarted() || mIsHideRunnablePosted; |
} |
- private void buildAnimators() { |
- if (mShowAnimator != null && mShowAnimator.isRunning()) mShowAnimator.end(); |
- if (mHideAnimator != null && mHideAnimator.isRunning()) mHideAnimator.end(); |
- |
- mShowAnimator = ObjectAnimator.ofFloat(this, View.SCALE_Y, 0.f, 1.f); |
- mShowAnimator.setDuration(SHOW_HIDE_DURATION_MS); |
- mShowAnimator.setInterpolator(BakedBezierInterpolator.FADE_IN_CURVE); |
- mShowAnimator.addListener(new AnimatorListenerAdapter() { |
- @Override |
- public void onAnimationStart(Animator animation) { |
- setSecondaryProgress(getMax()); |
- } |
- }); |
- |
- mHideAnimator = ObjectAnimator.ofFloat(this, View.SCALE_Y, 1.f, 0.f); |
- mHideAnimator.setDuration(SHOW_HIDE_DURATION_MS); |
- mHideAnimator.setInterpolator(BakedBezierInterpolator.FADE_OUT_CURVE); |
- mHideAnimator.addListener(new AnimatorListenerAdapter() { |
- @Override |
- public void onAnimationEnd(Animator animation) { |
- setSecondaryProgress(0); |
- } |
- }); |
+ private void animateAlphaTo(float targetAlpha) { |
+ mTargetAlpha = targetAlpha; |
+ if (getAlpha() != targetAlpha) mAlphaAnimator.start(); |
} |
+ // ClipDrawableProgressBar implementation. |
+ |
@Override |
- public void setProgress(int progress) { |
- // If the show animator has started, the progress bar needs to be tracked as if it is |
- // currently showing. This makes sure we trigger the proper hide animation and cancel the |
- // show animation if we show/hide the bar very fast. See crbug.com/453360. |
- boolean isShowing = |
- getProgress() > 0 || (mShowAnimator != null && mShowAnimator.isStarted()); |
- boolean willShow = progress > 0; |
- |
- removeCallbacks(mClearLoadProgressRunnable); |
+ public void setProgress(float progress) { |
+ assert mIsStarted; |
super.setProgress(progress); |
- |
- if (isShowing != willShow) { |
- if (mShowAnimator == null || mHideAnimator == null) buildAnimators(); |
- |
- if (mShowAnimator.isRunning()) mShowAnimator.end(); |
- if (mHideAnimator.isRunning()) mHideAnimator.end(); |
- |
- if (willShow) { |
- mShowAnimator.start(); |
- } else { |
- mHideAnimator.start(); |
- } |
- } |
} |
} |