Drawable一共有六个静态方法来创建对象,以及Resources的getDrawable方法,其中getDrawable经常使用,传入id便可,不做阐述。
1.根据本地文件的路径来创建Drawable对象
public static Drawable createFromPath(String pathName) {
if (pathName == null) {
return null;
}
Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, pathName);
try {
Bitmap bm = BitmapFactory.decodeFile(pathName);
if (bm != null) {
return drawableFromBitmap(null, bm, null, null, null, pathName);
}
} finally {
Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
}
return null;
}
可以看到,这里返回的实质上是一个Drawable的子类BitmapDrawable,只能解析位图。
2根据Xml文件来创建Drawable对象,能够自己传入属性
public static Drawable createFromXmlInner(Resources r, XmlPullParser parser, AttributeSet attrs)
throws XmlPullParserException, IOException {
Drawable drawable;
final String name = parser.getName();
if (name.equals("selector")) {
drawable = new StateListDrawable();
} else if (name.equals("level-list")) {
drawable = new LevelListDrawable();
} else if (name.equals("layer-list")) {
drawable = new LayerDrawable();
} else if (name.equals("transition")) {
drawable = new TransitionDrawable();
} else if (name.equals("color")) {
drawable = new ColorDrawable();
} else if (name.equals("shape")) {
drawable = new GradientDrawable();
} else if (name.equals("scale")) {
drawable = new ScaleDrawable();
} else if (name.equals("clip")) {
drawable = new ClipDrawable();
} else if (name.equals("rotate")) {
drawable = new RotateDrawable();
} else if (name.equals("animated-rotate")) {
drawable = new AnimatedRotateDrawable();
} else if (name.equals("animation-list")) {
drawable = new AnimationDrawable();
} else if (name.equals("inset")) {
drawable = new InsetDrawable();
} else if (name.equals("bitmap")) {
//noinspection deprecation
drawable = new BitmapDrawable(r);
if (r != null) {
((BitmapDrawable) drawable).setTargetDensity(r.getDisplayMetrics());
}
} else if (name.equals("nine-patch")) {
drawable = new NinePatchDrawable();
if (r != null) {
((NinePatchDrawable) drawable).setTargetDensity(r.getDisplayMetrics());
}
} else {
throw new XmlPullParserException(parser.getPositionDescription() +
": invalid drawable tag " + name);
}
drawable.inflate(r, parser, attrs);
return drawable;
}
上面可以看到,xml的标签其实都对应一个drawable的实现子类,根据标签来填充具体的类,适用于复用性较强的地方,而且由于传入了AttributeSet参数,能够在代码中改变属性,灵活度较好,比下面的封装更具灵活性
3根据Xml文件来创建Drawable对象,任何地方调用该资源看到的结果都应该是一样的,属性固定,是上面方法的封装
public static Drawable createFromXml(Resources r, XmlPullParser parser)
throws XmlPullParserException, IOException {
AttributeSet attrs = Xml.asAttributeSet(parser);
int type;
while ((type=parser.next()) != XmlPullParser.START_TAG &&
type != XmlPullParser.END_DOCUMENT) {
// Empty loop
}
if (type != XmlPullParser.START_TAG) {
throw new XmlPullParserException("No start tag found");
}
Drawable drawable = createFromXmlInner(r, parser, attrs);
if (drawable == null) {
throw new RuntimeException("Unknown initial tag: " + parser.getName());
}
return drawable;
}
4.根据流来创建Drawable对象,传入了Bitmap的参数选项
public static Drawable createFromResourceStream(Resources res, TypedValue value,
InputStream is, String srcName, BitmapFactory.Options opts) {
if (is == null) {
return null;
}
/* ugh. The decodeStream contract is that we have already allocated
the pad rect, but if the bitmap does not had a ninepatch chunk,
then the pad will be ignored. If we could change this to lazily
alloc/assign the rect, we could avoid the GC churn of making new
Rects only to drop them on the floor.
*/
Rect pad = new Rect();
// Special stuff for compatibility mode: if the target density is not
// the same as the display density, but the resource -is- the same as
// the display density, then don't scale it down to the target density.
// This allows us to load the system's density-correct resources into
// an application in compatibility mode, without scaling those down
// to the compatibility density only to have them scaled back up when
// drawn to the screen.
if (opts == null) opts = new BitmapFactory.Options();
opts.inScreenDensity = res != null
? res.getDisplayMetrics().noncompatDensityDpi : DisplayMetrics.DENSITY_DEVICE;
Bitmap bm = BitmapFactory.decodeResourceStream(res, value, is, pad, opts);
if (bm != null) {
byte[] np = bm.getNinePatchChunk();
if (np == null || !NinePatch.isNinePatchChunk(np)) {
np = null;
pad = null;
}
int[] layoutBounds = bm.getLayoutBounds();
Rect layoutBoundsRect = null;
if (layoutBounds != null) {
layoutBoundsRect = new Rect(layoutBounds[0], layoutBounds[1],
layoutBounds[2], layoutBounds[3]);
}
return drawableFromBitmap(res, bm, np, pad, layoutBoundsRect, srcName);
}
return null;
}
其中value持有资源的属性
5.根据流来创建Drawable对象,传入了Bitmap的参数对象,但不用传入bitmap的参数选项,是上面方法的封装
public static Drawable createFromResourceStream(Resources res, TypedValue value,
InputStream is, String srcName) {
Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, srcName != null ? srcName : "Unknown drawable");
try {
return createFromResourceStream(res, value, is, srcName, null);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
}
}
6.根据流来创建Drawable对象,同样是第4个方法的封装
public static Drawable createFromStream(InputStream is, String srcName) {
Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, srcName != null ? srcName : "Unknown drawable");
try {
return createFromResourceStream(null, null, is, srcName, null);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
}
}