FileDocCategorySizeDatePackage
ProgressBar.javaAPI DocAndroid 1.5 API29780Wed May 06 22:41:56 BST 2009android.widget

ProgressBar

public class ProgressBar extends android.view.View

Visual indicator of progress in some operation. Displays a bar to the user representing how far the operation has progressed; the application can change the amount of progress (modifying the length of the bar) as it moves forward. There is also a secondary progress displayable on a progress bar which is useful for displaying intermediate progress, such as the buffer level during a streaming playback progress bar.

A progress bar can also be made indeterminate. In indeterminate mode, the progress bar shows a cyclic animation. This mode is used by applications when the length of the task is unknown.

The following code example shows how a progress bar can be used from a worker thread to update the user interface to notify the user of progress:

public class MyActivity extends Activity {
private static final int PROGRESS = 0x1;

private ProgressBar mProgress;
private int mProgressStatus = 0;

private Handler mHandler = new Handler();

protected void onCreate(Bundle icicle) {
super.onCreate(icicle);

setContentView(R.layout.progressbar_activity);

mProgress = (ProgressBar) findViewById(R.id.progress_bar);

// Start lengthy operation in a background thread
new Thread(new Runnable() {
public void run() {
while (mProgressStatus < 100) {
mProgressStatus = doWork();

// Update the progress bar
mHandler.post(new Runnable() {
public void run() {
mProgress.setProgress(mProgressStatus);
}
});
}
}
}).start();
}
}

XML attributes

See {@link android.R.styleable#ProgressBar ProgressBar Attributes}, {@link android.R.styleable#View View Attributes}

Styles

attr
ref android.R.styleable#Theme_progressBarStyle
attr
ref android.R.styleable#Theme_progressBarStyleSmall
attr
ref android.R.styleable#Theme_progressBarStyleLarge
attr
ref android.R.styleable#Theme_progressBarStyleHorizontal

Fields Summary
private static final int
MAX_LEVEL
private static final int
ANIMATION_RESOLUTION
int
mMinWidth
int
mMaxWidth
int
mMinHeight
int
mMaxHeight
private int
mProgress
private int
mSecondaryProgress
private int
mMax
private int
mBehavior
private int
mDuration
private boolean
mIndeterminate
private boolean
mOnlyIndeterminate
private android.view.animation.Transformation
mTransformation
private android.view.animation.AlphaAnimation
mAnimation
private android.graphics.drawable.Drawable
mIndeterminateDrawable
private android.graphics.drawable.Drawable
mProgressDrawable
private android.graphics.drawable.Drawable
mCurrentDrawable
android.graphics.Bitmap
mSampleTile
private boolean
mNoInvalidate
private android.view.animation.Interpolator
mInterpolator
private RefreshProgressRunnable
mRefreshProgressRunnable
private long
mUiThreadId
private boolean
mShouldStartAnimationDrawable
private long
mLastDrawTime
private boolean
mInDrawing
Constructors Summary
public ProgressBar(android.content.Context context)
Create a new progress bar with range 0...100 and initial progress of 0.

param
context the application environment


                           
       
        this(context, null);
    
public ProgressBar(android.content.Context context, android.util.AttributeSet attrs)

        this(context, attrs, com.android.internal.R.attr.progressBarStyle);
    
public ProgressBar(android.content.Context context, android.util.AttributeSet attrs, int defStyle)

        super(context, attrs, defStyle);
        mUiThreadId = Thread.currentThread().getId();
        initProgressBar();

        TypedArray a =
            context.obtainStyledAttributes(attrs, R.styleable.ProgressBar, defStyle, 0);
        
        mNoInvalidate = true;
        
        Drawable drawable = a.getDrawable(R.styleable.ProgressBar_progressDrawable);
        if (drawable != null) {
            drawable = tileify(drawable, false);
            setProgressDrawable(drawable);
        }


        mDuration = a.getInt(R.styleable.ProgressBar_indeterminateDuration, mDuration);

        mMinWidth = a.getDimensionPixelSize(R.styleable.ProgressBar_minWidth, mMinWidth);
        mMaxWidth = a.getDimensionPixelSize(R.styleable.ProgressBar_maxWidth, mMaxWidth);
        mMinHeight = a.getDimensionPixelSize(R.styleable.ProgressBar_minHeight, mMinHeight);
        mMaxHeight = a.getDimensionPixelSize(R.styleable.ProgressBar_maxHeight, mMaxHeight);

        mBehavior = a.getInt(R.styleable.ProgressBar_indeterminateBehavior, mBehavior);

        final int resID = a.getResourceId(com.android.internal.R.styleable.ProgressBar_interpolator, -1);
        if (resID > 0) {
            setInterpolator(context, resID);
        }

        setMax(a.getInt(R.styleable.ProgressBar_max, mMax));

        setProgress(a.getInt(R.styleable.ProgressBar_progress, mProgress));

        setSecondaryProgress(
                a.getInt(R.styleable.ProgressBar_secondaryProgress, mSecondaryProgress));

        drawable = a.getDrawable(R.styleable.ProgressBar_indeterminateDrawable);
        if (drawable != null) {
            drawable = tileifyIndeterminate(drawable);
            setIndeterminateDrawable(drawable);
        }

        mOnlyIndeterminate = a.getBoolean(
                R.styleable.ProgressBar_indeterminateOnly, mOnlyIndeterminate);

        mNoInvalidate = false;

        setIndeterminate(mOnlyIndeterminate || a.getBoolean(
                R.styleable.ProgressBar_indeterminate, mIndeterminate));

        a.recycle();
    
Methods Summary
private synchronized voiddoRefreshProgress(int id, int progress, boolean fromUser)

        float scale = mMax > 0 ? (float) progress / (float) mMax : 0;
        final Drawable d = mCurrentDrawable;
        if (d != null) {
            Drawable progressDrawable = null;

            if (d instanceof LayerDrawable) {
                progressDrawable = ((LayerDrawable) d).findDrawableByLayerId(id);
            }

            final int level = (int) (scale * MAX_LEVEL);
            (progressDrawable != null ? progressDrawable : d).setLevel(level);
        } else {
            invalidate();
        }
        
        if (id == R.id.progress) {
            onProgressRefresh(scale, fromUser);
        }
    
protected voiddrawableStateChanged()

        super.drawableStateChanged();
        
        int[] state = getDrawableState();
        
        if (mProgressDrawable != null && mProgressDrawable.isStateful()) {
            mProgressDrawable.setState(state);
        }
        
        if (mIndeterminateDrawable != null && mIndeterminateDrawable.isStateful()) {
            mIndeterminateDrawable.setState(state);
        }
    
android.graphics.drawable.DrawablegetCurrentDrawable()

return
The drawable currently used to draw the progress bar

        return mCurrentDrawable;
    
android.graphics.drawable.shapes.ShapegetDrawableShape()

        final float[] roundedCorners = new float[] { 5, 5, 5, 5, 5, 5, 5, 5 };
        return new RoundRectShape(roundedCorners, null, null);
    
public android.graphics.drawable.DrawablegetIndeterminateDrawable()

Get the drawable used to draw the progress bar in indeterminate mode.

return
a {@link android.graphics.drawable.Drawable} instance
see
#setIndeterminateDrawable(android.graphics.drawable.Drawable)
see
#setIndeterminate(boolean)

        return mIndeterminateDrawable;
    
public android.view.animation.InterpolatorgetInterpolator()
Gets the acceleration curve type for the indeterminate animation.

return
the {@link Interpolator} associated to this animation

        return mInterpolator;
    
public synchronized intgetMax()

Return the upper limit of this progress bar's range.

return
a positive integer
see
#setMax(int)
see
#getProgress()
see
#getSecondaryProgress()

        return mMax;
    
public synchronized intgetProgress()

Get the progress bar's current level of progress. Return 0 when the progress bar is in indeterminate mode.

return
the current progress, between 0 and {@link #getMax()}
see
#setIndeterminate(boolean)
see
#isIndeterminate()
see
#setProgress(int)
see
#setMax(int)
see
#getMax()

        return mIndeterminate ? 0 : mProgress;
    
public android.graphics.drawable.DrawablegetProgressDrawable()

Get the drawable used to draw the progress bar in progress mode.

return
a {@link android.graphics.drawable.Drawable} instance
see
#setProgressDrawable(android.graphics.drawable.Drawable)
see
#setIndeterminate(boolean)

        return mProgressDrawable;
    
public synchronized intgetSecondaryProgress()

Get the progress bar's current level of secondary progress. Return 0 when the progress bar is in indeterminate mode.

return
the current secondary progress, between 0 and {@link #getMax()}
see
#setIndeterminate(boolean)
see
#isIndeterminate()
see
#setSecondaryProgress(int)
see
#setMax(int)
see
#getMax()

        return mIndeterminate ? 0 : mSecondaryProgress;
    
public final synchronized voidincrementProgressBy(int diff)

Increase the progress bar's progress by the specified amount.

param
diff the amount by which the progress must be increased
see
#setProgress(int)

        setProgress(mProgress + diff);
    
public final synchronized voidincrementSecondaryProgressBy(int diff)

Increase the progress bar's secondary progress by the specified amount.

param
diff the amount by which the secondary progress must be increased
see
#setSecondaryProgress(int)

        setSecondaryProgress(mSecondaryProgress + diff);
    
private voidinitProgressBar()

Initialize the progress bar's default values:

  • progress = 0
  • max = 100
  • animation duration = 4000 ms
  • indeterminate = false
  • behavior = repeat

        mMax = 100;
        mProgress = 0;
        mSecondaryProgress = 0;
        mIndeterminate = false;
        mOnlyIndeterminate = false;
        mDuration = 4000;
        mBehavior = AlphaAnimation.RESTART;
        mMinWidth = 24;
        mMaxWidth = 48;
        mMinHeight = 24;
        mMaxHeight = 48;
    
public voidinvalidateDrawable(android.graphics.drawable.Drawable dr)

        if (!mInDrawing) {
            if (verifyDrawable(dr)) {
                final Rect dirty = dr.getBounds();
                final int scrollX = mScrollX + mPaddingLeft;
                final int scrollY = mScrollY + mPaddingTop;

                invalidate(dirty.left + scrollX, dirty.top + scrollY,
                        dirty.right + scrollX, dirty.bottom + scrollY);
            } else {
                super.invalidateDrawable(dr);
            }
        }
    
public synchronized booleanisIndeterminate()

Indicate whether this progress bar is in indeterminate mode.

return
true if the progress bar is in indeterminate mode

        return mIndeterminate;
    
protected synchronized voidonDraw(android.graphics.Canvas canvas)

        super.onDraw(canvas);

        Drawable d = mCurrentDrawable;
        if (d != null) {
            // Translate canvas so a indeterminate circular progress bar with padding
            // rotates properly in its animation
            canvas.save();
            canvas.translate(mPaddingLeft, mPaddingTop);
            long time = getDrawingTime();
            if (mAnimation != null) {
                mAnimation.getTransformation(time, mTransformation);
                float scale = mTransformation.getAlpha();
                try {
                    mInDrawing = true;
                    d.setLevel((int) (scale * MAX_LEVEL));
                } finally {
                    mInDrawing = false;
                }
                if (SystemClock.uptimeMillis() - mLastDrawTime >= ANIMATION_RESOLUTION) {
                    mLastDrawTime = SystemClock.uptimeMillis();
                    postInvalidateDelayed(ANIMATION_RESOLUTION);
                }
            }
            d.draw(canvas);
            canvas.restore();
            if (mShouldStartAnimationDrawable && d instanceof AnimationDrawable) {
                ((AnimationDrawable) d).start();
                mShouldStartAnimationDrawable = false;
            }
        }
    
protected synchronized voidonMeasure(int widthMeasureSpec, int heightMeasureSpec)

        Drawable d = mCurrentDrawable;

        int dw = 0;
        int dh = 0;
        if (d != null) {
            dw = Math.max(mMinWidth, Math.min(mMaxWidth, d.getIntrinsicWidth()));
            dh = Math.max(mMinHeight, Math.min(mMaxHeight, d.getIntrinsicHeight()));
        }
        dw += mPaddingLeft + mPaddingRight;
        dh += mPaddingTop + mPaddingBottom;

        setMeasuredDimension(resolveSize(dw, widthMeasureSpec),
                resolveSize(dh, heightMeasureSpec));
    
voidonProgressRefresh(float scale, boolean fromUser)

        
    
public voidonRestoreInstanceState(android.os.Parcelable state)

        SavedState ss = (SavedState) state;
        super.onRestoreInstanceState(ss.getSuperState());
        
        setProgress(ss.progress);
        setSecondaryProgress(ss.secondaryProgress);
    
public android.os.ParcelableonSaveInstanceState()

    

    
       
        // Force our ancestor class to save its state
        Parcelable superState = super.onSaveInstanceState();
        SavedState ss = new SavedState(superState);
        
        ss.progress = mProgress;
        ss.secondaryProgress = mSecondaryProgress;
        
        return ss;
    
protected voidonSizeChanged(int w, int h, int oldw, int oldh)

        // onDraw will translate the canvas so we draw starting at 0,0
        int right = w - mPaddingRight - mPaddingLeft;
        int bottom = h - mPaddingBottom - mPaddingTop;

        if (mIndeterminateDrawable != null) {
            mIndeterminateDrawable.setBounds(0, 0, right, bottom);
        }
        
        if (mProgressDrawable != null) {
            mProgressDrawable.setBounds(0, 0, right, bottom);
        }
    
public voidpostInvalidate()

        if (!mNoInvalidate) {
            super.postInvalidate();
        }
    
private synchronized voidrefreshProgress(int id, int progress, boolean fromUser)

        if (mUiThreadId == Thread.currentThread().getId()) {
            doRefreshProgress(id, progress, fromUser);
        } else {
            RefreshProgressRunnable r;
            if (mRefreshProgressRunnable != null) {
                // Use cached RefreshProgressRunnable if available
                r = mRefreshProgressRunnable;
                // Uncache it
                mRefreshProgressRunnable = null;
                r.setup(id, progress, fromUser);
            } else {
                // Make a new one
                r = new RefreshProgressRunnable(id, progress, fromUser);
            }
            post(r);
        }
    
public synchronized voidsetIndeterminate(boolean indeterminate)

Change the indeterminate mode for this progress bar. In indeterminate mode, the progress is ignored and the progress bar shows an infinite animation instead.

If this progress bar's style only supports indeterminate mode (such as the circular progress bars), then this will be ignored.

param
indeterminate true to enable the indeterminate mode

        if ((!mOnlyIndeterminate || !mIndeterminate) && indeterminate != mIndeterminate) {
            mIndeterminate = indeterminate;

            if (indeterminate) {
                // swap between indeterminate and regular backgrounds
                mCurrentDrawable = mIndeterminateDrawable;
                startAnimation();
            } else {
                mCurrentDrawable = mProgressDrawable;
                stopAnimation();
            }
        }
    
public voidsetIndeterminateDrawable(android.graphics.drawable.Drawable d)

Define the drawable used to draw the progress bar in indeterminate mode.

param
d the new drawable
see
#getIndeterminateDrawable()
see
#setIndeterminate(boolean)

        if (d != null) {
            d.setCallback(this);
        }
        mIndeterminateDrawable = d;
        if (mIndeterminate) {
            mCurrentDrawable = d;
            postInvalidate();
        }
    
public voidsetInterpolator(android.content.Context context, int resID)
Sets the acceleration curve for the indeterminate animation. The interpolator is loaded as a resource from the specified context.

param
context The application environment
param
resID The resource identifier of the interpolator to load

        setInterpolator(AnimationUtils.loadInterpolator(context, resID));
    
public voidsetInterpolator(android.view.animation.Interpolator interpolator)
Sets the acceleration curve for the indeterminate animation. Defaults to a linear interpolation.

param
interpolator The interpolator which defines the acceleration curve

        mInterpolator = interpolator;
    
public synchronized voidsetMax(int max)

Set the range of the progress bar to 0...max.

param
max the upper range of this progress bar
see
#getMax()
see
#setProgress(int)
see
#setSecondaryProgress(int)

        if (max < 0) {
            max = 0;
        }
        if (max != mMax) {
            mMax = max;
            postInvalidate();

            if (mProgress > max) {
                mProgress = max;
            }
        }
    
public synchronized voidsetProgress(int progress)

Set the current progress to the specified value. Does not do anything if the progress bar is in indeterminate mode.

param
progress the new progress, between 0 and {@link #getMax()}
see
#setIndeterminate(boolean)
see
#isIndeterminate()
see
#getProgress()
see
#incrementProgressBy(int)

        setProgress(progress, false);
    
synchronized voidsetProgress(int progress, boolean fromUser)

        if (mIndeterminate) {
            return;
        }

        if (progress < 0) {
            progress = 0;
        }

        if (progress > mMax) {
            progress = mMax;
        }

        if (progress != mProgress) {
            mProgress = progress;
            refreshProgress(R.id.progress, mProgress, fromUser);
        }
    
public voidsetProgressDrawable(android.graphics.drawable.Drawable d)

Define the drawable used to draw the progress bar in progress mode.

param
d the new drawable
see
#getProgressDrawable()
see
#setIndeterminate(boolean)

        if (d != null) {
            d.setCallback(this);
        }
        mProgressDrawable = d;
        if (!mIndeterminate) {
            mCurrentDrawable = d;
            postInvalidate();
        }
    
public synchronized voidsetSecondaryProgress(int secondaryProgress)

Set the current secondary progress to the specified value. Does not do anything if the progress bar is in indeterminate mode.

param
secondaryProgress the new secondary progress, between 0 and {@link #getMax()}
see
#setIndeterminate(boolean)
see
#isIndeterminate()
see
#getSecondaryProgress()
see
#incrementSecondaryProgressBy(int)

        if (mIndeterminate) {
            return;
        }

        if (secondaryProgress < 0) {
            secondaryProgress = 0;
        }

        if (secondaryProgress > mMax) {
            secondaryProgress = mMax;
        }

        if (secondaryProgress != mSecondaryProgress) {
            mSecondaryProgress = secondaryProgress;
            refreshProgress(R.id.secondaryProgress, mSecondaryProgress, false);
        }
    
public voidsetVisibility(int v)

        if (getVisibility() != v) {
            super.setVisibility(v);

            if (mIndeterminate) {
                // let's be nice with the UI thread
                if (v == GONE || v == INVISIBLE) {
                    stopAnimation();
                } else if (v == VISIBLE) {
                    startAnimation();
                }
            }
        }
    
voidstartAnimation()

Start the indeterminate progress animation.

        int visibility = getVisibility();
        if (visibility != VISIBLE) {
            return;
        }

        if (mIndeterminateDrawable instanceof AnimationDrawable) {
            mShouldStartAnimationDrawable = true;
            mAnimation = null;
        } else {
            if (mInterpolator == null) {
                mInterpolator = new LinearInterpolator();
            }
    
            mTransformation = new Transformation();
            mAnimation = new AlphaAnimation(0.0f, 1.0f);
            mAnimation.setRepeatMode(mBehavior);
            mAnimation.setRepeatCount(Animation.INFINITE);
            mAnimation.setDuration(mDuration);
            mAnimation.setInterpolator(mInterpolator);
            mAnimation.setStartTime(Animation.START_ON_FIRST_FRAME);
            postInvalidate();
        }
    
voidstopAnimation()

Stop the indeterminate progress animation.

        mAnimation = null;
        mTransformation = null;
        if (mIndeterminateDrawable instanceof AnimationDrawable) {
            ((AnimationDrawable) mIndeterminateDrawable).stop();
            mShouldStartAnimationDrawable = false;
        }
    
private android.graphics.drawable.Drawabletileify(android.graphics.drawable.Drawable drawable, boolean clip)
Converts a drawable to a tiled version of itself. It will recursively traverse layer and state list drawables.

        
        if (drawable instanceof LayerDrawable) {
            LayerDrawable background = (LayerDrawable) drawable;
            final int N = background.getNumberOfLayers();
            Drawable[] outDrawables = new Drawable[N];
            
            for (int i = 0; i < N; i++) {
                int id = background.getId(i);
                outDrawables[i] = tileify(background.getDrawable(i),
                        (id == R.id.progress || id == R.id.secondaryProgress));
            }

            LayerDrawable newBg = new LayerDrawable(outDrawables);
            
            for (int i = 0; i < N; i++) {
                newBg.setId(i, background.getId(i));
            }
            
            return newBg;
            
        } else if (drawable instanceof StateListDrawable) {
            StateListDrawable in = (StateListDrawable) drawable;
            StateListDrawable out = new StateListDrawable();
            int numStates = in.getStateCount();
            for (int i = 0; i < numStates; i++) {
                out.addState(in.getStateSet(i), tileify(in.getStateDrawable(i), clip));
            }
            return out;
            
        } else if (drawable instanceof BitmapDrawable) {
            final Bitmap tileBitmap = ((BitmapDrawable) drawable).getBitmap();
            if (mSampleTile == null) {
                mSampleTile = tileBitmap;
            }
            
            final ShapeDrawable shapeDrawable = new ShapeDrawable(getDrawableShape());

            final BitmapShader bitmapShader = new BitmapShader(tileBitmap,
                    Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
            shapeDrawable.getPaint().setShader(bitmapShader);

            return (clip) ? new ClipDrawable(shapeDrawable, Gravity.LEFT,
                    ClipDrawable.HORIZONTAL) : shapeDrawable;
        }
        
        return drawable;
    
private android.graphics.drawable.DrawabletileifyIndeterminate(android.graphics.drawable.Drawable drawable)
Convert a AnimationDrawable for use as a barberpole animation. Each frame of the animation is wrapped in a ClipDrawable and given a tiling BitmapShader.

        if (drawable instanceof AnimationDrawable) {
            AnimationDrawable background = (AnimationDrawable) drawable;
            final int N = background.getNumberOfFrames();
            AnimationDrawable newBg = new AnimationDrawable();
            newBg.setOneShot(background.isOneShot());
            
            for (int i = 0; i < N; i++) {
                Drawable frame = tileify(background.getFrame(i), true);
                frame.setLevel(10000);
                newBg.addFrame(frame, background.getDuration(i));
            }
            newBg.setLevel(10000);
            drawable = newBg;
        }
        return drawable;
    
protected booleanverifyDrawable(android.graphics.drawable.Drawable who)

        return who == mProgressDrawable || who == mIndeterminateDrawable
                || super.verifyDrawable(who);