Drawable详解 一
博客专区 > 勿否 的博客 > 博客详情
Drawable详解 一
勿否 发表于3年前
Drawable详解 一
  • 发表于 3年前
  • 阅读 25
  • 收藏 0
  • 点赞 0
  • 评论 0

腾讯云 技术升级10大核心产品年终让利>>>   

摘要: 创建Drawable的几种方式

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


共有 人打赏支持
粉丝 0
博文 3
码字总数 1118
×
勿否
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: