FileDocCategorySizeDatePackage
ShapeDrawable.javaAPI DocAndroid 5.1 API19925Thu Mar 12 22:22:30 GMT 2015android.graphics.drawable

ShapeDrawable

public class ShapeDrawable extends Drawable
A Drawable object that draws primitive shapes. A ShapeDrawable takes a {@link android.graphics.drawable.shapes.Shape} object and manages its presence on the screen. If no Shape is given, then the ShapeDrawable will default to a {@link android.graphics.drawable.shapes.RectShape}.

This object can be defined in an XML file with the <shape> element.

Developer Guides

For more information about how to use ShapeDrawable, read the Canvas and Drawables document. For more information about defining a ShapeDrawable in XML, read the Drawable Resources document.

attr
ref android.R.styleable#ShapeDrawablePadding_left
attr
ref android.R.styleable#ShapeDrawablePadding_top
attr
ref android.R.styleable#ShapeDrawablePadding_right
attr
ref android.R.styleable#ShapeDrawablePadding_bottom
attr
ref android.R.styleable#ShapeDrawable_color
attr
ref android.R.styleable#ShapeDrawable_width
attr
ref android.R.styleable#ShapeDrawable_height

Fields Summary
private ShapeState
mShapeState
private android.graphics.PorterDuffColorFilter
mTintFilter
private boolean
mMutated
Constructors Summary
public ShapeDrawable()
ShapeDrawable constructor.

        this(new ShapeState(null), null);
    
public ShapeDrawable(android.graphics.drawable.shapes.Shape s)
Creates a ShapeDrawable with a specified Shape.

param
s the Shape that this ShapeDrawable should be

        this(new ShapeState(null), null);

        mShapeState.mShape = s;
    
private ShapeDrawable(ShapeState state, android.content.res.Resources res)
The one constructor to rule them all. This is called by all public constructors to set the state and initialize local properties.

        mShapeState = state;

        initializeWithState(state, res);
    
Methods Summary
public voidapplyTheme(android.content.res.Resources.Theme t)

        super.applyTheme(t);

        final ShapeState state = mShapeState;
        if (state == null || state.mThemeAttrs == null) {
            return;
        }

        final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.ShapeDrawable);
        updateStateFromTypedArray(a);
        a.recycle();

        // Update local properties.
        initializeWithState(state, t.getResources());
    
public voidclearMutated()

hide

        super.clearMutated();
        mMutated = false;
    
public voiddraw(android.graphics.Canvas canvas)

        final Rect r = getBounds();
        final ShapeState state = mShapeState;
        final Paint paint = state.mPaint;

        final int prevAlpha = paint.getAlpha();
        paint.setAlpha(modulateAlpha(prevAlpha, state.mAlpha));

        // only draw shape if it may affect output
        if (paint.getAlpha() != 0 || paint.getXfermode() != null || paint.hasShadowLayer()) {
            final boolean clearColorFilter;
            if (mTintFilter != null && paint.getColorFilter() == null) {
                paint.setColorFilter(mTintFilter);
                clearColorFilter = true;
            } else {
                clearColorFilter = false;
            }

            if (state.mShape != null) {
                // need the save both for the translate, and for the (unknown)
                // Shape
                final int count = canvas.save();
                canvas.translate(r.left, r.top);
                onDraw(state.mShape, canvas, paint);
                canvas.restoreToCount(count);
            } else {
                canvas.drawRect(r, paint);
            }

            if (clearColorFilter) {
                paint.setColorFilter(null);
            }
        }

        // restore
        paint.setAlpha(prevAlpha);
    
public intgetAlpha()

        return mShapeState.mAlpha;
    
public intgetChangingConfigurations()

        return super.getChangingConfigurations()
                | mShapeState.mChangingConfigurations;
    
public ConstantStategetConstantState()

        mShapeState.mChangingConfigurations = getChangingConfigurations();
        return mShapeState;
    
public intgetIntrinsicHeight()

        return mShapeState.mIntrinsicHeight;
    
public intgetIntrinsicWidth()

        return mShapeState.mIntrinsicWidth;
    
public intgetOpacity()

        if (mShapeState.mShape == null) {
            final Paint p = mShapeState.mPaint;
            if (p.getXfermode() == null) {
                final int alpha = p.getAlpha();
                if (alpha == 0) {
                    return PixelFormat.TRANSPARENT;
                }
                if (alpha == 255) {
                    return PixelFormat.OPAQUE;
                }
            }
        }
        // not sure, so be safe
        return PixelFormat.TRANSLUCENT;
    
public voidgetOutline(android.graphics.Outline outline)

        if (mShapeState.mShape != null) {
            mShapeState.mShape.getOutline(outline);
            outline.setAlpha(getAlpha() / 255.0f);
        }
    
public booleangetPadding(android.graphics.Rect padding)

        if (mShapeState.mPadding != null) {
            padding.set(mShapeState.mPadding);
            return true;
        } else {
            return super.getPadding(padding);
        }
    
public android.graphics.PaintgetPaint()
Returns the Paint used to draw the shape.

        return mShapeState.mPaint;
    
public android.graphics.drawable.ShapeDrawable$ShaderFactorygetShaderFactory()
Returns the ShaderFactory used by this ShapeDrawable for requesting a {@link android.graphics.Shader}.

        return mShapeState.mShaderFactory;
    
public android.graphics.drawable.shapes.ShapegetShape()
Returns the Shape of this ShapeDrawable.

        return mShapeState.mShape;
    
public voidinflate(android.content.res.Resources r, org.xmlpull.v1.XmlPullParser parser, android.util.AttributeSet attrs, android.content.res.Resources.Theme theme)

        super.inflate(r, parser, attrs, theme);

        final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.ShapeDrawable);
        updateStateFromTypedArray(a);
        a.recycle();

        int type;
        final int outerDepth = parser.getDepth();
        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
            if (type != XmlPullParser.START_TAG) {
                continue;
            }

            final String name = parser.getName();
            // call our subclass
            if (!inflateTag(name, r, parser, attrs)) {
                android.util.Log.w("drawable", "Unknown element: " + name +
                        " for ShapeDrawable " + this);
            }
        }

        // Update local properties.
        initializeWithState(mShapeState, r);
    
protected booleaninflateTag(java.lang.String name, android.content.res.Resources r, org.xmlpull.v1.XmlPullParser parser, android.util.AttributeSet attrs)
Subclasses override this to parse custom subelements. If you handle it, return true, else return super.inflateTag(...).


        if ("padding".equals(name)) {
            TypedArray a = r.obtainAttributes(attrs,
                    com.android.internal.R.styleable.ShapeDrawablePadding);
            setPadding(
                    a.getDimensionPixelOffset(
                            com.android.internal.R.styleable.ShapeDrawablePadding_left, 0),
                    a.getDimensionPixelOffset(
                            com.android.internal.R.styleable.ShapeDrawablePadding_top, 0),
                    a.getDimensionPixelOffset(
                            com.android.internal.R.styleable.ShapeDrawablePadding_right, 0),
                    a.getDimensionPixelOffset(
                            com.android.internal.R.styleable.ShapeDrawablePadding_bottom, 0));
            a.recycle();
            return true;
        }

        return false;
    
private voidinitializeWithState(android.graphics.drawable.ShapeDrawable$ShapeState state, android.content.res.Resources res)
Initializes local dynamic properties from state. This should be called after significant state changes, e.g. from the One True Constructor and after inflating or applying a theme.

        mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
    
public booleanisStateful()

        final ShapeState s = mShapeState;
        return super.isStateful() || (s.mTint != null && s.mTint.isStateful());
    
private static intmodulateAlpha(int paintAlpha, int alpha)

        int scale = alpha + (alpha >>> 7); // convert to 0..256
        return paintAlpha * scale >>> 8;
    
public Drawablemutate()

        if (!mMutated && super.mutate() == this) {
            if (mShapeState.mPaint != null) {
                mShapeState.mPaint = new Paint(mShapeState.mPaint);
            } else {
                mShapeState.mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            }
            if (mShapeState.mPadding != null) {
                mShapeState.mPadding = new Rect(mShapeState.mPadding);
            } else {
                mShapeState.mPadding = new Rect();
            }
            try {
                mShapeState.mShape = mShapeState.mShape.clone();
            } catch (CloneNotSupportedException e) {
                return null;
            }
            mMutated = true;
        }
        return this;
    
protected voidonBoundsChange(android.graphics.Rect bounds)

        super.onBoundsChange(bounds);
        updateShape();
    
protected voidonDraw(android.graphics.drawable.shapes.Shape shape, android.graphics.Canvas canvas, android.graphics.Paint paint)
Called from the drawable's draw() method after the canvas has been set to draw the shape at (0,0). Subclasses can override for special effects such as multiple layers, stroking, etc.

        shape.draw(canvas, paint);
    
protected booleanonStateChange(int[] stateSet)

        final ShapeState state = mShapeState;
        if (state.mTint != null && state.mTintMode != null) {
            mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
            return true;
        }
        return false;
    
public voidsetAlpha(int alpha)
Set the alpha level for this drawable [0..255]. Note that this drawable also has a color in its paint, which has an alpha as well. These two values are automatically combined during drawing. Thus if the color's alpha is 75% (i.e. 192) and the drawable's alpha is 50% (i.e. 128), then the combined alpha that will be used during drawing will be 37.5% (i.e. 96).

        mShapeState.mAlpha = alpha;
        invalidateSelf();
    
public voidsetColorFilter(android.graphics.ColorFilter cf)

        mShapeState.mPaint.setColorFilter(cf);
        invalidateSelf();
    
public voidsetDither(boolean dither)

        mShapeState.mPaint.setDither(dither);
        invalidateSelf();
    
public voidsetIntrinsicHeight(int height)
Sets the intrinsic (default) height for this shape.

param
height the intrinsic height (in pixels)

        mShapeState.mIntrinsicHeight = height;
        invalidateSelf();
    
public voidsetIntrinsicWidth(int width)
Sets the intrinsic (default) width for this shape.

param
width the intrinsic width (in pixels)

        mShapeState.mIntrinsicWidth = width;
        invalidateSelf();
    
public voidsetPadding(int left, int top, int right, int bottom)
Sets padding for the shape.

param
left padding for the left side (in pixels)
param
top padding for the top (in pixels)
param
right padding for the right side (in pixels)
param
bottom padding for the bottom (in pixels)

        if ((left | top | right | bottom) == 0) {
            mShapeState.mPadding = null;
        } else {
            if (mShapeState.mPadding == null) {
                mShapeState.mPadding = new Rect();
            }
            mShapeState.mPadding.set(left, top, right, bottom);
        }
        invalidateSelf();
    
public voidsetPadding(android.graphics.Rect padding)
Sets padding for this shape, defined by a Rect object. Define the padding in the Rect object as: left, top, right, bottom.

        if (padding == null) {
            mShapeState.mPadding = null;
        } else {
            if (mShapeState.mPadding == null) {
                mShapeState.mPadding = new Rect();
            }
            mShapeState.mPadding.set(padding);
        }
        invalidateSelf();
    
public voidsetShaderFactory(android.graphics.drawable.ShapeDrawable$ShaderFactory fact)
Sets a ShaderFactory to which requests for a {@link android.graphics.Shader} object will be made.

param
fact an instance of your ShaderFactory implementation

        mShapeState.mShaderFactory = fact;
    
public voidsetShape(android.graphics.drawable.shapes.Shape s)
Sets the Shape of this ShapeDrawable.

        mShapeState.mShape = s;
        updateShape();
    
public voidsetTintList(android.content.res.ColorStateList tint)

        mShapeState.mTint = tint;
        mTintFilter = updateTintFilter(mTintFilter, tint, mShapeState.mTintMode);
        invalidateSelf();
    
public voidsetTintMode(android.graphics.PorterDuff.Mode tintMode)

        mShapeState.mTintMode = tintMode;
        mTintFilter = updateTintFilter(mTintFilter, mShapeState.mTint, tintMode);
        invalidateSelf();
    
private voidupdateShape()

        if (mShapeState.mShape != null) {
            final Rect r = getBounds();
            final int w = r.width();
            final int h = r.height();

            mShapeState.mShape.resize(w, h);
            if (mShapeState.mShaderFactory != null) {
                mShapeState.mPaint.setShader(mShapeState.mShaderFactory.resize(w, h));
            }
        }
        invalidateSelf();
    
private voidupdateStateFromTypedArray(android.content.res.TypedArray a)

        final ShapeState state = mShapeState;
        final Paint paint = state.mPaint;

        // Account for any configuration changes.
        state.mChangingConfigurations |= a.getChangingConfigurations();

        // Extract the theme attributes, if any.
        state.mThemeAttrs = a.extractThemeAttrs();

        int color = paint.getColor();
        color = a.getColor(R.styleable.ShapeDrawable_color, color);
        paint.setColor(color);

        boolean dither = paint.isDither();
        dither = a.getBoolean(R.styleable.ShapeDrawable_dither, dither);
        paint.setDither(dither);

        setIntrinsicWidth((int) a.getDimension(
                R.styleable.ShapeDrawable_width, state.mIntrinsicWidth));
        setIntrinsicHeight((int) a.getDimension(
                R.styleable.ShapeDrawable_height, state.mIntrinsicHeight));

        final int tintMode = a.getInt(R.styleable.ShapeDrawable_tintMode, -1);
        if (tintMode != -1) {
            state.mTintMode = Drawable.parseTintMode(tintMode, Mode.SRC_IN);
        }

        final ColorStateList tint = a.getColorStateList(R.styleable.ShapeDrawable_tint);
        if (tint != null) {
            state.mTint = tint;
        }