blob: a0b707ef25ffcfff0898d9bc14ff2dd307d9a569 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.autofill_assistant;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ArgbEvaluator;
import android.animation.ValueAnimator;
import android.view.View;
import org.chromium.chrome.browser.compositor.animation.CompositorAnimator;
import org.chromium.chrome.browser.widget.MaterialProgressBar;
import java.util.ArrayDeque;
import java.util.Queue;
/**
* Wrapper around {@link MaterialProgressBar} to animate progress changes and enable/disable
* pulsing.
*/
public class AnimatedProgressBar {
// The number of ms the progress bar would take to go from 0 to 100%.
private static final int PROGRESS_BAR_SPEED_MS = 3_000;
private static final int PROGRESS_BAR_PULSING_DURATION_MS = 1_000;
private final MaterialProgressBar mProgressBar;
private final int mNormalColor;
private final int mPulsedColor;
private boolean mIsRunningProgressAnimation;
private int mLastProgress;
private Queue<ValueAnimator> mPendingIncreaseAnimations = new ArrayDeque<>();
private ValueAnimator mPulseAnimation;
public AnimatedProgressBar(MaterialProgressBar progressBar, int normalColor, int pulsedColor) {
mProgressBar = progressBar;
mNormalColor = normalColor;
mPulsedColor = pulsedColor;
}
public void show() {
mProgressBar.setVisibility(View.VISIBLE);
}
public void hide() {
mProgressBar.setVisibility(View.INVISIBLE);
}
/**
* Set the progress to {@code progress} if it is higher than the current progress, or do nothing
* if it is not (hence it is OK to call this method with the same value multiple times).
*/
public void maybeIncreaseProgress(int progress) {
if (progress > mLastProgress) {
ValueAnimator progressAnimation = ValueAnimator.ofInt(mLastProgress, progress);
progressAnimation.setDuration(PROGRESS_BAR_SPEED_MS * (progress - mLastProgress) / 100);
progressAnimation.setInterpolator(CompositorAnimator.ACCELERATE_INTERPOLATOR);
progressAnimation.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (mPendingIncreaseAnimations.isEmpty()) {
mIsRunningProgressAnimation = false;
} else {
mIsRunningProgressAnimation = true;
mPendingIncreaseAnimations.poll().start();
}
}
});
progressAnimation.addUpdateListener(
animation -> mProgressBar.setProgress((int) animation.getAnimatedValue()));
mLastProgress = progress;
if (mIsRunningProgressAnimation) {
mPendingIncreaseAnimations.offer(progressAnimation);
} else {
mIsRunningProgressAnimation = true;
progressAnimation.start();
}
}
}
public void enablePulsing() {
if (mPulseAnimation == null) {
mPulseAnimation = ValueAnimator.ofInt(mNormalColor, mPulsedColor);
mPulseAnimation.setDuration(PROGRESS_BAR_PULSING_DURATION_MS);
mPulseAnimation.setEvaluator(new ArgbEvaluator());
mPulseAnimation.setRepeatCount(ValueAnimator.INFINITE);
mPulseAnimation.setRepeatMode(ValueAnimator.REVERSE);
mPulseAnimation.setInterpolator(CompositorAnimator.ACCELERATE_INTERPOLATOR);
mPulseAnimation.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationCancel(Animator animation) {
mProgressBar.setProgressColor(mNormalColor);
}
});
mPulseAnimation.addUpdateListener(
animation -> mProgressBar.setProgressColor((int) animation.getAnimatedValue()));
mPulseAnimation.start();
}
}
public void disablePulsing() {
if (mPulseAnimation != null) {
mPulseAnimation.cancel();
mPulseAnimation = null;
}
}
}