Constructors Summary |
---|
public BitmapDrawable()Create an empty drawable, not dealing with density.
mBitmapState = new BitmapState((Bitmap) null);
|
public BitmapDrawable(android.content.res.Resources res)Create an empty drawable, setting initial target density based on
the display metrics of the resources.
mBitmapState = new BitmapState((Bitmap) null);
mBitmapState.mTargetDensity = mTargetDensity;
|
public BitmapDrawable(android.graphics.Bitmap bitmap)Create drawable from a bitmap, not dealing with density.
this(new BitmapState(bitmap), null);
|
public BitmapDrawable(android.content.res.Resources res, android.graphics.Bitmap bitmap)Create drawable from a bitmap, setting initial target density based on
the display metrics of the resources.
this(new BitmapState(bitmap), res);
mBitmapState.mTargetDensity = mTargetDensity;
|
public BitmapDrawable(String filepath)Create a drawable by opening a given file path and decoding the bitmap.
this(new BitmapState(BitmapFactory.decodeFile(filepath)), null);
if (mBitmapState.mBitmap == null) {
android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath);
}
|
public BitmapDrawable(android.content.res.Resources res, String filepath)Create a drawable by opening a given file path and decoding the bitmap.
this(new BitmapState(BitmapFactory.decodeFile(filepath)), null);
mBitmapState.mTargetDensity = mTargetDensity;
if (mBitmapState.mBitmap == null) {
android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath);
}
|
private BitmapDrawable(BitmapState 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.
mBitmapState = state;
initializeWithState(mBitmapState, res);
|
public BitmapDrawable(InputStream is)Create a drawable by decoding a bitmap from the given input stream.
this(new BitmapState(BitmapFactory.decodeStream(is)), null);
if (mBitmapState.mBitmap == null) {
android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is);
}
|
public BitmapDrawable(android.content.res.Resources res, InputStream is)Create a drawable by decoding a bitmap from the given input stream.
this(new BitmapState(BitmapFactory.decodeStream(is)), null);
mBitmapState.mTargetDensity = mTargetDensity;
if (mBitmapState.mBitmap == null) {
android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is);
}
|
Methods Summary |
---|
public void | applyTheme(android.content.res.Resources.Theme t)
super.applyTheme(t);
final BitmapState state = mBitmapState;
if (state == null || state.mThemeAttrs == null) {
return;
}
final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.BitmapDrawable);
try {
updateStateFromTypedArray(a);
} catch (XmlPullParserException e) {
throw new RuntimeException(e);
} finally {
a.recycle();
}
|
public boolean | canApplyTheme()
return mBitmapState != null && mBitmapState.mThemeAttrs != null;
|
public void | clearMutated()
super.clearMutated();
mMutated = false;
|
private void | computeBitmapSize()
final Bitmap bitmap = mBitmapState.mBitmap;
if (bitmap != null) {
mBitmapWidth = bitmap.getScaledWidth(mTargetDensity);
mBitmapHeight = bitmap.getScaledHeight(mTargetDensity);
} else {
mBitmapWidth = mBitmapHeight = -1;
}
|
public void | draw(android.graphics.Canvas canvas)
final Bitmap bitmap = mBitmapState.mBitmap;
if (bitmap == null) {
return;
}
final BitmapState state = mBitmapState;
final Paint paint = state.mPaint;
if (state.mRebuildShader) {
final Shader.TileMode tmx = state.mTileModeX;
final Shader.TileMode tmy = state.mTileModeY;
if (tmx == null && tmy == null) {
paint.setShader(null);
} else {
paint.setShader(new BitmapShader(bitmap,
tmx == null ? Shader.TileMode.CLAMP : tmx,
tmy == null ? Shader.TileMode.CLAMP : tmy));
}
state.mRebuildShader = false;
}
final int restoreAlpha;
if (state.mBaseAlpha != 1.0f) {
final Paint p = getPaint();
restoreAlpha = p.getAlpha();
p.setAlpha((int) (restoreAlpha * state.mBaseAlpha + 0.5f));
} else {
restoreAlpha = -1;
}
final boolean clearColorFilter;
if (mTintFilter != null && paint.getColorFilter() == null) {
paint.setColorFilter(mTintFilter);
clearColorFilter = true;
} else {
clearColorFilter = false;
}
updateDstRectAndInsetsIfDirty();
final Shader shader = paint.getShader();
final boolean needMirroring = needMirroring();
if (shader == null) {
if (needMirroring) {
canvas.save();
// Mirror the bitmap
canvas.translate(mDstRect.right - mDstRect.left, 0);
canvas.scale(-1.0f, 1.0f);
}
canvas.drawBitmap(bitmap, null, mDstRect, paint);
if (needMirroring) {
canvas.restore();
}
} else {
if (needMirroring) {
// Mirror the bitmap
updateMirrorMatrix(mDstRect.right - mDstRect.left);
shader.setLocalMatrix(mMirrorMatrix);
paint.setShader(shader);
} else {
if (mMirrorMatrix != null) {
mMirrorMatrix = null;
shader.setLocalMatrix(Matrix.IDENTITY_MATRIX);
paint.setShader(shader);
}
}
canvas.drawRect(mDstRect, paint);
}
if (clearColorFilter) {
paint.setColorFilter(null);
}
if (restoreAlpha >= 0) {
paint.setAlpha(restoreAlpha);
}
|
public int | getAlpha()
return mBitmapState.mPaint.getAlpha();
|
public final android.graphics.Bitmap | getBitmap()Returns the bitmap used by this drawable to render. May be null.
return mBitmapState.mBitmap;
|
public int | getChangingConfigurations()
return super.getChangingConfigurations() | mBitmapState.mChangingConfigurations;
|
public android.graphics.ColorFilter | getColorFilter()
return mBitmapState.mPaint.getColorFilter();
|
public final ConstantState | getConstantState()
mBitmapState.mChangingConfigurations = getChangingConfigurations();
return mBitmapState;
|
public int | getGravity()Get the gravity used to position/stretch the bitmap within its bounds.
See android.view.Gravity
return mBitmapState.mGravity;
|
public int | getIntrinsicHeight()
return mBitmapHeight;
|
public int | getIntrinsicWidth()
return mBitmapWidth;
|
public int | getOpacity()
if (mBitmapState.mGravity != Gravity.FILL) {
return PixelFormat.TRANSLUCENT;
}
final Bitmap bitmap = mBitmapState.mBitmap;
return (bitmap == null || bitmap.hasAlpha() || mBitmapState.mPaint.getAlpha() < 255) ?
PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE;
|
public android.graphics.Insets | getOpticalInsets()
updateDstRectAndInsetsIfDirty();
return mOpticalInsets;
|
public void | getOutline(android.graphics.Outline outline)
updateDstRectAndInsetsIfDirty();
outline.setRect(mDstRect);
// Only opaque Bitmaps can report a non-0 alpha,
// since only they are guaranteed to fill their bounds
boolean opaqueOverShape = mBitmapState.mBitmap != null
&& !mBitmapState.mBitmap.hasAlpha();
outline.setAlpha(opaqueOverShape ? getAlpha() / 255.0f : 0.0f);
|
public final android.graphics.Paint | getPaint()Returns the paint used to render this drawable.
return mBitmapState.mPaint;
|
public Shader.TileMode | getTileModeX()Indicates the repeat behavior of this drawable on the X axis.
return mBitmapState.mTileModeX;
|
public Shader.TileMode | getTileModeY()Indicates the repeat behavior of this drawable on the Y axis.
return mBitmapState.mTileModeY;
|
public android.content.res.ColorStateList | getTint()
return mBitmapState.mTint;
|
public android.graphics.PorterDuff.Mode | getTintMode()
return mBitmapState.mTintMode;
|
public boolean | hasAntiAlias()Indicates whether anti-aliasing is enabled for this drawable.
return mBitmapState.mPaint.isAntiAlias();
|
public boolean | hasMipMap()Indicates whether the mipmap hint is enabled on this drawable's bitmap.
return mBitmapState.mBitmap != null && mBitmapState.mBitmap.hasMipMap();
|
public void | inflate(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.BitmapDrawable);
updateStateFromTypedArray(a);
verifyState(a);
a.recycle();
|
private void | initializeWithState(android.graphics.drawable.BitmapDrawable$BitmapState 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.
if (res != null) {
mTargetDensity = res.getDisplayMetrics().densityDpi;
} else {
mTargetDensity = state.mTargetDensity;
}
mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
computeBitmapSize();
|
public final boolean | isAutoMirrored()
return mBitmapState.mAutoMirrored;
|
public boolean | isStateful()
final BitmapState s = mBitmapState;
return super.isStateful() || (s.mTint != null && s.mTint.isStateful());
|
public Drawable | mutate()A mutable BitmapDrawable still shares its Bitmap with any other Drawable
that comes from the same resource.
if (!mMutated && super.mutate() == this) {
mBitmapState = new BitmapState(mBitmapState);
mMutated = true;
}
return this;
|
private boolean | needMirroring()
return isAutoMirrored() && getLayoutDirection() == LayoutDirection.RTL;
|
protected void | onBoundsChange(android.graphics.Rect bounds)
mDstRectAndInsetsDirty = true;
final Shader shader = mBitmapState.mPaint.getShader();
if (shader != null) {
if (needMirroring()) {
updateMirrorMatrix(bounds.right - bounds.left);
shader.setLocalMatrix(mMirrorMatrix);
mBitmapState.mPaint.setShader(shader);
} else {
if (mMirrorMatrix != null) {
mMirrorMatrix = null;
shader.setLocalMatrix(Matrix.IDENTITY_MATRIX);
mBitmapState.mPaint.setShader(shader);
}
}
}
|
protected boolean | onStateChange(int[] stateSet)
final BitmapState state = mBitmapState;
if (state.mTint != null && state.mTintMode != null) {
mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
return true;
}
return false;
|
private static Shader.TileMode | parseTileMode(int tileMode)
switch (tileMode) {
case TILE_MODE_CLAMP:
return Shader.TileMode.CLAMP;
case TILE_MODE_REPEAT:
return Shader.TileMode.REPEAT;
case TILE_MODE_MIRROR:
return Shader.TileMode.MIRROR;
default:
return null;
}
|
public void | setAlpha(int alpha)
final int oldAlpha = mBitmapState.mPaint.getAlpha();
if (alpha != oldAlpha) {
mBitmapState.mPaint.setAlpha(alpha);
invalidateSelf();
}
|
public void | setAntiAlias(boolean aa)Enables or disables anti-aliasing for this drawable. Anti-aliasing affects
the edges of the bitmap only so it applies only when the drawable is rotated.
mBitmapState.mPaint.setAntiAlias(aa);
invalidateSelf();
|
public void | setAutoMirrored(boolean mirrored)
if (mBitmapState.mAutoMirrored != mirrored) {
mBitmapState.mAutoMirrored = mirrored;
invalidateSelf();
}
|
private void | setBitmap(android.graphics.Bitmap bitmap)
if (mBitmapState.mBitmap != bitmap) {
mBitmapState.mBitmap = bitmap;
computeBitmapSize();
invalidateSelf();
}
|
public void | setColorFilter(android.graphics.ColorFilter cf)
mBitmapState.mPaint.setColorFilter(cf);
invalidateSelf();
|
public void | setDither(boolean dither)
mBitmapState.mPaint.setDither(dither);
invalidateSelf();
|
public void | setFilterBitmap(boolean filter)
mBitmapState.mPaint.setFilterBitmap(filter);
invalidateSelf();
|
public void | setGravity(int gravity)Set the gravity used to position/stretch the bitmap within its bounds.
See android.view.Gravity
if (mBitmapState.mGravity != gravity) {
mBitmapState.mGravity = gravity;
mDstRectAndInsetsDirty = true;
invalidateSelf();
}
|
public void | setMipMap(boolean mipMap)Enables or disables the mipmap hint for this drawable's bitmap.
See {@link Bitmap#setHasMipMap(boolean)} for more information.
If the bitmap is null calling this method has no effect.
if (mBitmapState.mBitmap != null) {
mBitmapState.mBitmap.setHasMipMap(mipMap);
invalidateSelf();
}
|
public void | setTargetDensity(android.graphics.Canvas canvas)Set the density scale at which this drawable will be rendered. This
method assumes the drawable will be rendered at the same density as the
specified canvas.
setTargetDensity(canvas.getDensity());
|
public void | setTargetDensity(android.util.DisplayMetrics metrics)Set the density scale at which this drawable will be rendered.
setTargetDensity(metrics.densityDpi);
|
public void | setTargetDensity(int density)Set the density at which this drawable will be rendered.
if (mTargetDensity != density) {
mTargetDensity = density == 0 ? DisplayMetrics.DENSITY_DEFAULT : density;
if (mBitmapState.mBitmap != null) {
computeBitmapSize();
}
invalidateSelf();
}
|
public void | setTileModeX(Shader.TileMode mode)Sets the repeat behavior of this drawable on the X axis. By default, the drawable
does not repeat its bitmap. Using {@link android.graphics.Shader.TileMode#REPEAT} or
{@link android.graphics.Shader.TileMode#MIRROR} the bitmap can be repeated (or tiled)
if the bitmap is smaller than this drawable.
setTileModeXY(mode, mBitmapState.mTileModeY);
|
public void | setTileModeXY(Shader.TileMode xmode, Shader.TileMode ymode)Sets the repeat behavior of this drawable on both axis. By default, the drawable
does not repeat its bitmap. Using {@link android.graphics.Shader.TileMode#REPEAT} or
{@link android.graphics.Shader.TileMode#MIRROR} the bitmap can be repeated (or tiled)
if the bitmap is smaller than this drawable.
final BitmapState state = mBitmapState;
if (state.mTileModeX != xmode || state.mTileModeY != ymode) {
state.mTileModeX = xmode;
state.mTileModeY = ymode;
state.mRebuildShader = true;
mDstRectAndInsetsDirty = true;
invalidateSelf();
}
|
public final void | setTileModeY(Shader.TileMode mode)Sets the repeat behavior of this drawable on the Y axis. By default, the drawable
does not repeat its bitmap. Using {@link android.graphics.Shader.TileMode#REPEAT} or
{@link android.graphics.Shader.TileMode#MIRROR} the bitmap can be repeated (or tiled)
if the bitmap is smaller than this drawable.
setTileModeXY(mBitmapState.mTileModeX, mode);
|
public void | setTintList(android.content.res.ColorStateList tint)
mBitmapState.mTint = tint;
mTintFilter = updateTintFilter(mTintFilter, tint, mBitmapState.mTintMode);
invalidateSelf();
|
public void | setTintMode(android.graphics.PorterDuff.Mode tintMode)
mBitmapState.mTintMode = tintMode;
mTintFilter = updateTintFilter(mTintFilter, mBitmapState.mTint, tintMode);
invalidateSelf();
|
public void | setXfermode(android.graphics.Xfermode xfermode)
mBitmapState.mPaint.setXfermode(xfermode);
invalidateSelf();
|
private void | updateDstRectAndInsetsIfDirty()
if (mDstRectAndInsetsDirty) {
if (mBitmapState.mTileModeX == null && mBitmapState.mTileModeY == null) {
final Rect bounds = getBounds();
final int layoutDirection = getLayoutDirection();
Gravity.apply(mBitmapState.mGravity, mBitmapWidth, mBitmapHeight,
bounds, mDstRect, layoutDirection);
final int left = mDstRect.left - bounds.left;
final int top = mDstRect.top - bounds.top;
final int right = bounds.right - mDstRect.right;
final int bottom = bounds.bottom - mDstRect.bottom;
mOpticalInsets = Insets.of(left, top, right, bottom);
} else {
copyBounds(mDstRect);
mOpticalInsets = Insets.NONE;
}
}
mDstRectAndInsetsDirty = false;
|
private void | updateMirrorMatrix(float dx)
if (mMirrorMatrix == null) {
mMirrorMatrix = new Matrix();
}
mMirrorMatrix.setTranslate(dx, 0);
mMirrorMatrix.preScale(-1.0f, 1.0f);
|
private void | updateStateFromTypedArray(android.content.res.TypedArray a)Updates the constant state from the values in the typed array.
final Resources r = a.getResources();
final BitmapState state = mBitmapState;
// Account for any configuration changes.
state.mChangingConfigurations |= a.getChangingConfigurations();
// Extract the theme attributes, if any.
state.mThemeAttrs = a.extractThemeAttrs();
final int srcResId = a.getResourceId(R.styleable.BitmapDrawable_src, 0);
if (srcResId != 0) {
final Bitmap bitmap = BitmapFactory.decodeResource(r, srcResId);
if (bitmap == null) {
throw new XmlPullParserException(a.getPositionDescription() +
": <bitmap> requires a valid src attribute");
}
state.mBitmap = bitmap;
}
state.mTargetDensity = r.getDisplayMetrics().densityDpi;
final boolean defMipMap = state.mBitmap != null ? state.mBitmap.hasMipMap() : false;
setMipMap(a.getBoolean(R.styleable.BitmapDrawable_mipMap, defMipMap));
state.mAutoMirrored = a.getBoolean(
R.styleable.BitmapDrawable_autoMirrored, state.mAutoMirrored);
state.mBaseAlpha = a.getFloat(R.styleable.BitmapDrawable_alpha, state.mBaseAlpha);
final int tintMode = a.getInt(R.styleable.BitmapDrawable_tintMode, -1);
if (tintMode != -1) {
state.mTintMode = Drawable.parseTintMode(tintMode, Mode.SRC_IN);
}
final ColorStateList tint = a.getColorStateList(R.styleable.BitmapDrawable_tint);
if (tint != null) {
state.mTint = tint;
}
final Paint paint = mBitmapState.mPaint;
paint.setAntiAlias(a.getBoolean(
R.styleable.BitmapDrawable_antialias, paint.isAntiAlias()));
paint.setFilterBitmap(a.getBoolean(
R.styleable.BitmapDrawable_filter, paint.isFilterBitmap()));
paint.setDither(a.getBoolean(R.styleable.BitmapDrawable_dither, paint.isDither()));
setGravity(a.getInt(R.styleable.BitmapDrawable_gravity, state.mGravity));
final int tileMode = a.getInt(R.styleable.BitmapDrawable_tileMode, TILE_MODE_UNDEFINED);
if (tileMode != TILE_MODE_UNDEFINED) {
final Shader.TileMode mode = parseTileMode(tileMode);
setTileModeXY(mode, mode);
}
final int tileModeX = a.getInt(R.styleable.BitmapDrawable_tileModeX, TILE_MODE_UNDEFINED);
if (tileModeX != TILE_MODE_UNDEFINED) {
setTileModeX(parseTileMode(tileModeX));
}
final int tileModeY = a.getInt(R.styleable.BitmapDrawable_tileModeY, TILE_MODE_UNDEFINED);
if (tileModeY != TILE_MODE_UNDEFINED) {
setTileModeY(parseTileMode(tileModeY));
}
// Update local properties.
initializeWithState(state, r);
|
private void | verifyState(android.content.res.TypedArray a)Ensures all required attributes are set.
final BitmapState state = mBitmapState;
if (state.mBitmap == null) {
throw new XmlPullParserException(a.getPositionDescription() +
": <bitmap> requires a valid src attribute");
}
|