// Copyright 2015 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.widget;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ProgressBar;
import org.chromium.ui.interpolators.BakedBezierInterpolator;
/**
* A {@link ProgressBar} that understands the hiding/showing policy defined in Material Design.
*/
public class LoadingView extends ProgressBar {
private static final int LOADING_ANIMATION_DELAY_MS = 500;
private static final int MINIMUM_ANIMATION_SHOW_TIME_MS = 500;
private long mStartTime = -1;
private final Runnable mDelayedShow = new Runnable() {
@Override
public void run() {
if (!mShouldShow) return;
mStartTime = SystemClock.elapsedRealtime();
setVisibility(View.VISIBLE);
setAlpha(1.0f);
}
};
/**
* Tracks whether the View should be displayed when {@link #mDelayedShow} is run. Android
* doesn't always cancel a Runnable when requested, meaning that the View could be hidden before
* it even has a chance to be shown.
*/
private boolean mShouldShow;
// Material loading design spec requires us to show progress spinner at least 500ms, so we need
// this delayed runnable to implement that.
private final Runnable mDelayedHide = new Runnable() {
@Override
public void run() {
animate().alpha(0.0f).setInterpolator(BakedBezierInterpolator.TRANSFORM_CURVE)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
setVisibility(GONE);
}
});
}
};
/**
* Constructor for creating the view programatically.
*/
public LoadingView(Context context) {
super(context);
}
/**
* Constructor for inflating from XML.
*/
public LoadingView(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* Show loading UI. It shows the loading animation 500ms after.
*/
public void showLoadingUI() {
removeCallbacks(mDelayedShow);
removeCallbacks(mDelayedHide);
mShouldShow = true;
setVisibility(GONE);
postDelayed(mDelayedShow, LOADING_ANIMATION_DELAY_MS);
}
/**
* Hide loading UI. If progress bar is not shown, it disappears immediately. If so, it smoothly
* fades out.
*/
public void hideLoadingUI() {
removeCallbacks(mDelayedShow);
removeCallbacks(mDelayedHide);
mShouldShow = false;
if (getVisibility() == VISIBLE) {
postDelayed(mDelayedHide, Math.max(0,
mStartTime + MINIMUM_ANIMATION_SHOW_TIME_MS - SystemClock.elapsedRealtime()));
}
}
}