Drawable源码分析及自定义
表现¶
drawable可以是图片文件,也可以是xml,常用于背景,ImageView等- 代码中修改背景支持直接使用id设置,也支持使用
Drawable对象设置 - 通常使用
context.getResourse().getDrawable(int resid)的方式去获取Drawable对象,断点时可以发现不同的资源产生的Drawable类型不同
疑问¶
- 为何可以对一个view设置
background属性,设置drawable文件就可以使其能够显示一个图像 - 当drawable设置为图片,或xml文件时,结果会变得不一样,底层是如何处理的
- 假如当前使用了
shape标签,直接在标签内定义的属性,及内部定义的标签如何被解析
源码探索¶
从源头getDrawable()开始¶
给一个View设置背景最常用的方法view.setBackground(Drawable drawable)一定不陌生,当我们想使用存放在drawable目录下的资源时,通常使用context.getResourse().getDrawable(int resid)的方式去获取,深入以下具体实现
loadDrawable¶
createFromXmlForDensity¶
inflate¶
到这一步代码已经没法在sdk中查看了,剩余的代码在sdk内,继续分析
http://aospxref.com/android-13.0.0_r3/xref/frameworks/base/graphics/java/android/graphics/drawable/DrawableInflater.java#89

可以看到实际原生也是使用的xml标签解析,不同的xml对应不同类型的drawable实现,这里基本已经包含了所有的自带drawable了
系统还有部分其他Drawable,不支持标签使用,常用于代码使用,比如PaintDrawable,ShapeDrawable等等
<shape>标签及其实现¶
通过这种写法,可以生成一个颜色为暗蓝色的背景,那么它是如何知道我们设置的颜色,并绘制出来呢
Android中的自定义标签一般会预先定义在
attr文件内,根据其描述及其解析位置,可以找寻到其实现类
通过选中android:color属性,找到以下源码
源码干脆直接说明该属性被GradientDrawable使用 基于第四部中的标签对照,确实该标签对应的实现类为GradientDrawable
GradientDrawable¶
当我们使用shape标签时,将会创建一个GradientDrawable对象用于绘制,那么除了attr之外,还有一些内部标签是怎么解析的呢
其它细节¶
- inflate方法是在创建后最先调用的方法,部分初始化逻辑可以放在这里
- 在通过xml创建时,存在创建失败的情况,如不存在的标签,此时会走另一个方法进行创建,提供了可扩展性

当标签为drawable且存在class属性时,尝试使用class内容初始化,否则使用标签名初始化
流程总结¶

自定义阴影drawable¶
原生elevation不支持所有版本,颜色修改也有版本限制 原生elevation光源固定,导致不同屏幕位置的控件,阴影效果不完全相同
定义基类¶
矩形阴影实现类,可定义圆角¶
path阴影实现类,可使用vectordrawable的path¶
使用方式¶
使用drawable标签+class属性自定义
使用自定义标签
效果¶
