NinePatchDrawablepublic class NinePatchDrawable extends Drawable A resizeable bitmap, with stretchable areas that you define. This type of image
is defined in a .png file with a special format.
Developer Guides
For more information about how to use a NinePatchDrawable, read the
Canvas and Drawables developer guide. For information about creating a NinePatch image
file using the draw9patch tool, see the
Draw 9-patch tool guide. |
Fields Summary |
---|
private static final boolean | DEFAULT_DITHER | private NinePatchState | mNinePatchState | private android.graphics.NinePatch | mNinePatch | private android.graphics.PorterDuffColorFilter | mTintFilter | private android.graphics.Rect | mPadding | private android.graphics.Insets | mOpticalInsets | private android.graphics.Paint | mPaint | private boolean | mMutated | private int | mTargetDensity | private int | mBitmapWidth | private int | mBitmapHeight |
Constructors Summary |
---|
NinePatchDrawable()
mNinePatchState = new NinePatchState();
| public NinePatchDrawable(android.graphics.Bitmap bitmap, byte[] chunk, android.graphics.Rect padding, String srcName)Create drawable from raw nine-patch data, not dealing with density.
this(new NinePatchState(new NinePatch(bitmap, chunk, srcName), padding), null);
| public NinePatchDrawable(android.content.res.Resources res, android.graphics.Bitmap bitmap, byte[] chunk, android.graphics.Rect padding, String srcName)Create drawable from raw nine-patch data, setting initial target density
based on the display metrics of the resources.
this(new NinePatchState(new NinePatch(bitmap, chunk, srcName), padding), res);
mNinePatchState.mTargetDensity = mTargetDensity;
| public NinePatchDrawable(android.content.res.Resources res, android.graphics.Bitmap bitmap, byte[] chunk, android.graphics.Rect padding, android.graphics.Rect opticalInsets, String srcName)Create drawable from raw nine-patch data, setting initial target density
based on the display metrics of the resources.
this(new NinePatchState(new NinePatch(bitmap, chunk, srcName), padding, opticalInsets),
res);
mNinePatchState.mTargetDensity = mTargetDensity;
| private NinePatchDrawable(NinePatchState 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.
mNinePatchState = state;
initializeWithState(mNinePatchState, res);
| public NinePatchDrawable(android.graphics.NinePatch patch)Create drawable from existing nine-patch, not dealing with density.
this(new NinePatchState(patch, new Rect()), null);
| public NinePatchDrawable(android.content.res.Resources res, android.graphics.NinePatch patch)Create drawable from existing nine-patch, setting initial target density
based on the display metrics of the resources.
this(new NinePatchState(patch, new Rect()), res);
mNinePatchState.mTargetDensity = mTargetDensity;
|
Methods Summary |
---|
public void | applyTheme(android.content.res.Resources.Theme t)
super.applyTheme(t);
final NinePatchState state = mNinePatchState;
if (state == null || state.mThemeAttrs == null) {
return;
}
final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.NinePatchDrawable);
try {
updateStateFromTypedArray(a);
} catch (XmlPullParserException e) {
throw new RuntimeException(e);
} finally {
a.recycle();
}
| public boolean | canApplyTheme()
return mNinePatchState != null && mNinePatchState.mThemeAttrs != null;
| public void | clearMutated()
super.clearMutated();
mMutated = false;
| private void | computeBitmapSize()
final int sdensity = mNinePatch.getDensity();
final int tdensity = mTargetDensity;
if (sdensity == tdensity) {
mBitmapWidth = mNinePatch.getWidth();
mBitmapHeight = mNinePatch.getHeight();
mOpticalInsets = mNinePatchState.mOpticalInsets;
} else {
mBitmapWidth = Bitmap.scaleFromDensity(mNinePatch.getWidth(), sdensity, tdensity);
mBitmapHeight = Bitmap.scaleFromDensity(mNinePatch.getHeight(), sdensity, tdensity);
if (mNinePatchState.mPadding != null && mPadding != null) {
Rect dest = mPadding;
Rect src = mNinePatchState.mPadding;
if (dest == src) {
mPadding = dest = new Rect(src);
}
dest.left = Bitmap.scaleFromDensity(src.left, sdensity, tdensity);
dest.top = Bitmap.scaleFromDensity(src.top, sdensity, tdensity);
dest.right = Bitmap.scaleFromDensity(src.right, sdensity, tdensity);
dest.bottom = Bitmap.scaleFromDensity(src.bottom, sdensity, tdensity);
}
mOpticalInsets = scaleFromDensity(mNinePatchState.mOpticalInsets, sdensity, tdensity);
}
| public void | draw(android.graphics.Canvas canvas)
final Rect bounds = getBounds();
final boolean clearColorFilter;
if (mTintFilter != null && getPaint().getColorFilter() == null) {
mPaint.setColorFilter(mTintFilter);
clearColorFilter = true;
} else {
clearColorFilter = false;
}
final boolean needsMirroring = needsMirroring();
if (needsMirroring) {
// Mirror the 9patch
canvas.translate(bounds.right - bounds.left, 0);
canvas.scale(-1.0f, 1.0f);
}
final int restoreAlpha;
if (mNinePatchState.mBaseAlpha != 1.0f) {
restoreAlpha = mPaint.getAlpha();
mPaint.setAlpha((int) (restoreAlpha * mNinePatchState.mBaseAlpha + 0.5f));
} else {
restoreAlpha = -1;
}
mNinePatch.draw(canvas, bounds, mPaint);
if (clearColorFilter) {
mPaint.setColorFilter(null);
}
if (restoreAlpha >= 0) {
mPaint.setAlpha(restoreAlpha);
}
| public int | getAlpha()
if (mPaint == null) {
// Fast common case -- normal alpha.
return 0xFF;
}
return getPaint().getAlpha();
| public int | getChangingConfigurations()
return super.getChangingConfigurations() | mNinePatchState.mChangingConfigurations;
| public ConstantState | getConstantState()
mNinePatchState.mChangingConfigurations = getChangingConfigurations();
return mNinePatchState;
| public int | getIntrinsicHeight()Retrieves the height of the source .png file (before resizing).
return mBitmapHeight;
| public int | getIntrinsicWidth()Retrieves the width of the source .png file (before resizing).
return mBitmapWidth;
| public int | getMinimumHeight()
return mBitmapHeight;
| public int | getMinimumWidth()
return mBitmapWidth;
| public int | getOpacity()Returns a {@link android.graphics.PixelFormat graphics.PixelFormat}
value of OPAQUE or TRANSLUCENT.
return mNinePatch.hasAlpha() || (mPaint != null && mPaint.getAlpha() < 255) ?
PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE;
| public android.graphics.Insets | getOpticalInsets()
if (needsMirroring()) {
return Insets.of(mOpticalInsets.right, mOpticalInsets.top,
mOpticalInsets.left, mOpticalInsets.bottom);
} else {
return mOpticalInsets;
}
| public void | getOutline(android.graphics.Outline outline)
final Rect bounds = getBounds();
if (bounds.isEmpty()) return;
if (mNinePatchState != null) {
NinePatch.InsetStruct insets = mNinePatchState.mNinePatch.getBitmap().getNinePatchInsets();
if (insets != null) {
final Rect outlineInsets = insets.outlineRect;
outline.setRoundRect(bounds.left + outlineInsets.left,
bounds.top + outlineInsets.top,
bounds.right - outlineInsets.right,
bounds.bottom - outlineInsets.bottom,
insets.outlineRadius);
outline.setAlpha(insets.outlineAlpha * (getAlpha() / 255.0f));
return;
}
}
super.getOutline(outline);
| public boolean | getPadding(android.graphics.Rect padding)
final Rect scaledPadding = mPadding;
if (scaledPadding != null) {
if (needsMirroring()) {
padding.set(scaledPadding.right, scaledPadding.top,
scaledPadding.left, scaledPadding.bottom);
} else {
padding.set(scaledPadding);
}
return (padding.left | padding.top | padding.right | padding.bottom) != 0;
}
return false;
| public android.graphics.Paint | getPaint()
if (mPaint == null) {
mPaint = new Paint();
mPaint.setDither(DEFAULT_DITHER);
}
return mPaint;
| public android.graphics.Region | getTransparentRegion()
return mNinePatch.getTransparentRegion(getBounds());
| 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.NinePatchDrawable);
updateStateFromTypedArray(a);
a.recycle();
| private void | initializeWithState(android.graphics.drawable.NinePatchDrawable$NinePatchState state, android.content.res.Resources res)Initializes local dynamic properties from state.
if (res != null) {
mTargetDensity = res.getDisplayMetrics().densityDpi;
} else {
mTargetDensity = state.mTargetDensity;
}
// If we can, avoid calling any methods that initialize Paint.
if (state.mDither != DEFAULT_DITHER) {
setDither(state.mDither);
}
// Make a local copy of the padding.
if (state.mPadding != null) {
mPadding = new Rect(state.mPadding);
}
mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
setNinePatch(state.mNinePatch);
| public boolean | isAutoMirrored()
return mNinePatchState.mAutoMirrored;
| public boolean | isStateful()
final NinePatchState s = mNinePatchState;
return super.isStateful() || (s.mTint != null && s.mTint.isStateful());
| public Drawable | mutate()
if (!mMutated && super.mutate() == this) {
mNinePatchState = new NinePatchState(mNinePatchState);
mNinePatch = mNinePatchState.mNinePatch;
mMutated = true;
}
return this;
| private boolean | needsMirroring()
return isAutoMirrored() && getLayoutDirection() == LayoutDirection.RTL;
| protected boolean | onStateChange(int[] stateSet)
final NinePatchState state = mNinePatchState;
if (state.mTint != null && state.mTintMode != null) {
mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
return true;
}
return false;
| private static android.graphics.Insets | scaleFromDensity(android.graphics.Insets insets, int sdensity, int tdensity)
int left = Bitmap.scaleFromDensity(insets.left, sdensity, tdensity);
int top = Bitmap.scaleFromDensity(insets.top, sdensity, tdensity);
int right = Bitmap.scaleFromDensity(insets.right, sdensity, tdensity);
int bottom = Bitmap.scaleFromDensity(insets.bottom, sdensity, tdensity);
return Insets.of(left, top, right, bottom);
| public void | setAlpha(int alpha)
if (mPaint == null && alpha == 0xFF) {
// Fast common case -- leave at normal alpha.
return;
}
getPaint().setAlpha(alpha);
invalidateSelf();
| public void | setAutoMirrored(boolean mirrored)
mNinePatchState.mAutoMirrored = mirrored;
| public void | setColorFilter(android.graphics.ColorFilter cf)
if (mPaint == null && cf == null) {
// Fast common case -- leave at no color filter.
return;
}
getPaint().setColorFilter(cf);
invalidateSelf();
| public void | setDither(boolean dither)
//noinspection PointlessBooleanExpression
if (mPaint == null && dither == DEFAULT_DITHER) {
// Fast common case -- leave at default dither.
return;
}
getPaint().setDither(dither);
invalidateSelf();
| public void | setFilterBitmap(boolean filter)
getPaint().setFilterBitmap(filter);
invalidateSelf();
| private void | setNinePatch(android.graphics.NinePatch ninePatch)
if (mNinePatch != ninePatch) {
mNinePatch = ninePatch;
if (ninePatch != null) {
computeBitmapSize();
} else {
mBitmapWidth = mBitmapHeight = -1;
mOpticalInsets = Insets.NONE;
}
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 (density != mTargetDensity) {
mTargetDensity = density == 0 ? DisplayMetrics.DENSITY_DEFAULT : density;
if (mNinePatch != null) {
computeBitmapSize();
}
invalidateSelf();
}
| public void | setTintList(android.content.res.ColorStateList tint)
mNinePatchState.mTint = tint;
mTintFilter = updateTintFilter(mTintFilter, tint, mNinePatchState.mTintMode);
invalidateSelf();
| public void | setTintMode(android.graphics.PorterDuff.Mode tintMode)
mNinePatchState.mTintMode = tintMode;
mTintFilter = updateTintFilter(mTintFilter, mNinePatchState.mTint, tintMode);
invalidateSelf();
| 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 NinePatchState state = mNinePatchState;
// Account for any configuration changes.
state.mChangingConfigurations |= a.getChangingConfigurations();
// Extract the theme attributes, if any.
state.mThemeAttrs = a.extractThemeAttrs();
state.mDither = a.getBoolean(R.styleable.NinePatchDrawable_dither, state.mDither);
final int srcResId = a.getResourceId(R.styleable.NinePatchDrawable_src, 0);
if (srcResId != 0) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inDither = !state.mDither;
options.inScreenDensity = r.getDisplayMetrics().noncompatDensityDpi;
final Rect padding = new Rect();
final Rect opticalInsets = new Rect();
Bitmap bitmap = null;
try {
final TypedValue value = new TypedValue();
final InputStream is = r.openRawResource(srcResId, value);
bitmap = BitmapFactory.decodeResourceStream(r, value, is, padding, options);
is.close();
} catch (IOException e) {
// Ignore
}
if (bitmap == null) {
throw new XmlPullParserException(a.getPositionDescription() +
": <nine-patch> requires a valid src attribute");
} else if (bitmap.getNinePatchChunk() == null) {
throw new XmlPullParserException(a.getPositionDescription() +
": <nine-patch> requires a valid 9-patch source image");
}
bitmap.getOpticalInsets(opticalInsets);
state.mNinePatch = new NinePatch(bitmap, bitmap.getNinePatchChunk());
state.mPadding = padding;
state.mOpticalInsets = Insets.of(opticalInsets);
}
state.mAutoMirrored = a.getBoolean(
R.styleable.NinePatchDrawable_autoMirrored, state.mAutoMirrored);
state.mBaseAlpha = a.getFloat(R.styleable.NinePatchDrawable_alpha, state.mBaseAlpha);
final int tintMode = a.getInt(R.styleable.NinePatchDrawable_tintMode, -1);
if (tintMode != -1) {
state.mTintMode = Drawable.parseTintMode(tintMode, Mode.SRC_IN);
}
final ColorStateList tint = a.getColorStateList(R.styleable.NinePatchDrawable_tint);
if (tint != null) {
state.mTint = tint;
}
// Update local properties.
initializeWithState(state, r);
// Push density applied by setNinePatchState into state.
state.mTargetDensity = mTargetDensity;
|
|