// Copyright 2016 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.ntp.cards; import android.content.Context; import android.support.annotation.ColorRes; import android.util.AttributeSet; import android.view.View; import android.widget.ImageView; import org.chromium.base.ApiCompatibilityUtils; import org.chromium.chrome.R; import org.chromium.third_party.android.swiperefresh.MaterialProgressDrawable; /** * Displays an indeterminate circular spinner, similar to {@link android.widget.ProgressBar} in * Lollipop+. This class allows to backport the Material style to pre-L OS versions. * * It stays invisible for the first 500ms when shown, to avoid showing a spinner when content * can load very quickly. */ public class ProgressIndicatorView extends ImageView { private static final int SHOW_DELAY_MS = 500; private final Runnable mShowSpinnerRunnable; private final MaterialProgressDrawable mProgressDrawable; private boolean mPostedCallback = false; /** * Constructor for use in layout files. */ public ProgressIndicatorView(Context context, AttributeSet attrs) { super(context, attrs); mShowSpinnerRunnable = new Runnable() { @Override public void run() { mPostedCallback = false; show(); } }; mProgressDrawable = new MaterialProgressDrawable(getContext(), this); mProgressDrawable.setBackgroundColor(getColorAsInt(R.color.ntp_material_design_bg)); mProgressDrawable.setAlpha(255); mProgressDrawable.setColorSchemeColors(getColorAsInt(R.color.light_active_color)); mProgressDrawable.updateSizes(MaterialProgressDrawable.LARGE); setImageDrawable(mProgressDrawable); hide(); } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); // When the view is detached, the progress drawable would have been invalidated and stopped // animating. We restart the animation here in that case. if (getVisibility() == VISIBLE) show(); } public void show() { if (mPostedCallback) return; // Stop first to reset the internal state of the drawable. mProgressDrawable.stop(); setVisibility(View.VISIBLE); mProgressDrawable.start(); } public void hide() { mProgressDrawable.stop(); removeCallbacks(mShowSpinnerRunnable); mPostedCallback = false; setVisibility(View.GONE); } public void showDelayed() { // The indicator is already visible, just let it as it is to avoid jumps in the animation. if (getVisibility() == View.VISIBLE) return; mPostedCallback = true; // We don't want to show the spinner every time we load content if it loads quickly; instead // only start showing the spinner if loading the content has taken longer than 500ms postDelayed(mShowSpinnerRunnable, SHOW_DELAY_MS); } private int getColorAsInt(@ColorRes int colorId) { return ApiCompatibilityUtils.getColor(getResources(), colorId); } }