drawable基本概念

drawable表示可以在canvas(画布)中进行绘制的抽象概念,是个抽象类。

  • 创建
  • 在res/drawable/目录下新建XML文件,使用自定义drawable对应标签创建drawable,如

res/drawable/filename.xml
文件名用作资源 ID

  • 也可以直接通过代码创建drawable对象,但这方式使用起来比较复杂
  • drawable大小和内容宽高
  • 首先,不是所有drawable都有内部宽高,像图片形成的BitmapDrawable内部宽高就是图片实际宽高,而其他的如颜色形成的,是没有内部宽高的,也没什么意义。
  • drawable很多时候如作为背景为适应所在view尺寸会拉伸或缩小,这时候的尺寸是drawable的大小,没有内部宽高
  • 资源引用
    这部分直接从官方文档中摘录过来如下:

在Java中:R.drawable.filename
在XML中:@[package:]drawable/filename

10种具体Drawable类

1. BitmapDrawable

bitmap标签

android:src直接引用图片即可。

  • 重要属性
  • antialias图片抗锯齿功能,能让图片变得平滑,但也会在一定程度降低图片清晰度
  • dither抖动功能,开启后,能使图片在高分辨率或低分辨率屏幕上都能保持很好的显示效果
  • filter过滤功能,开启后能使图片在拉伸或压缩时都能保持很好的显示效果
  • mipmap纹理映射,不常用一般设为false
  • tileMode平铺模式,有四种选择:disabled,repeat,clamp,mirror。其中clamp最特别,表示图片四周的像素会扩展到周围区域。

2. NinepatchDrawable

nine_patch标签

都是android:src直接引用图片即可,表示一张.9格式的图片,能根据所需的宽高进行不失真缩放。在使用上和BitmapDrawable基本是一致的。

3. ShapeDrawable

shape标签

  • 重要属性:
  • padding子属性,竟然是view相对屏幕的边距,设置了之后对布局上的所有view都起效
  • stroke指描边,即边缘线。

仅当 android:shape=”ring”时, 才使用以下属性(官方文档):

  • android:innerRadius
    尺寸。环内部(中间的孔)的半径,以尺寸值或尺寸资源表示。
  • android:innerRadiusRatio
    浮点型。环内部的半径,以环宽度的比率表示。例如,如果 android:innerRadiusRatio=”5”,则内半径等于环宽度除以 5。此值被 android:innerRadius 覆盖。默认值为 9。
  • android:thickness
    尺寸。环的厚度,以尺寸值或尺寸资源表示。
  • android:thicknessRatio
    浮点型。环的厚度,表示为环宽度的比率。例如,如果 android:thicknessRatio=”2”,则厚度等于环宽度除以 2。此值被 android:innerRadius 覆盖。默认值为 3。
  • android:useLevel
    布尔值。如果这用作 LevelListDrawable,则此值为“true”。这通常应为“false”,否则形状不会显示。

记录一次bug
刚才在AS上写了一个ShapeDrawable做测试,android.type设置成“linear”和“sweep”都能正常显示,但设置成“radial”( 径向渐变,起始颜色为中心颜色。)时,程序崩溃了,直接闪退。
初学时易犯这种错误,后来我才发现在使用“radial”时,一定要同时设置属性“android:gradientRadius”才行,否则直接闪退,无法显示。可以理解为二者是绑定在一起的,radial属性的初始化需要指定gradientRadius才行。

类似“radial”使用,当设置android:shape=”ring”时,一定要同时设置ring的专属属性,不然同样无法显示。使用专属属性时需要注意的是:

  • android:useLevel一定要设置,不用作 LevelListDrawable的话 一般为false
  • 圆环内半径android:innerRadius/android:innnerRadiusRadio和圆环厚度android:thickness/android:thicknessRadio每一种都至少设置一个,当圆环内半径的两种属性同时设置时,以前一种android:innerRadius为准,圆环厚度亦同。
  • android:innerRadius和android:thickness的值是Xdp,而android:innnerRadiusRadio和android:thicknessRadio分别表示内半径和厚度占drawable宽度(由于drawable作为背景一般会自适应view的宽和高,所以可以理解为所在view的宽度)的比例,是个int值。

4. LayerDrawable

layer-list标签

不同层的drawable用item子项表示。下面的item会覆盖上面的item,从而实现叠加效果。

5. StateListDrawable

selector标签

  • 表示drawable集合,每一种drawable对应于view的一种状态。constantSize固有大小是否不随着状态的改变而改变,一般设为false;variablePadding表示padding是否随着状态的改变而改变,一般设为false。
  • 系统根据当前view状态,会从上到下对item中的drawable进行匹配,类似于switch语句中default的作用,最后一个item不设置任何匹配状态,因此可以匹配任何状态,也就是除了上面可匹配状态之外的所有状态都使用最后一个item,相当于加了一份保证,不至于某种状态下找不到drawable。

6. LevelListDrawable

level-list标签

这个比较好理解,和statelistdrawable类似,也是表示drawable集合,由一个个子项item表示,每个item对应一定范围的level,由属性maxLevel、minLevel限定上下界。等级最大为1000,最小等级默认值是0。

  • 用作view背景时,通过drawable的setLevel方法通过设置等级来切换不同的drawable
  • 用作view前景时,通过drawable的setImageLevel方法来切换drawable

7. TransitionDrawable

transition标签,表示过渡效果。

每个子项item依然有left\right\top\bottom这些表示drawable四周偏移量的属性。

  • startTransition(int durationMillis)开启淡入淡出效果,即下面的item淡入到上面的item之上。
  • durationMillis表示过渡时长。
  • reverseTransition(int duration)实现逆过程。

8. InsetDrawable

inset标签,将其他drawable内嵌到自己当中,并且可以在四周留出一定边距。

9. ScaleDrawable

scale标签,根据自己的等级将指定的Drawable缩放到一定比例。

  • 缩放效果受宽高缩放比例和等级的共同影响。
  • 缩放效果与level的关系:等级范围为0-10000,默认值为0;等级越大,缩放效果越不明显,drawable看起来就越大,反之亦然。等级为0时,drawable不可见;等级为10000时没有缩放效果。
  • 与缩放比例的关系:scaleWidth\scaleHeight分别为宽、高的缩放比例。缩放比例越大,drawable看起来越小。

注意:使用ScaleDrawable时,一定要使用.setLevel()方法设置等级在1-10000之间,不然drawable不可见。另外,等级当设为10000以上的值时,也能正常工作,但不推荐这样做,因为系统约定等级范围在0-10000之间。

10. ClipDrawable

clip标签,根据等级来裁剪另一个Drawable。

  • 裁剪方向由android:clipOrientation和android:gravity共同决定,clipOrientation共有vertical、horizontal两种。
  • gravity根据其裁剪特点可分为四类:
  • top、bottom、left、right都是从相反方向开始裁剪,其中top、bottom与vertical配合使用,left、right与horizontal配合使用,这种配合想来也很自然。
  • center、center_vertical、center_horizontal:匹配gravity方向,从上下或左右同时裁剪。
  • fill_vertical、fill_horizontal、fill:前两种在gravity方向上填充容器,fill 是在水平和竖直方向上都同时填充;而且只有当等级为0时才能裁剪。
  • clip_vertical、clip_horizoncal:都是附加选项,表示gravity方向上的裁剪,但较少使用。

注意:裁剪效果也与level相关,等级0表示完全裁剪;等级10000表示不裁剪。“等级/10000”相当于裁剪过后的图片相比原图片的保留比例。

总结

  • TransitionDrawable、ScaleDrawable、ClipDrawable都具有等级level属性,都需要在加载该Drawable的Activity中添加相关执行代码,对Drawable进行相关设置。

根据XML特点:

  • BitmapDrawable、ScaleDrawable、ClipDrawable只有设置自身的属性
  • ShapeDrawable、LayerDrawable、StateListDrawable、LevelListDrawable、TransitionDrawable、InsetDrawable除了自身属性,还有子项属性,其中
  • LayerDrawable、StateListDrawable、LevelListDrawable、TransitionDrawable设置item子项
  • ShapeDrawable设置如corners之类的子属性
  • InsetDrawable内部可以设置shape子项,用以表示drawable

自定义Drawable

Drawable使用场景:

  • 作为ImageView中的图像来显示
  • 作为view的背景,第二种情况居多。

自定义view时必须要实现的方法

  • draw()
  • setAlpha()设置透明度
  • setColorFilter()
  • getOpacity()设置不透明度

其中draw是最主要的方法。

注意:自定义drawable无法在XML中使用