FileDocCategorySizeDatePackage
ProgressBar.javaAPI DocAndroid 5.1 API68001Thu Mar 12 22:22:10 GMT 2015android.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 without an indication of progress. This mode is used by applications when the length of the task is unknown. The indeterminate progress bar can be either a spinning wheel or a horizontal bar.

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();
}
}

To add a progress bar to a layout file, you can use the {@code <ProgressBar>} element. By default, the progress bar is a spinning wheel (an indeterminate indicator). To change to a horizontal progress bar, apply the {@link android.R.style#Widget_ProgressBar_Horizontal Widget.ProgressBar.Horizontal} style, like so:

<ProgressBar
style="@android:style/Widget.ProgressBar.Horizontal"
... />

If you will use the progress bar to show real progress, you must use the horizontal bar. You can then increment the progress with {@link #incrementProgressBy incrementProgressBy()} or {@link #setProgress setProgress()}. By default, the progress bar is full when it reaches 100. If necessary, you can adjust the maximum value (the value for a full bar) using the {@link android.R.styleable#ProgressBar_max android:max} attribute. Other attributes available are listed below.

Another common style to apply to the progress bar is {@link android.R.style#Widget_ProgressBar_Small Widget.ProgressBar.Small}, which shows a smaller version of the spinning wheel—useful when waiting for content to load. For example, you can insert this kind of progress bar into your default layout for a view that will be populated by some content fetched from the Internet—the spinning wheel appears immediately and when your application receives the content, it replaces the progress bar with the loaded content. For example:

<LinearLayout
android:orientation="horizontal"
... >
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@android:style/Widget.ProgressBar.Small"
android:layout_marginRight="5dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/loading" />
</LinearLayout>

Other progress bar styles provided by the system include:

  • {@link android.R.style#Widget_ProgressBar_Horizontal Widget.ProgressBar.Horizontal}
  • {@link android.R.style#Widget_ProgressBar_Small Widget.ProgressBar.Small}
  • {@link android.R.style#Widget_ProgressBar_Large Widget.ProgressBar.Large}
  • {@link android.R.style#Widget_ProgressBar_Inverse Widget.ProgressBar.Inverse}
  • {@link android.R.style#Widget_ProgressBar_Small_Inverse Widget.ProgressBar.Small.Inverse}
  • {@link android.R.style#Widget_ProgressBar_Large_Inverse Widget.ProgressBar.Large.Inverse}

The "inverse" styles provide an inverse color scheme for the spinner, which may be necessary if your application uses a light colored theme (a white background).

XML attributes

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

attr
ref android.R.styleable#ProgressBar_animationResolution
attr
ref android.R.styleable#ProgressBar_indeterminate
attr
ref android.R.styleable#ProgressBar_indeterminateBehavior
attr
ref android.R.styleable#ProgressBar_indeterminateDrawable
attr
ref android.R.styleable#ProgressBar_indeterminateDuration
attr
ref android.R.styleable#ProgressBar_indeterminateOnly
attr
ref android.R.styleable#ProgressBar_interpolator
attr
ref android.R.styleable#ProgressBar_max
attr
ref android.R.styleable#ProgressBar_maxHeight
attr
ref android.R.styleable#ProgressBar_maxWidth
attr
ref android.R.styleable#ProgressBar_minHeight
attr
ref android.R.styleable#ProgressBar_minWidth
attr
ref android.R.styleable#ProgressBar_mirrorForRtl
attr
ref android.R.styleable#ProgressBar_progress
attr
ref android.R.styleable#ProgressBar_progressDrawable
attr
ref android.R.styleable#ProgressBar_secondaryProgress

Fields Summary
private static final int
MAX_LEVEL
private static final int
TIMEOUT_SEND_ACCESSIBILITY_EVENT
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 boolean
mHasAnimation
private android.graphics.drawable.Drawable
mIndeterminateDrawable
private android.graphics.drawable.Drawable
mProgressDrawable
private android.graphics.drawable.Drawable
mCurrentDrawable
private ProgressTintInfo
mProgressTintInfo
android.graphics.Bitmap
mSampleTile
private boolean
mNoInvalidate
private android.view.animation.Interpolator
mInterpolator
private RefreshProgressRunnable
mRefreshProgressRunnable
private long
mUiThreadId
private boolean
mShouldStartAnimationDrawable
private boolean
mInDrawing
private boolean
mAttached
private boolean
mRefreshIsPosted
boolean
mMirrorForRtl
private final ArrayList
mRefreshData
private AccessibilityEventSender
mAccessibilityEventSender
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 defStyleAttr)

        this(context, attrs, defStyleAttr, 0);
    
public ProgressBar(android.content.Context context, android.util.AttributeSet attrs, int defStyleAttr, int defStyleRes)

        super(context, attrs, defStyleAttr, defStyleRes);

        mUiThreadId = Thread.currentThread().getId();
        initProgressBar();

        final TypedArray a = context.obtainStyledAttributes(
                attrs, R.styleable.ProgressBar, defStyleAttr, defStyleRes);
        
        mNoInvalidate = true;
        
        final Drawable progressDrawable = a.getDrawable(R.styleable.ProgressBar_progressDrawable);
        if (progressDrawable != null) {
            // Calling this method can set mMaxHeight, make sure the corresponding
            // XML attribute for mMaxHeight is read after calling this method
            setProgressDrawableTiled(progressDrawable);
        }


        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, 
                android.R.anim.linear_interpolator); // default to linear interpolator
        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));

        final Drawable indeterminateDrawable = a.getDrawable(
                R.styleable.ProgressBar_indeterminateDrawable);
        if (indeterminateDrawable != null) {
            setIndeterminateDrawableTiled(indeterminateDrawable);
        }

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

        mNoInvalidate = false;

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

        mMirrorForRtl = a.getBoolean(R.styleable.ProgressBar_mirrorForRtl, mMirrorForRtl);

        if (a.hasValue(R.styleable.ProgressBar_progressTintMode)) {
            if (mProgressTintInfo == null) {
                mProgressTintInfo = new ProgressTintInfo();
            }
            mProgressTintInfo.mProgressTintMode = Drawable.parseTintMode(a.getInt(
                    R.styleable.ProgressBar_progressBackgroundTintMode, -1), null);
            mProgressTintInfo.mHasProgressTintMode = true;
        }

        if (a.hasValue(R.styleable.ProgressBar_progressTint)) {
            if (mProgressTintInfo == null) {
                mProgressTintInfo = new ProgressTintInfo();
            }
            mProgressTintInfo.mProgressTintList = a.getColorStateList(
                    R.styleable.ProgressBar_progressTint);
            mProgressTintInfo.mHasProgressTint = true;
        }

        if (a.hasValue(R.styleable.ProgressBar_progressBackgroundTintMode)) {
            if (mProgressTintInfo == null) {
                mProgressTintInfo = new ProgressTintInfo();
            }
            mProgressTintInfo.mProgressBackgroundTintMode = Drawable.parseTintMode(a.getInt(
                    R.styleable.ProgressBar_progressTintMode, -1), null);
            mProgressTintInfo.mHasProgressBackgroundTintMode = true;
        }

        if (a.hasValue(R.styleable.ProgressBar_progressBackgroundTint)) {
            if (mProgressTintInfo == null) {
                mProgressTintInfo = new ProgressTintInfo();
            }
            mProgressTintInfo.mProgressBackgroundTintList = a.getColorStateList(
                    R.styleable.ProgressBar_progressBackgroundTint);
            mProgressTintInfo.mHasProgressBackgroundTint = true;
        }

        if (a.hasValue(R.styleable.ProgressBar_secondaryProgressTintMode)) {
            if (mProgressTintInfo == null) {
                mProgressTintInfo = new ProgressTintInfo();
            }
            mProgressTintInfo.mSecondaryProgressTintMode = Drawable.parseTintMode(
                    a.getInt(R.styleable.ProgressBar_secondaryProgressTintMode, -1), null);
            mProgressTintInfo.mHasSecondaryProgressTintMode = true;
        }

        if (a.hasValue(R.styleable.ProgressBar_secondaryProgressTint)) {
            if (mProgressTintInfo == null) {
                mProgressTintInfo = new ProgressTintInfo();
            }
            mProgressTintInfo.mSecondaryProgressTintList = a.getColorStateList(
                    R.styleable.ProgressBar_secondaryProgressTint);
            mProgressTintInfo.mHasSecondaryProgressTint = true;
        }

        if (a.hasValue(R.styleable.ProgressBar_indeterminateTint)) {
            if (mProgressTintInfo == null) {
                mProgressTintInfo = new ProgressTintInfo();
            }
            mProgressTintInfo.mIndeterminateTintMode = Drawable.parseTintMode(a.getInt(
                    R.styleable.ProgressBar_indeterminateTintMode, -1), null);
            mProgressTintInfo.mHasIndeterminateTintMode = true;
        }

        if (a.hasValue(R.styleable.ProgressBar_indeterminateTint)) {
            if (mProgressTintInfo == null) {
                mProgressTintInfo = new ProgressTintInfo();
            }
            mProgressTintInfo.mIndeterminateTintList = a.getColorStateList(
                    R.styleable.ProgressBar_indeterminateTint);
            mProgressTintInfo.mHasIndeterminateTint = true;
        }

        a.recycle();

        applyProgressTints();
        applyIndeterminateTint();

        // If not explicitly specified this view is important for accessibility.
        if (getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
            setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
        }
    
Methods Summary
private voidapplyIndeterminateTint()

        if (mIndeterminateDrawable != null && mProgressTintInfo != null) {
            final ProgressTintInfo tintInfo = mProgressTintInfo;
            if (tintInfo.mHasIndeterminateTint || tintInfo.mHasIndeterminateTintMode) {
                mIndeterminateDrawable = mIndeterminateDrawable.mutate();

                if (tintInfo.mHasIndeterminateTint) {
                    mIndeterminateDrawable.setTintList(tintInfo.mIndeterminateTintList);
                }

                if (tintInfo.mHasIndeterminateTintMode) {
                    mIndeterminateDrawable.setTintMode(tintInfo.mIndeterminateTintMode);
                }

                // The drawable (or one of its children) may not have been
                // stateful before applying the tint, so let's try again.
                if (mIndeterminateDrawable.isStateful()) {
                    mIndeterminateDrawable.setState(getDrawableState());
                }
            }
        }
    
private voidapplyPrimaryProgressTint()
Should only be called if we've already verified that mProgressDrawable and mProgressTintInfo are non-null.

        if (mProgressTintInfo.mHasProgressTint
                || mProgressTintInfo.mHasProgressTintMode) {
            final Drawable target = getTintTarget(R.id.progress, true);
            if (target != null) {
                if (mProgressTintInfo.mHasProgressTint) {
                    target.setTintList(mProgressTintInfo.mProgressTintList);
                }
                if (mProgressTintInfo.mHasProgressTintMode) {
                    target.setTintMode(mProgressTintInfo.mProgressTintMode);
                }

                // The drawable (or one of its children) may not have been
                // stateful before applying the tint, so let's try again.
                if (target.isStateful()) {
                    target.setState(getDrawableState());
                }
            }
        }
    
private voidapplyProgressBackgroundTint()
Should only be called if we've already verified that mProgressDrawable and mProgressTintInfo are non-null.

        if (mProgressTintInfo.mHasProgressBackgroundTint
                || mProgressTintInfo.mHasProgressBackgroundTintMode) {
            final Drawable target = getTintTarget(R.id.background, false);
            if (target != null) {
                if (mProgressTintInfo.mHasProgressBackgroundTint) {
                    target.setTintList(mProgressTintInfo.mProgressBackgroundTintList);
                }
                if (mProgressTintInfo.mHasProgressBackgroundTintMode) {
                    target.setTintMode(mProgressTintInfo.mProgressBackgroundTintMode);
                }

                // The drawable (or one of its children) may not have been
                // stateful before applying the tint, so let's try again.
                if (target.isStateful()) {
                    target.setState(getDrawableState());
                }
            }
        }
    
private voidapplyProgressTints()
Applies the progress tints in order of increasing specificity.

        if (mProgressDrawable != null && mProgressTintInfo != null) {
            applyPrimaryProgressTint();
            applyProgressBackgroundTint();
            applySecondaryProgressTint();
        }
    
private voidapplySecondaryProgressTint()
Should only be called if we've already verified that mProgressDrawable and mProgressTintInfo are non-null.

        if (mProgressTintInfo.mHasSecondaryProgressTint
                || mProgressTintInfo.mHasSecondaryProgressTintMode) {
            final Drawable target = getTintTarget(R.id.secondaryProgress, false);
            if (target != null) {
                if (mProgressTintInfo.mHasSecondaryProgressTint) {
                    target.setTintList(mProgressTintInfo.mSecondaryProgressTintList);
                }
                if (mProgressTintInfo.mHasSecondaryProgressTintMode) {
                    target.setTintMode(mProgressTintInfo.mSecondaryProgressTintMode);
                }

                // The drawable (or one of its children) may not have been
                // stateful before applying the tint, so let's try again.
                if (target.isStateful()) {
                    target.setState(getDrawableState());
                }
            }
        }
    
private synchronized voiddoRefreshProgress(int id, int progress, boolean fromUser, boolean callBackToApp)

        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);
                if (progressDrawable != null && canResolveLayoutDirection()) {
                    progressDrawable.setLayoutDirection(getLayoutDirection());
                }
            }

            final int level = (int) (scale * MAX_LEVEL);
            (progressDrawable != null ? progressDrawable : d).setLevel(level);
        } else {
            invalidate();
        }
        
        if (callBackToApp && id == R.id.progress) {
            onProgressRefresh(scale, fromUser);
        }
    
voiddrawTrack(android.graphics.Canvas canvas)
Draws the progress bar track.

        final Drawable d = mCurrentDrawable;
        if (d != null) {
            // Translate canvas so a indeterminate circular progress bar with padding
            // rotates properly in its animation
            final int saveCount = canvas.save();

            if(isLayoutRtl() && mMirrorForRtl) {
                canvas.translate(getWidth() - mPaddingRight, mPaddingTop);
                canvas.scale(-1.0f, 1.0f);
            } else {
                canvas.translate(mPaddingLeft, mPaddingTop);
            }

            final long time = getDrawingTime();
            if (mHasAnimation) {
                mAnimation.getTransformation(time, mTransformation);
                final float scale = mTransformation.getAlpha();
                try {
                    mInDrawing = true;
                    d.setLevel((int) (scale * MAX_LEVEL));
                } finally {
                    mInDrawing = false;
                }
                postInvalidateOnAnimation();
            }

            d.draw(canvas);
            canvas.restoreToCount(saveCount);

            if (mShouldStartAnimationDrawable && d instanceof Animatable) {
                ((Animatable) d).start();
                mShouldStartAnimationDrawable = false;
            }
        }
    
public voiddrawableHotspotChanged(float x, float y)

        super.drawableHotspotChanged(x, y);

        if (mProgressDrawable != null) {
            mProgressDrawable.setHotspot(x, y);
        }

        if (mIndeterminateDrawable != null) {
            mIndeterminateDrawable.setHotspot(x, y);
        }
    
protected voiddrawableStateChanged()

        super.drawableStateChanged();
        updateDrawableState();
    
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.content.res.ColorStateListgetIndeterminateTintList()

return
the tint applied to the indeterminate drawable
attr
ref android.R.styleable#ProgressBar_indeterminateTint
see
#setIndeterminateTintList(ColorStateList)

        return mProgressTintInfo != null ? mProgressTintInfo.mIndeterminateTintList : null;
    
public android.graphics.PorterDuff.ModegetIndeterminateTintMode()
Returns the blending mode used to apply the tint to the indeterminate drawable, if specified.

return
the blending mode used to apply the tint to the indeterminate drawable
attr
ref android.R.styleable#ProgressBar_indeterminateTintMode
see
#setIndeterminateTintMode(PorterDuff.Mode)

        return mProgressTintInfo != null ? mProgressTintInfo.mIndeterminateTintMode : null;
    
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.content.res.ColorStateListgetProgressBackgroundTintList()
Returns the tint applied to the progress background, if specified.

return
the tint applied to the progress background
attr
ref android.R.styleable#ProgressBar_progressBackgroundTint
see
#setProgressBackgroundTintList(ColorStateList)

        return mProgressTintInfo != null ? mProgressTintInfo.mProgressBackgroundTintList : null;
    
public android.graphics.PorterDuff.ModegetProgressBackgroundTintMode()

return
the blending mode used to apply the tint to the progress background
attr
ref android.R.styleable#ProgressBar_progressBackgroundTintMode
see
#setProgressBackgroundTintMode(PorterDuff.Mode)

        return mProgressTintInfo != null ? mProgressTintInfo.mProgressBackgroundTintMode : null;
    
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 android.content.res.ColorStateListgetProgressTintList()
Returns the tint applied to the progress drawable, if specified.

return
the tint applied to the progress drawable
attr
ref android.R.styleable#ProgressBar_progressTint
see
#setProgressTintList(ColorStateList)

        return mProgressTintInfo != null ? mProgressTintInfo.mProgressTintList : null;
    
public android.graphics.PorterDuff.ModegetProgressTintMode()
Returns the blending mode used to apply the tint to the progress drawable, if specified.

return
the blending mode used to apply the tint to the progress drawable
attr
ref android.R.styleable#ProgressBar_progressTintMode
see
#setProgressTintMode(PorterDuff.Mode)

        return mProgressTintInfo != null ? mProgressTintInfo.mProgressTintMode : null;
    
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 android.content.res.ColorStateListgetSecondaryProgressTintList()
Returns the tint applied to the secondary progress drawable, if specified.

return
the tint applied to the secondary progress drawable
attr
ref android.R.styleable#ProgressBar_secondaryProgressTint
see
#setSecondaryProgressTintList(ColorStateList)

        return mProgressTintInfo != null ? mProgressTintInfo.mSecondaryProgressTintList : null;
    
public android.graphics.PorterDuff.ModegetSecondaryProgressTintMode()
Returns the blending mode used to apply the tint to the secondary progress drawable, if specified.

return
the blending mode used to apply the tint to the secondary progress drawable
attr
ref android.R.styleable#ProgressBar_secondaryProgressTintMode
see
#setSecondaryProgressTintMode(PorterDuff.Mode)

        return mProgressTintInfo != null ? mProgressTintInfo.mSecondaryProgressTintMode : null;
    
private android.graphics.drawable.DrawablegetTintTarget(int layerId, boolean shouldFallback)
Returns the drawable to which a tint or tint mode should be applied.

param
layerId id of the layer to modify
param
shouldFallback whether the base drawable should be returned if the id does not exist
return
the drawable to modify

        Drawable layer = null;

        final Drawable d = mProgressDrawable;
        if (d != null) {
            mProgressDrawable = d.mutate();

            if (d instanceof LayerDrawable) {
                layer = ((LayerDrawable) d).findDrawableByLayerId(layerId);
            }

            if (shouldFallback && layer == null) {
                layer = d;
            }
        }

        return layer;
    
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;
    
public voidjumpDrawablesToCurrentState()

        super.jumpDrawablesToCurrentState();
        if (mProgressDrawable != null) mProgressDrawable.jumpToCurrentState();
        if (mIndeterminateDrawable != null) mIndeterminateDrawable.jumpToCurrentState();
    
protected voidonAttachedToWindow()

        super.onAttachedToWindow();
        if (mIndeterminate) {
            startAnimation();
        }
        if (mRefreshData != null) {
            synchronized (this) {
                final int count = mRefreshData.size();
                for (int i = 0; i < count; i++) {
                    final RefreshData rd = mRefreshData.get(i);
                    doRefreshProgress(rd.id, rd.progress, rd.fromUser, true);
                    rd.recycle();
                }
                mRefreshData.clear();
            }
        }
        mAttached = true;
    
protected voidonDetachedFromWindow()

        if (mIndeterminate) {
            stopAnimation();
        }
        if (mRefreshProgressRunnable != null) {
            removeCallbacks(mRefreshProgressRunnable);
        }
        if (mRefreshProgressRunnable != null && mRefreshIsPosted) {
            removeCallbacks(mRefreshProgressRunnable);
        }
        if (mAccessibilityEventSender != null) {
            removeCallbacks(mAccessibilityEventSender);
        }
        // This should come after stopAnimation(), otherwise an invalidate message remains in the
        // queue, which can prevent the entire view hierarchy from being GC'ed during a rotation
        super.onDetachedFromWindow();
        mAttached = false;
    
protected synchronized voidonDraw(android.graphics.Canvas canvas)

        super.onDraw(canvas);

        drawTrack(canvas);
    
public voidonInitializeAccessibilityEvent(android.view.accessibility.AccessibilityEvent event)

        super.onInitializeAccessibilityEvent(event);
        event.setClassName(ProgressBar.class.getName());
        event.setItemCount(mMax);
        event.setCurrentItemIndex(mProgress);
    
public voidonInitializeAccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo info)

        super.onInitializeAccessibilityNodeInfo(info);
        info.setClassName(ProgressBar.class.getName());
    
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()));
        }
        updateDrawableState();
        dw += mPaddingLeft + mPaddingRight;
        dh += mPaddingTop + mPaddingBottom;

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

        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
            scheduleAccessibilityEventSender();
        }
    
public voidonResolveDrawables(int layoutDirection)

hide

        final Drawable d = mCurrentDrawable;
        if (d != null) {
            d.setLayoutDirection(layoutDirection);
        }
        if (mIndeterminateDrawable != null) {
            mIndeterminateDrawable.setLayoutDirection(layoutDirection);
        }
        if (mProgressDrawable != null) {
            mProgressDrawable.setLayoutDirection(layoutDirection);
        }
    
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)

        updateDrawableBounds(w, h);
    
protected voidonVisibilityChanged(android.view.View changedView, int visibility)

        super.onVisibilityChanged(changedView, visibility);

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

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

        if (mUiThreadId == Thread.currentThread().getId()) {
            doRefreshProgress(id, progress, fromUser, true);
        } else {
            if (mRefreshProgressRunnable == null) {
                mRefreshProgressRunnable = new RefreshProgressRunnable();
            }

            final RefreshData rd = RefreshData.obtain(id, progress, fromUser);
            mRefreshData.add(rd);
            if (mAttached && !mRefreshIsPosted) {
                post(mRefreshProgressRunnable);
                mRefreshIsPosted = true;
            }
        }
    
private voidscheduleAccessibilityEventSender()
Schedule a command for sending an accessibility event.
Note: A command is used to ensure that accessibility events are sent at most one in a given time frame to save system resources while the progress changes quickly.

        if (mAccessibilityEventSender == null) {
            mAccessibilityEventSender = new AccessibilityEventSender();
        } else {
            removeCallbacks(mAccessibilityEventSender);
        }
        postDelayed(mAccessibilityEventSender, TIMEOUT_SEND_ACCESSIBILITY_EVENT);
    
private voidsetDrawableTint(int id, android.content.res.ColorStateList tint, android.graphics.PorterDuff.Mode tintMode, boolean fallback)

        Drawable layer = null;

        // We expect a layer drawable, so try to find the target ID.
        final Drawable d = mCurrentDrawable;
        if (d instanceof LayerDrawable) {
            layer = ((LayerDrawable) d).findDrawableByLayerId(id);
        }

        if (fallback && layer == null) {
            layer = d;
        }

        layer.mutate();
        layer.setTintList(tint);
        layer.setTintMode(tintMode);
    
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 (mIndeterminateDrawable != d) {
            if (mIndeterminateDrawable != null) {
                mIndeterminateDrawable.setCallback(null);
                unscheduleDrawable(mIndeterminateDrawable);
            }

            mIndeterminateDrawable = d;

            if (d != null) {
                d.setCallback(this);
                d.setLayoutDirection(getLayoutDirection());
                if (d.isStateful()) {
                    d.setState(getDrawableState());
                }
                applyIndeterminateTint();
            }

            if (mIndeterminate) {
                mCurrentDrawable = d;
                postInvalidate();
            }
        }
    
public voidsetIndeterminateDrawableTiled(android.graphics.drawable.Drawable d)
Define the tileable drawable used to draw the progress bar in indeterminate mode.

If the drawable is a BitmapDrawable or contains BitmapDrawables, a tiled copy will be generated for display as a progress bar.

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

        if (d != null) {
            d = tileifyIndeterminate(d);
        }

        setIndeterminateDrawable(d);
    
public voidsetIndeterminateTintList(android.content.res.ColorStateList tint)
Applies a tint to the indeterminate drawable. Does not modify the current tint mode, which is {@link PorterDuff.Mode#SRC_IN} by default.

Subsequent calls to {@link #setIndeterminateDrawable(Drawable)} will automatically mutate the drawable and apply the specified tint and tint mode using {@link Drawable#setTintList(ColorStateList)}.

param
tint the tint to apply, may be {@code null} to clear tint
attr
ref android.R.styleable#ProgressBar_indeterminateTint
see
#getIndeterminateTintList()
see
Drawable#setTintList(ColorStateList)

        if (mProgressTintInfo == null) {
            mProgressTintInfo = new ProgressTintInfo();
        }
        mProgressTintInfo.mIndeterminateTintList = tint;
        mProgressTintInfo.mHasIndeterminateTint = true;

        applyIndeterminateTint();
    
public voidsetIndeterminateTintMode(android.graphics.PorterDuff.Mode tintMode)
Specifies the blending mode used to apply the tint specified by {@link #setIndeterminateTintList(ColorStateList)} to the indeterminate drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.

param
tintMode the blending mode used to apply the tint, may be {@code null} to clear tint
attr
ref android.R.styleable#ProgressBar_indeterminateTintMode
see
#setIndeterminateTintList(ColorStateList)
see
Drawable#setTintMode(PorterDuff.Mode)

        if (mProgressTintInfo == null) {
            mProgressTintInfo = new ProgressTintInfo();
        }
        mProgressTintInfo.mIndeterminateTintMode = tintMode;
        mProgressTintInfo.mHasIndeterminateTintMode = true;

        applyIndeterminateTint();
    
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;
            }
            refreshProgress(R.id.progress, mProgress, false);
        }
    
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 voidsetProgressBackgroundTintList(android.content.res.ColorStateList tint)
Applies a tint to the progress background, if one exists. Does not modify the current tint mode, which is {@link PorterDuff.Mode#SRC_ATOP} by default.

The progress background must be specified as a layer with id {@link android.R.id#background} in a {@link LayerDrawable} used as the progress drawable.

Subsequent calls to {@link #setProgressDrawable(Drawable)} where the drawable contains a progress background will automatically mutate the drawable and apply the specified tint and tint mode using {@link Drawable#setTintList(ColorStateList)}.

param
tint the tint to apply, may be {@code null} to clear tint
attr
ref android.R.styleable#ProgressBar_progressBackgroundTint
see
#getProgressBackgroundTintList()
see
Drawable#setTintList(ColorStateList)

        if (mProgressTintInfo == null) {
            mProgressTintInfo = new ProgressTintInfo();
        }
        mProgressTintInfo.mProgressBackgroundTintList = tint;
        mProgressTintInfo.mHasProgressBackgroundTint = true;

        if (mProgressDrawable != null) {
            applyProgressBackgroundTint();
        }
    
public voidsetProgressBackgroundTintMode(android.graphics.PorterDuff.Mode tintMode)
Specifies the blending mode used to apply the tint specified by {@link #setProgressBackgroundTintList(ColorStateList)}} to the progress background. The default mode is {@link PorterDuff.Mode#SRC_IN}.

param
tintMode the blending mode used to apply the tint, may be {@code null} to clear tint
attr
ref android.R.styleable#ProgressBar_progressBackgroundTintMode
see
#setProgressBackgroundTintList(ColorStateList)
see
Drawable#setTintMode(PorterDuff.Mode)

        if (mProgressTintInfo == null) {
            mProgressTintInfo = new ProgressTintInfo();
        }
        mProgressTintInfo.mProgressBackgroundTintMode = tintMode;
        mProgressTintInfo.mHasProgressBackgroundTintMode = true;

        if (mProgressDrawable != null) {
            applyProgressBackgroundTint();
        }
    
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 (mProgressDrawable != d) {
            if (mProgressDrawable != null) {
                mProgressDrawable.setCallback(null);
                unscheduleDrawable(mProgressDrawable);
            }

            mProgressDrawable = d;

            if (d != null) {
                d.setCallback(this);
                d.setLayoutDirection(getLayoutDirection());
                if (d.isStateful()) {
                    d.setState(getDrawableState());
                }

                // Make sure the ProgressBar is always tall enough
                int drawableHeight = d.getMinimumHeight();
                if (mMaxHeight < drawableHeight) {
                    mMaxHeight = drawableHeight;
                    requestLayout();
                }

                applyProgressTints();
            }

            if (!mIndeterminate) {
                mCurrentDrawable = d;
                postInvalidate();
            }

            updateDrawableBounds(getWidth(), getHeight());
            updateDrawableState();

            doRefreshProgress(R.id.progress, mProgress, false, false);
            doRefreshProgress(R.id.secondaryProgress, mSecondaryProgress, false, false);
        }
    
public voidsetProgressDrawableTiled(android.graphics.drawable.Drawable d)
Define the tileable drawable used to draw the progress bar in progress mode.

If the drawable is a BitmapDrawable or contains BitmapDrawables, a tiled copy will be generated for display as a progress bar.

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

        if (d != null) {
            d = tileify(d, false);
        }

        setProgressDrawable(d);
    
public voidsetProgressTintList(android.content.res.ColorStateList tint)
Applies a tint to the progress indicator, if one exists, or to the entire progress drawable otherwise. Does not modify the current tint mode, which is {@link PorterDuff.Mode#SRC_IN} by default.

The progress indicator should be specified as a layer with id {@link android.R.id#progress} in a {@link LayerDrawable} used as the progress drawable.

Subsequent calls to {@link #setProgressDrawable(Drawable)} will automatically mutate the drawable and apply the specified tint and tint mode using {@link Drawable#setTintList(ColorStateList)}.

param
tint the tint to apply, may be {@code null} to clear tint
attr
ref android.R.styleable#ProgressBar_progressTint
see
#getProgressTintList()
see
Drawable#setTintList(ColorStateList)

        if (mProgressTintInfo == null) {
            mProgressTintInfo = new ProgressTintInfo();
        }
        mProgressTintInfo.mProgressTintList = tint;
        mProgressTintInfo.mHasProgressTint = true;

        if (mProgressDrawable != null) {
            applyPrimaryProgressTint();
        }
    
public voidsetProgressTintMode(android.graphics.PorterDuff.Mode tintMode)
Specifies the blending mode used to apply the tint specified by {@link #setProgressTintList(ColorStateList)}} to the progress indicator. The default mode is {@link PorterDuff.Mode#SRC_IN}.

param
tintMode the blending mode used to apply the tint, may be {@code null} to clear tint
attr
ref android.R.styleable#ProgressBar_progressTintMode
see
#getProgressTintMode()
see
Drawable#setTintMode(PorterDuff.Mode)

        if (mProgressTintInfo == null) {
            mProgressTintInfo = new ProgressTintInfo();
        }
        mProgressTintInfo.mProgressTintMode = tintMode;
        mProgressTintInfo.mHasProgressTintMode = true;

        if (mProgressDrawable != null) {
            applyPrimaryProgressTint();
        }
    
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 voidsetSecondaryProgressTintList(android.content.res.ColorStateList tint)
Applies a tint to the secondary progress indicator, if one exists. Does not modify the current tint mode, which is {@link PorterDuff.Mode#SRC_ATOP} by default.

The secondary progress indicator must be specified as a layer with id {@link android.R.id#secondaryProgress} in a {@link LayerDrawable} used as the progress drawable.

Subsequent calls to {@link #setProgressDrawable(Drawable)} where the drawable contains a secondary progress indicator will automatically mutate the drawable and apply the specified tint and tint mode using {@link Drawable#setTintList(ColorStateList)}.

param
tint the tint to apply, may be {@code null} to clear tint
attr
ref android.R.styleable#ProgressBar_secondaryProgressTint
see
#getSecondaryProgressTintList()
see
Drawable#setTintList(ColorStateList)

        if (mProgressTintInfo == null) {
            mProgressTintInfo = new ProgressTintInfo();
        }
        mProgressTintInfo.mSecondaryProgressTintList = tint;
        mProgressTintInfo.mHasSecondaryProgressTint = true;

        if (mProgressDrawable != null) {
            applySecondaryProgressTint();
        }
    
public voidsetSecondaryProgressTintMode(android.graphics.PorterDuff.Mode tintMode)
Specifies the blending mode used to apply the tint specified by {@link #setSecondaryProgressTintList(ColorStateList)}} to the secondary progress indicator. The default mode is {@link PorterDuff.Mode#SRC_ATOP}.

param
tintMode the blending mode used to apply the tint, may be {@code null} to clear tint
attr
ref android.R.styleable#ProgressBar_secondaryProgressTintMode
see
#setSecondaryProgressTintList(ColorStateList)
see
Drawable#setTintMode(PorterDuff.Mode)

        if (mProgressTintInfo == null) {
            mProgressTintInfo = new ProgressTintInfo();
        }
        mProgressTintInfo.mSecondaryProgressTintMode = tintMode;
        mProgressTintInfo.mHasSecondaryProgressTintMode = true;

        if (mProgressDrawable != null) {
            applySecondaryProgressTint();
        }
    
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 {
                    startAnimation();
                }
            }
        }
    
voidstartAnimation()

Start the indeterminate progress animation.

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

        if (mIndeterminateDrawable instanceof Animatable) {
            mShouldStartAnimationDrawable = true;
            mHasAnimation = false;
        } else {
            mHasAnimation = true;

            if (mInterpolator == null) {
                mInterpolator = new LinearInterpolator();
            }
    
            if (mTransformation == null) {
                mTransformation = new Transformation();
            } else {
                mTransformation.clear();
            }
            
            if (mAnimation == null) {
                mAnimation = new AlphaAnimation(0.0f, 1.0f);
            } else {
                mAnimation.reset();
            }

            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.

        mHasAnimation = false;
        if (mIndeterminateDrawable instanceof Animatable) {
            ((Animatable) mIndeterminateDrawable).stop();
            mShouldStartAnimationDrawable = false;
        }
        postInvalidate();
    
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 BitmapDrawable bitmap = (BitmapDrawable) drawable;
            final Bitmap tileBitmap = bitmap.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);

            // Ensure the tint and filter are propagated in the correct order.
            shapeDrawable.setTintList(bitmap.getTint());
            shapeDrawable.setTintMode(bitmap.getTintMode());
            shapeDrawable.setColorFilter(bitmap.getColorFilter());

            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;
    
private voidupdateDrawableBounds(int w, int h)

        // onDraw will translate the canvas so we draw starting at 0,0.
        // Subtract out padding for the purposes of the calculations below.
        w -= mPaddingRight + mPaddingLeft;
        h -= mPaddingTop + mPaddingBottom;

        int right = w;
        int bottom = h;
        int top = 0;
        int left = 0;

        if (mIndeterminateDrawable != null) {
            // Aspect ratio logic does not apply to AnimationDrawables
            if (mOnlyIndeterminate && !(mIndeterminateDrawable instanceof AnimationDrawable)) {
                // Maintain aspect ratio. Certain kinds of animated drawables
                // get very confused otherwise.
                final int intrinsicWidth = mIndeterminateDrawable.getIntrinsicWidth();
                final int intrinsicHeight = mIndeterminateDrawable.getIntrinsicHeight();
                final float intrinsicAspect = (float) intrinsicWidth / intrinsicHeight;
                final float boundAspect = (float) w / h;
                if (intrinsicAspect != boundAspect) {
                    if (boundAspect > intrinsicAspect) {
                        // New width is larger. Make it smaller to match height.
                        final int width = (int) (h * intrinsicAspect);
                        left = (w - width) / 2;
                        right = left + width;
                    } else {
                        // New height is larger. Make it smaller to match width.
                        final int height = (int) (w * (1 / intrinsicAspect));
                        top = (h - height) / 2;
                        bottom = top + height;
                    }
                }
            }
            if (isLayoutRtl() && mMirrorForRtl) {
                int tempLeft = left;
                left = w - right;
                right = w - tempLeft;
            }
            mIndeterminateDrawable.setBounds(left, top, right, bottom);
        }
        
        if (mProgressDrawable != null) {
            mProgressDrawable.setBounds(0, 0, right, bottom);
        }
    
private voidupdateDrawableState()

        int[] state = getDrawableState();
        
        if (mProgressDrawable != null && mProgressDrawable.isStateful()) {
            mProgressDrawable.setState(state);
        }
        
        if (mIndeterminateDrawable != null && mIndeterminateDrawable.isStateful()) {
            mIndeterminateDrawable.setState(state);
        }
    
protected booleanverifyDrawable(android.graphics.drawable.Drawable who)

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