1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.support.v4.widget; 18 19import android.content.Context; 20import android.util.AttributeSet; 21import android.view.View; 22import android.widget.ProgressBar; 23 24/** 25 * ContentLoadingProgressBar implements a ProgressBar that waits a minimum time to be 26 * dismissed before showing. Once visible, the progress bar will be visible for 27 * a minimum amount of time to avoid "flashes" in the UI when an event could take 28 * a largely variable time to complete (from none, to a user perceivable amount) 29 */ 30public class ContentLoadingProgressBar extends ProgressBar { 31 private static final int MIN_SHOW_TIME = 500; // ms 32 private static final int MIN_DELAY = 500; // ms 33 34 private long mStartTime = -1; 35 36 private boolean mPostedHide = false; 37 38 private boolean mPostedShow = false; 39 40 private boolean mDismissed = false; 41 42 private final Runnable mDelayedHide = new Runnable() { 43 44 @Override 45 public void run() { 46 mPostedHide = false; 47 mStartTime = -1; 48 setVisibility(View.GONE); 49 } 50 }; 51 52 private final Runnable mDelayedShow = new Runnable() { 53 54 @Override 55 public void run() { 56 mPostedShow = false; 57 if (!mDismissed) { 58 mStartTime = System.currentTimeMillis(); 59 setVisibility(View.VISIBLE); 60 } 61 } 62 }; 63 64 public ContentLoadingProgressBar(Context context) { 65 this(context, null); 66 } 67 68 public ContentLoadingProgressBar(Context context, AttributeSet attrs) { 69 super(context, attrs, 0); 70 } 71 72 @Override 73 public void onAttachedToWindow() { 74 super.onAttachedToWindow(); 75 removeCallbacks(); 76 } 77 78 @Override 79 public void onDetachedFromWindow() { 80 super.onDetachedFromWindow(); 81 removeCallbacks(); 82 } 83 84 private void removeCallbacks() { 85 removeCallbacks(mDelayedHide); 86 removeCallbacks(mDelayedShow); 87 } 88 89 /** 90 * Hide the progress view if it is visible. The progress view will not be 91 * hidden until it has been shown for at least a minimum show time. If the 92 * progress view was not yet visible, cancels showing the progress view. 93 */ 94 public void hide() { 95 mDismissed = true; 96 removeCallbacks(mDelayedShow); 97 long diff = System.currentTimeMillis() - mStartTime; 98 if (diff >= MIN_SHOW_TIME || mStartTime == -1) { 99 // The progress spinner has been shown long enough 100 // OR was not shown yet. If it wasn't shown yet, 101 // it will just never be shown. 102 setVisibility(View.GONE); 103 } else { 104 // The progress spinner is shown, but not long enough, 105 // so put a delayed message in to hide it when its been 106 // shown long enough. 107 if (!mPostedHide) { 108 postDelayed(mDelayedHide, MIN_SHOW_TIME - diff); 109 mPostedHide = true; 110 } 111 } 112 } 113 114 /** 115 * Show the progress view after waiting for a minimum delay. If 116 * during that time, hide() is called, the view is never made visible. 117 */ 118 public void show() { 119 // Reset the start time. 120 mStartTime = -1; 121 mDismissed = false; 122 removeCallbacks(mDelayedHide); 123 if (!mPostedShow) { 124 postDelayed(mDelayedShow, MIN_DELAY); 125 mPostedShow = true; 126 } 127 } 128} 129