1ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banespackage android.support.v7.internal.widget; 2ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 3ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes/* 4ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * Copyright (C) 2013 Android Open Source Project 5ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * 6ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * Licensed under the Apache License, Version 2.0 (the "License"); 7ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * you may not use this file except in compliance with the License. 8ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * You may obtain a copy of the License at 9ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * 10ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * http://www.apache.org/licenses/LICENSE-2.0 11ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * 12ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * Unless required by applicable law or agreed to in writing, software 13ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * distributed under the License is distributed on an "AS IS" BASIS, 14ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * See the License for the specific language governing permissions and 16ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * limitations under the License. 17ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes */ 18ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 19ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 20ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banesimport android.content.Context; 21ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banesimport android.content.res.TypedArray; 22ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banesimport android.graphics.Bitmap; 23ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banesimport android.graphics.BitmapShader; 24ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banesimport android.graphics.Canvas; 25ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banesimport android.graphics.Rect; 26ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banesimport android.graphics.Shader; 27ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banesimport android.graphics.drawable.Animatable; 28ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banesimport android.graphics.drawable.AnimationDrawable; 29ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banesimport android.graphics.drawable.BitmapDrawable; 30ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banesimport android.graphics.drawable.ClipDrawable; 31ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banesimport android.graphics.drawable.Drawable; 32ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banesimport android.graphics.drawable.LayerDrawable; 33ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banesimport android.graphics.drawable.ShapeDrawable; 34ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banesimport android.graphics.drawable.shapes.RoundRectShape; 35ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banesimport android.graphics.drawable.shapes.Shape; 36ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banesimport android.os.Parcel; 37ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banesimport android.os.Parcelable; 38ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banesimport android.os.SystemClock; 39ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banesimport android.util.AttributeSet; 40ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banesimport android.view.Gravity; 41ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banesimport android.view.View; 42ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banesimport android.view.animation.AlphaAnimation; 43ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banesimport android.view.animation.Animation; 44ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banesimport android.view.animation.AnimationUtils; 45ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banesimport android.view.animation.Interpolator; 46ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banesimport android.view.animation.LinearInterpolator; 47ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banesimport android.view.animation.Transformation; 48ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 49ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes/** 50ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @hide 51ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes */ 52ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banespublic class ProgressBarICS extends View { 53ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 54ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private static final int MAX_LEVEL = 10000; 55ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private static final int ANIMATION_RESOLUTION = 200; 56ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 57ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes /** 58ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * android.R.styleable.ProgressBar is internalised, so we need to create it ourselves. 59ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes */ 60ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private static final int[] android_R_styleable_ProgressBar = new int[]{ 61ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes android.R.attr.max, 62ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes android.R.attr.progress, 63ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes android.R.attr.secondaryProgress, 64ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes android.R.attr.indeterminate, 65ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes android.R.attr.indeterminateOnly, 66ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes android.R.attr.indeterminateDrawable, 67ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes android.R.attr.progressDrawable, 68ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes android.R.attr.indeterminateDuration, 69ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes android.R.attr.indeterminateBehavior, 70ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes android.R.attr.minWidth, 71ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes android.R.attr.maxWidth, 72ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes android.R.attr.minHeight, 73ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes android.R.attr.maxHeight, 74ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes android.R.attr.interpolator, 75ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes }; 76ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 77ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes int mMinWidth; 78ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes int mMaxWidth; 79ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes int mMinHeight; 80ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes int mMaxHeight; 81ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 82ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private int mProgress; 83ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private int mSecondaryProgress; 84ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private int mMax; 85ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 86ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private int mBehavior; 87ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private int mDuration; 88ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private boolean mIndeterminate; 89ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private boolean mOnlyIndeterminate; 90ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private Transformation mTransformation; 91ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private AlphaAnimation mAnimation; 92ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private Drawable mIndeterminateDrawable; 93ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private Drawable mProgressDrawable; 94ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private Drawable mCurrentDrawable; 95ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes Bitmap mSampleTile; 96ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private boolean mNoInvalidate; 97ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private Interpolator mInterpolator; 98ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private RefreshProgressRunnable mRefreshProgressRunnable; 99ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private long mUiThreadId; 100ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private boolean mShouldStartAnimationDrawable; 101ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private long mLastDrawTime; 102ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 103ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private boolean mInDrawing; 104ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 105ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes /** 106ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @hide 107ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes */ 108ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes public ProgressBarICS(Context context, AttributeSet attrs, int defStyle, int styleRes) { 109ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes super(context, attrs, defStyle); 110ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mUiThreadId = Thread.currentThread().getId(); 111ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes initProgressBar(); 112ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 113ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes TypedArray a = context.obtainStyledAttributes(attrs, android_R_styleable_ProgressBar, 114ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes defStyle, styleRes); 115ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 116ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mNoInvalidate = true; 117ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 118ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes setMax(a.getInt(0, mMax)); 119ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes setProgress(a.getInt(1, mProgress)); 120ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes setSecondaryProgress(a.getInt(2, mSecondaryProgress)); 121ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 122ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes final boolean indeterminate = a.getBoolean(3, mIndeterminate); 123ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mOnlyIndeterminate = a.getBoolean(4, mOnlyIndeterminate); 124ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 125ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes Drawable drawable = a.getDrawable(5); 126ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (drawable != null) { 127ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes drawable = tileifyIndeterminate(drawable); 128ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes setIndeterminateDrawable(drawable); 129ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 130ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 131ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes drawable = a.getDrawable(6); 132ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (drawable != null) { 133ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes drawable = tileify(drawable, false); 134ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes // Calling this method can set mMaxHeight, make sure the corresponding 135ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes // XML attribute for mMaxHeight is read after calling this method 136ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes setProgressDrawable(drawable); 137ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 138ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 139ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mDuration = a.getInt(7, mDuration); 140ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mBehavior = a.getInt(8, mBehavior); 141ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mMinWidth = a.getDimensionPixelSize(9, mMinWidth); 142ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mMaxWidth = a.getDimensionPixelSize(10, mMaxWidth); 143ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mMinHeight = a.getDimensionPixelSize(11, mMinHeight); 144ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mMaxHeight = a.getDimensionPixelSize(12, mMaxHeight); 145ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 146ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes final int resID = a.getResourceId(13, android.R.anim.linear_interpolator); 147ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (resID > 0) { 148ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes setInterpolator(context, resID); 149ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 150ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 151ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes a.recycle(); 152ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 153ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mNoInvalidate = false; 154ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes setIndeterminate(mOnlyIndeterminate || indeterminate); 155ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 156ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 157ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes /** 158ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * Converts a drawable to a tiled version of itself. It will recursively 159ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * traverse layer and state list drawables. 160ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes */ 161ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private Drawable tileify(Drawable drawable, boolean clip) { 162ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 163ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (drawable instanceof LayerDrawable) { 164ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes LayerDrawable background = (LayerDrawable) drawable; 165ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes final int N = background.getNumberOfLayers(); 166ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes Drawable[] outDrawables = new Drawable[N]; 167ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 168ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes for (int i = 0; i < N; i++) { 169ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes int id = background.getId(i); 170ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes outDrawables[i] = tileify(background.getDrawable(i), 171ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes (id == android.R.id.progress || id == android.R.id.secondaryProgress)); 172ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 173ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 174ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes LayerDrawable newBg = new LayerDrawable(outDrawables); 175ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 176ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes for (int i = 0; i < N; i++) { 177ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes newBg.setId(i, background.getId(i)); 178ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 179ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 180ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes return newBg; 181ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 182ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } else if (drawable instanceof BitmapDrawable) { 183ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes final Bitmap tileBitmap = ((BitmapDrawable) drawable).getBitmap(); 184ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (mSampleTile == null) { 185ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mSampleTile = tileBitmap; 186ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 187ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 188ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes final ShapeDrawable shapeDrawable = new ShapeDrawable(getDrawableShape()); 189ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 190ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes final BitmapShader bitmapShader = new BitmapShader(tileBitmap, 191ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes Shader.TileMode.REPEAT, Shader.TileMode.CLAMP); 192ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes shapeDrawable.getPaint().setShader(bitmapShader); 193ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 194ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes return (clip) ? new ClipDrawable(shapeDrawable, Gravity.LEFT, 195ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes ClipDrawable.HORIZONTAL) : shapeDrawable; 196ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 197ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 198ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes return drawable; 199ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 200ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 201ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes Shape getDrawableShape() { 202ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes final float[] roundedCorners = new float[] { 5, 5, 5, 5, 5, 5, 5, 5 }; 203ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes return new RoundRectShape(roundedCorners, null, null); 204ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 205ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 206ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes /** 207ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * Convert a AnimationDrawable for use as a barberpole animation. 208ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * Each frame of the animation is wrapped in a ClipDrawable and 209ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * given a tiling BitmapShader. 210ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes */ 211ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private Drawable tileifyIndeterminate(Drawable drawable) { 212ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (drawable instanceof AnimationDrawable) { 213ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes AnimationDrawable background = (AnimationDrawable) drawable; 214ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes final int N = background.getNumberOfFrames(); 215ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes AnimationDrawable newBg = new AnimationDrawable(); 216ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes newBg.setOneShot(background.isOneShot()); 217ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 218ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes for (int i = 0; i < N; i++) { 219ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes Drawable frame = tileify(background.getFrame(i), true); 220ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes frame.setLevel(10000); 221ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes newBg.addFrame(frame, background.getDuration(i)); 222ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 223ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes newBg.setLevel(10000); 224ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes drawable = newBg; 225ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 226ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes return drawable; 227ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 228ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 229ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes /** 230ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * <p> 231ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * Initialize the progress bar's default values: 232ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * </p> 233ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * <ul> 234ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * <li>progress = 0</li> 235ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * <li>max = 100</li> 236ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * <li>animation duration = 4000 ms</li> 237ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * <li>indeterminate = false</li> 238ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * <li>behavior = repeat</li> 239ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * </ul> 240ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes */ 241ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private void initProgressBar() { 242ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mMax = 100; 243ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mProgress = 0; 244ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mSecondaryProgress = 0; 245ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mIndeterminate = false; 246ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mOnlyIndeterminate = false; 247ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mDuration = 4000; 248ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mBehavior = AlphaAnimation.RESTART; 249ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mMinWidth = 24; 250ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mMaxWidth = 48; 251ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mMinHeight = 24; 252ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mMaxHeight = 48; 253ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 254ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 255ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes /** 256ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * <p>Indicate whether this progress bar is in indeterminate mode.</p> 257ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * 258ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @return true if the progress bar is in indeterminate mode 259ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes */ 260ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes public synchronized boolean isIndeterminate() { 261ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes return mIndeterminate; 262ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 263ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 264ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes /** 265ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * <p>Change the indeterminate mode for this progress bar. In indeterminate 266ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * mode, the progress is ignored and the progress bar shows an infinite 267ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * animation instead.</p> 268ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * 269ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * If this progress bar's style only supports indeterminate mode (such as the circular 270ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * progress bars), then this will be ignored. 271ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * 272ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @param indeterminate true to enable the indeterminate mode 273ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes */ 274ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes public synchronized void setIndeterminate(boolean indeterminate) { 275ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if ((!mOnlyIndeterminate || !mIndeterminate) && indeterminate != mIndeterminate) { 276ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mIndeterminate = indeterminate; 277ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 278ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (indeterminate) { 279ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes // swap between indeterminate and regular backgrounds 280ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mCurrentDrawable = mIndeterminateDrawable; 281ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes startAnimation(); 282ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } else { 283ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mCurrentDrawable = mProgressDrawable; 284ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes stopAnimation(); 285ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 286ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 287ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 288ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 289ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes /** 290ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * <p>Get the drawable used to draw the progress bar in 291ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * indeterminate mode.</p> 292ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * 293ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @return a {@link android.graphics.drawable.Drawable} instance 294ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * 295ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @see #setIndeterminateDrawable(android.graphics.drawable.Drawable) 296ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @see #setIndeterminate(boolean) 297ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes */ 298ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes public Drawable getIndeterminateDrawable() { 299ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes return mIndeterminateDrawable; 300ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 301ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 302ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes /** 303ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * <p>Define the drawable used to draw the progress bar in 304ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * indeterminate mode.</p> 305ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * 306ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @param d the new drawable 307ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * 308ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @see #getIndeterminateDrawable() 309ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @see #setIndeterminate(boolean) 310ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes */ 311ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes public void setIndeterminateDrawable(Drawable d) { 312ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (d != null) { 313ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes d.setCallback(this); 314ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 315ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mIndeterminateDrawable = d; 316ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (mIndeterminate) { 317ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mCurrentDrawable = d; 318ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes postInvalidate(); 319ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 320ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 321ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 322ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes /** 323ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * <p>Get the drawable used to draw the progress bar in 324ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * progress mode.</p> 325ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * 326ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @return a {@link android.graphics.drawable.Drawable} instance 327ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * 328ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @see #setProgressDrawable(android.graphics.drawable.Drawable) 329ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @see #setIndeterminate(boolean) 330ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes */ 331ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes public Drawable getProgressDrawable() { 332ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes return mProgressDrawable; 333ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 334ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 335ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes /** 336ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * <p>Define the drawable used to draw the progress bar in 337ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * progress mode.</p> 338ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * 339ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @param d the new drawable 340ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * 341ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @see #getProgressDrawable() 342ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @see #setIndeterminate(boolean) 343ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes */ 344ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes public void setProgressDrawable(Drawable d) { 345ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes boolean needUpdate; 346ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (mProgressDrawable != null && d != mProgressDrawable) { 347ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mProgressDrawable.setCallback(null); 348ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes needUpdate = true; 349ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } else { 350ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes needUpdate = false; 351ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 352ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 353ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (d != null) { 354ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes d.setCallback(this); 355ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 356ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes // Make sure the android_R_styleable_ProgressBar is always tall enough 357ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes int drawableHeight = d.getMinimumHeight(); 358ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (mMaxHeight < drawableHeight) { 359ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mMaxHeight = drawableHeight; 360ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes requestLayout(); 361ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 362ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 363ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mProgressDrawable = d; 364ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (!mIndeterminate) { 365ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mCurrentDrawable = d; 366ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes postInvalidate(); 367ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 368ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 369ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (needUpdate) { 370ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes updateDrawableBounds(getWidth(), getHeight()); 371ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes updateDrawableState(); 372ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes doRefreshProgress(android.R.id.progress, mProgress, false, false); 373ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes doRefreshProgress(android.R.id.secondaryProgress, mSecondaryProgress, false, false); 374ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 375ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 376ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 377ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes @Override 378ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes protected boolean verifyDrawable(Drawable who) { 379ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes return who == mProgressDrawable || who == mIndeterminateDrawable 380ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes || super.verifyDrawable(who); 381ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 382ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 383ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes @Override 384ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes public void postInvalidate() { 385ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (!mNoInvalidate) { 386ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes super.postInvalidate(); 387ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 388ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 389ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 390ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private class RefreshProgressRunnable implements Runnable { 391ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 392ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private int mId; 393ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private int mProgress; 394ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private boolean mFromUser; 395ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 396ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes RefreshProgressRunnable(int id, int progress, boolean fromUser) { 397ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mId = id; 398ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mProgress = progress; 399ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mFromUser = fromUser; 400ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 401ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 402ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes public void run() { 403ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes doRefreshProgress(mId, mProgress, mFromUser, true); 404ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes // Put ourselves back in the cache when we are done 405ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mRefreshProgressRunnable = this; 406ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 407ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 408ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes public void setup(int id, int progress, boolean fromUser) { 409ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mId = id; 410ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mProgress = progress; 411ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mFromUser = fromUser; 412ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 413ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 414ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 415ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 416ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private synchronized void doRefreshProgress(int id, int progress, boolean fromUser, 417ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes boolean callBackToApp) { 418ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes float scale = mMax > 0 ? (float) progress / (float) mMax : 0; 419ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes final Drawable d = mCurrentDrawable; 420ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (d != null) { 421ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes Drawable progressDrawable = null; 422ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 423ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (d instanceof LayerDrawable) { 424ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes progressDrawable = ((LayerDrawable) d).findDrawableByLayerId(id); 425ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 426ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 427ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes final int level = (int) (scale * MAX_LEVEL); 428ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes (progressDrawable != null ? progressDrawable : d).setLevel(level); 429ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } else { 430ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes invalidate(); 431ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 432ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 433ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 434ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private synchronized void refreshProgress(int id, int progress, boolean fromUser) { 435ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (mUiThreadId == Thread.currentThread().getId()) { 436ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes doRefreshProgress(id, progress, fromUser, true); 437ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } else { 438ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes RefreshProgressRunnable r; 439ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (mRefreshProgressRunnable != null) { 440ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes // Use cached RefreshProgressRunnable if available 441ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes r = mRefreshProgressRunnable; 442ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes // Uncache it 443ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mRefreshProgressRunnable = null; 444ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes r.setup(id, progress, fromUser); 445ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } else { 446ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes // Make a new one 447ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes r = new RefreshProgressRunnable(id, progress, fromUser); 448ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 449ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes post(r); 450ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 451ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 452ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 453ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes /** 454ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * <p>Set the current progress to the specified value. Does not do anything 455ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * if the progress bar is in indeterminate mode.</p> 456ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * 457ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @param progress the new progress, between 0 and {@link #getMax()} 458ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * 459ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @see #setIndeterminate(boolean) 460ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @see #isIndeterminate() 461ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @see #getProgress() 462ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @see #incrementProgressBy(int) 463ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes */ 464ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes public synchronized void setProgress(int progress) { 465ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes setProgress(progress, false); 466ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 467ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 468ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes synchronized void setProgress(int progress, boolean fromUser) { 469ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (mIndeterminate) { 470ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes return; 471ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 472ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 473ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (progress < 0) { 474ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes progress = 0; 475ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 476ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 477ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (progress > mMax) { 478ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes progress = mMax; 479ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 480ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 481ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (progress != mProgress) { 482ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mProgress = progress; 483ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes refreshProgress(android.R.id.progress, mProgress, fromUser); 484ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 485ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 486ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 487ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes /** 488ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * <p> 489ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * Set the current secondary progress to the specified value. Does not do 490ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * anything if the progress bar is in indeterminate mode. 491ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * </p> 492ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * 493ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @param secondaryProgress the new secondary progress, between 0 and {@link #getMax()} 494ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @see #setIndeterminate(boolean) 495ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @see #isIndeterminate() 496ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @see #getSecondaryProgress() 497ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @see #incrementSecondaryProgressBy(int) 498ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes */ 499ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes public synchronized void setSecondaryProgress(int secondaryProgress) { 500ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (mIndeterminate) { 501ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes return; 502ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 503ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 504ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (secondaryProgress < 0) { 505ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes secondaryProgress = 0; 506ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 507ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 508ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (secondaryProgress > mMax) { 509ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes secondaryProgress = mMax; 510ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 511ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 512ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (secondaryProgress != mSecondaryProgress) { 513ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mSecondaryProgress = secondaryProgress; 514ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes refreshProgress(android.R.id.secondaryProgress, mSecondaryProgress, false); 515ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 516ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 517ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 518ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes /** 519ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * <p>Get the progress bar's current level of progress. Return 0 when the 520ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * progress bar is in indeterminate mode.</p> 521ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * 522ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @return the current progress, between 0 and {@link #getMax()} 523ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * 524ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @see #setIndeterminate(boolean) 525ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @see #isIndeterminate() 526ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @see #setProgress(int) 527ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @see #setMax(int) 528ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @see #getMax() 529ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes */ 530ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes public synchronized int getProgress() { 531ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes return mIndeterminate ? 0 : mProgress; 532ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 533ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 534ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes /** 535ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * <p>Get the progress bar's current level of secondary progress. Return 0 when the 536ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * progress bar is in indeterminate mode.</p> 537ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * 538ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @return the current secondary progress, between 0 and {@link #getMax()} 539ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * 540ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @see #setIndeterminate(boolean) 541ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @see #isIndeterminate() 542ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @see #setSecondaryProgress(int) 543ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @see #setMax(int) 544ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @see #getMax() 545ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes */ 546ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes public synchronized int getSecondaryProgress() { 547ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes return mIndeterminate ? 0 : mSecondaryProgress; 548ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 549ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 550ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes /** 551ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * <p>Return the upper limit of this progress bar's range.</p> 552ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * 553ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @return a positive integer 554ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * 555ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @see #setMax(int) 556ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @see #getProgress() 557ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @see #getSecondaryProgress() 558ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes */ 559ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes public synchronized int getMax() { 560ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes return mMax; 561ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 562ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 563ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes /** 564ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * <p>Set the range of the progress bar to 0...<tt>max</tt>.</p> 565ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * 566ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @param max the upper range of this progress bar 567ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * 568ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @see #getMax() 569ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @see #setProgress(int) 570ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @see #setSecondaryProgress(int) 571ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes */ 572ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes public synchronized void setMax(int max) { 573ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (max < 0) { 574ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes max = 0; 575ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 576ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (max != mMax) { 577ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mMax = max; 578ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes postInvalidate(); 579ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 580ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (mProgress > max) { 581ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mProgress = max; 582ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 583ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes refreshProgress(android.R.id.progress, mProgress, false); 584ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 585ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 586ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 587ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes /** 588ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * <p>Increase the progress bar's progress by the specified amount.</p> 589ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * 590ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @param diff the amount by which the progress must be increased 591ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * 592ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @see #setProgress(int) 593ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes */ 594ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes public synchronized final void incrementProgressBy(int diff) { 595ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes setProgress(mProgress + diff); 596ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 597ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 598ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes /** 599ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * <p>Increase the progress bar's secondary progress by the specified amount.</p> 600ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * 601ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @param diff the amount by which the secondary progress must be increased 602ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * 603ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @see #setSecondaryProgress(int) 604ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes */ 605ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes public synchronized final void incrementSecondaryProgressBy(int diff) { 606ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes setSecondaryProgress(mSecondaryProgress + diff); 607ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 608ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 609ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes /** 610ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * <p>Start the indeterminate progress animation.</p> 611ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes */ 612ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes void startAnimation() { 613ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (getVisibility() != VISIBLE) { 614ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes return; 615ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 616ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 617ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (mIndeterminateDrawable instanceof Animatable) { 618ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mShouldStartAnimationDrawable = true; 619ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mAnimation = null; 620ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } else { 621ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (mInterpolator == null) { 622ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mInterpolator = new LinearInterpolator(); 623ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 624ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 625ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mTransformation = new Transformation(); 626ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mAnimation = new AlphaAnimation(0.0f, 1.0f); 627ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mAnimation.setRepeatMode(mBehavior); 628ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mAnimation.setRepeatCount(Animation.INFINITE); 629ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mAnimation.setDuration(mDuration); 630ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mAnimation.setInterpolator(mInterpolator); 631ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mAnimation.setStartTime(Animation.START_ON_FIRST_FRAME); 632ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 633ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes postInvalidate(); 634ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 635ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 636ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes /** 637ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * <p>Stop the indeterminate progress animation.</p> 638ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes */ 639ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes void stopAnimation() { 640ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mAnimation = null; 641ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mTransformation = null; 642ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (mIndeterminateDrawable instanceof Animatable) { 643ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes ((Animatable) mIndeterminateDrawable).stop(); 644ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mShouldStartAnimationDrawable = false; 645ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 646ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes postInvalidate(); 647ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 648ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 649ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes /** 650ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * Sets the acceleration curve for the indeterminate animation. 651ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * The interpolator is loaded as a resource from the specified context. 652ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * 653ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @param context The application environment 654ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @param resID The resource identifier of the interpolator to load 655ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes */ 656ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes public void setInterpolator(Context context, int resID) { 657ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes setInterpolator(AnimationUtils.loadInterpolator(context, resID)); 658ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 659ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 660ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes /** 661ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * Sets the acceleration curve for the indeterminate animation. 662ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * Defaults to a linear interpolation. 663ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * 664ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @param interpolator The interpolator which defines the acceleration curve 665ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes */ 666ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes public void setInterpolator(Interpolator interpolator) { 667ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mInterpolator = interpolator; 668ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 669ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 670ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes /** 671ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * Gets the acceleration curve type for the indeterminate animation. 672ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * 673ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * @return the {@link Interpolator} associated to this animation 674ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes */ 675ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes public Interpolator getInterpolator() { 676ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes return mInterpolator; 677ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 678ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 679ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes @Override 680ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes public void setVisibility(int v) { 681ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (getVisibility() != v) { 682ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes super.setVisibility(v); 683ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 684ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (mIndeterminate) { 685ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes // let's be nice with the UI thread 686ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (v == GONE || v == INVISIBLE) { 687ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes stopAnimation(); 688ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } else { 689ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes startAnimation(); 690ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 691ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 692ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 693ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 694ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 695ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes @Override 696ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes protected void onVisibilityChanged(View changedView, int visibility) { 697ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes super.onVisibilityChanged(changedView, visibility); 698ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 699ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (mIndeterminate) { 700ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes // let's be nice with the UI thread 701ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (visibility == GONE || visibility == INVISIBLE) { 702ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes stopAnimation(); 703ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } else { 704ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes startAnimation(); 705ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 706ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 707ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 708ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 709ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes @Override 710ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes public void invalidateDrawable(Drawable dr) { 711ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (!mInDrawing) { 712ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (verifyDrawable(dr)) { 713ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes final Rect dirty = dr.getBounds(); 714ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes final int scrollX = getScrollX() + getPaddingLeft(); 715ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes final int scrollY = getScrollY() + getPaddingTop(); 716ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 717ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes invalidate(dirty.left + scrollX, dirty.top + scrollY, 718ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes dirty.right + scrollX, dirty.bottom + scrollY); 719ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } else { 720ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes super.invalidateDrawable(dr); 721ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 722ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 723ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 724ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 725ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes @Override 726ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes protected void onSizeChanged(int w, int h, int oldw, int oldh) { 727ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes updateDrawableBounds(w, h); 728ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 729ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 730ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private void updateDrawableBounds(int w, int h) { 731ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes // onDraw will translate the canvas so we draw starting at 0,0 732ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes int right = w - getPaddingRight() - getPaddingLeft(); 733ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes int bottom = h - getPaddingBottom() - getPaddingTop(); 734ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes int top = 0; 735ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes int left = 0; 736ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 737ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (mIndeterminateDrawable != null) { 738ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes // Aspect ratio logic does not apply to AnimationDrawables 739ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (mOnlyIndeterminate && !(mIndeterminateDrawable instanceof AnimationDrawable)) { 740ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes // Maintain aspect ratio. Certain kinds of animated drawables 741ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes // get very confused otherwise. 742ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes final int intrinsicWidth = mIndeterminateDrawable.getIntrinsicWidth(); 743ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes final int intrinsicHeight = mIndeterminateDrawable.getIntrinsicHeight(); 744ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes final float intrinsicAspect = (float) intrinsicWidth / intrinsicHeight; 745ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes final float boundAspect = (float) w / h; 746ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (intrinsicAspect != boundAspect) { 747ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (boundAspect > intrinsicAspect) { 748ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes // New width is larger. Make it smaller to match height. 749ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes final int width = (int) (h * intrinsicAspect); 750ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes left = (w - width) / 2; 751ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes right = left + width; 752ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } else { 753ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes // New height is larger. Make it smaller to match width. 754ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes final int height = (int) (w * (1 / intrinsicAspect)); 755ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes top = (h - height) / 2; 756ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes bottom = top + height; 757ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 758ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 759ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 760ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mIndeterminateDrawable.setBounds(left, top, right, bottom); 761ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 762ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 763ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (mProgressDrawable != null) { 764ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mProgressDrawable.setBounds(0, 0, right, bottom); 765ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 766ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 767ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 768ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes @Override 769ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes protected synchronized void onDraw(Canvas canvas) { 770ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes super.onDraw(canvas); 771ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 772ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes Drawable d = mCurrentDrawable; 773ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (d != null) { 774ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes // Translate canvas so a indeterminate circular progress bar with padding 775ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes // rotates properly in its animation 776ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes canvas.save(); 777ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes canvas.translate(getPaddingLeft(), getPaddingTop()); 778ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes long time = getDrawingTime(); 779ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (mAnimation != null) { 780ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mAnimation.getTransformation(time, mTransformation); 781ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes float scale = mTransformation.getAlpha(); 782ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes try { 783ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mInDrawing = true; 784ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes d.setLevel((int) (scale * MAX_LEVEL)); 785ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } finally { 786ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mInDrawing = false; 787ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 788ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (SystemClock.uptimeMillis() - mLastDrawTime >= ANIMATION_RESOLUTION) { 789ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mLastDrawTime = SystemClock.uptimeMillis(); 790ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes postInvalidateDelayed(ANIMATION_RESOLUTION); 791ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 792ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 793ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes d.draw(canvas); 794ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes canvas.restore(); 795ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (mShouldStartAnimationDrawable && d instanceof Animatable) { 796ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes ((Animatable) d).start(); 797ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mShouldStartAnimationDrawable = false; 798ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 799ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 800ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 801ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 802ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes @Override 803ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 804ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes Drawable d = mCurrentDrawable; 805ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 806ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes int dw = 0; 807ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes int dh = 0; 808ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (d != null) { 809ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes dw = Math.max(mMinWidth, Math.min(mMaxWidth, d.getIntrinsicWidth())); 810ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes dh = Math.max(mMinHeight, Math.min(mMaxHeight, d.getIntrinsicHeight())); 811ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 812ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes updateDrawableState(); 813ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes dw += getPaddingLeft() + getPaddingRight(); 814ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes dh += getPaddingTop() + getPaddingBottom(); 815ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 816ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes setMeasuredDimension(resolveSize(dw, widthMeasureSpec), 817ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes resolveSize(dh, heightMeasureSpec)); 818ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 819ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 820ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes @Override 821ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes protected void drawableStateChanged() { 822ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes super.drawableStateChanged(); 823ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes updateDrawableState(); 824ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 825ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 826ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private void updateDrawableState() { 827ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes int[] state = getDrawableState(); 828ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 829ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (mProgressDrawable != null && mProgressDrawable.isStateful()) { 830ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mProgressDrawable.setState(state); 831ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 832ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 833ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (mIndeterminateDrawable != null && mIndeterminateDrawable.isStateful()) { 834ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes mIndeterminateDrawable.setState(state); 835ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 836ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 837ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 838ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes static class SavedState extends BaseSavedState { 839ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes int progress; 840ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes int secondaryProgress; 841ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 842ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes /** 843ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * Constructor called from {@link ProgressBarICS#onSaveInstanceState()} 844ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes */ 845ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes SavedState(Parcelable superState) { 846ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes super(superState); 847ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 848ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 849ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes /** 850ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes * Constructor called from {@link #CREATOR} 851ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes */ 852ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes private SavedState(Parcel in) { 853ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes super(in); 854ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes progress = in.readInt(); 855ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes secondaryProgress = in.readInt(); 856ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 857ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 858ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes @Override 859ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes public void writeToParcel(Parcel out, int flags) { 860ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes super.writeToParcel(out, flags); 861ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes out.writeInt(progress); 862ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes out.writeInt(secondaryProgress); 863ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 864ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 865ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes public static final Parcelable.Creator<SavedState> CREATOR 866ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes = new Parcelable.Creator<SavedState>() { 867ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes public SavedState createFromParcel(Parcel in) { 868ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes return new SavedState(in); 869ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 870ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 871ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes public SavedState[] newArray(int size) { 872ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes return new SavedState[size]; 873ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 874ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes }; 875ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 876ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 877ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes @Override 878ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes public Parcelable onSaveInstanceState() { 879ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes // Force our ancestor class to save its state 880ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes Parcelable superState = super.onSaveInstanceState(); 881ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes SavedState ss = new SavedState(superState); 882ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 883ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes ss.progress = mProgress; 884ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes ss.secondaryProgress = mSecondaryProgress; 885ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 886ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes return ss; 887ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 888ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 889ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes @Override 890ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes public void onRestoreInstanceState(Parcelable state) { 891ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes SavedState ss = (SavedState) state; 892ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes super.onRestoreInstanceState(ss.getSuperState()); 893ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 894ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes setProgress(ss.progress); 895ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes setSecondaryProgress(ss.secondaryProgress); 896ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 897ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 898ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes @Override 899ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes protected void onAttachedToWindow() { 900ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes super.onAttachedToWindow(); 901ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (mIndeterminate) { 902ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes startAnimation(); 903ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 904ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 905ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 906ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes @Override 907ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes protected void onDetachedFromWindow() { 908ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if (mIndeterminate) { 909ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes stopAnimation(); 910ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 911ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes if(mRefreshProgressRunnable != null) { 912ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes removeCallbacks(mRefreshProgressRunnable); 913ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 914ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 915ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes // This should come after stopAnimation(), otherwise an invalidate message remains in the 916ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes // queue, which can prevent the entire view hierarchy from being GC'ed during a rotation 917ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes super.onDetachedFromWindow(); 918ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes } 919ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes 920ed34e2dffd0ce7da89063d06fd3b25687ca367a2Chris Banes}