blob: 75b1fa4ab208fa05fb23274906b249863dac4494 [file] [log] [blame]
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.gallery3d.util;
import android.app.Activity;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import java.util.HashMap;
import java.util.Map;
/**
* This class manages the visibility of the progress spinner in the action bar for an
* Activity. It filters out short-lived appearances of the progress spinner by only
* showing the spinner if it hasn't been hidden again before the end of a specified
* delay period. It also enforces a minimum display time once the spinner is made visible.
* This meant to cut down on the frequent "flashes" of the progress spinner.
*/
public class SpinnerVisibilitySetter {
private static final int SHOW_SPINNER_REQUESTED = 0;
private static final int HIDE_SPINNER_REQUESTED = 1;
private static final int SHOW_SPINNER_DELAY_REACHED = 2;
private static final int HIDE_SPINNER_DELAY_REACHED = 3;
// Amount of time after a show request that the progress spinner is actually made visible.
// This means that any show/hide requests that happen subsequently within this period
// of time will be ignored.
private static final long SPINNER_DISPLAY_DELAY = 1000;
// The minimum amount of time the progress spinner must be visible before it can be hidden.
private static final long MIN_SPINNER_DISPLAY_TIME = 2000;
private boolean mPendingVisibilityRequest = false;
private boolean mActiveVisibilityRequest = false;
private long mSpinnerVisibilityStartTime;
Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch(msg.what) {
case SHOW_SPINNER_REQUESTED:
mPendingVisibilityRequest = true;
sendEmptyMessageDelayed(SHOW_SPINNER_DELAY_REACHED, SPINNER_DISPLAY_DELAY);
break;
case HIDE_SPINNER_REQUESTED:
mPendingVisibilityRequest = false;
if (!mActiveVisibilityRequest) {
// We haven't requested to show the spinner so no need to decide
// when to hide it.
break;
}
long currTime = SystemClock.uptimeMillis();
if (currTime - mSpinnerVisibilityStartTime > MIN_SPINNER_DISPLAY_TIME) {
// The spinner has already been visible longer than the requisite min
// display time. Send the hide message immediately.
sendEmptyMessage(HIDE_SPINNER_DELAY_REACHED);
} else {
// The spinner is visible but hasn't been visible for long enough yet.
// Send a delayed hide message.
sendEmptyMessageAtTime(HIDE_SPINNER_DELAY_REACHED,
mSpinnerVisibilityStartTime + MIN_SPINNER_DISPLAY_TIME);
}
break;
case SHOW_SPINNER_DELAY_REACHED:
if (mPendingVisibilityRequest) {
mPendingVisibilityRequest = false;
mActiveVisibilityRequest = true;
// Even though the spinner isn't visible quite yet, lets set this
// here to avoid possible cross-thread synchronization issues.
mSpinnerVisibilityStartTime = SystemClock.uptimeMillis();
mActivity.runOnUiThread(new SetProgressVisibilityRunnable(true));
}
break;
case HIDE_SPINNER_DELAY_REACHED:
mActiveVisibilityRequest = false;
mActivity.runOnUiThread(new SetProgressVisibilityRunnable(false));
break;
}
}
};
static final Map<Activity, SpinnerVisibilitySetter> sInstanceMap =
new HashMap<Activity, SpinnerVisibilitySetter>();
private Activity mActivity;
private SpinnerVisibilitySetter(Activity activity) {
mActivity = activity;
}
public static SpinnerVisibilitySetter getInstance(Activity activity) {
synchronized(sInstanceMap) {
if (sInstanceMap.get(activity) == null) {
sInstanceMap.put(activity, new SpinnerVisibilitySetter(activity));
}
return sInstanceMap.get(activity);
}
}
public void setSpinnerVisibility(boolean visible) {
mHandler.sendEmptyMessage(visible ? SHOW_SPINNER_REQUESTED : HIDE_SPINNER_REQUESTED);
}
private class SetProgressVisibilityRunnable implements Runnable {
boolean mVisible;
public SetProgressVisibilityRunnable(boolean visible) {
mVisible = visible;
}
@Override
public void run() {
mActivity.setProgressBarIndeterminateVisibility(mVisible);
}
}
}