Android中的Drawable
Drawable
表示的是一种可以在Canvas
上进行绘制的抽象的概念,它的种类有很多,最常见的颜色和图片都可以是一个Drawable
。
Drawable
在开发中有着自己的优点:首先,它使用简单,比自定义View
的成本要低;其次,非图片类型的Drawable
占用空间较小,这对减少apk
的大小也很有帮助。
1. Drawable简介
Drawable
有很多种,它们都表示一种图像的概念,但是它们又不全是图片,通过颜色也可以构造出各式各样的图像的效果。在Android
的设计中,Drawable
是一个抽象类,它是所有Drawable
对象的基类,每个具体的Drawable
都是它的子类,比如ShapeDrawable
,BitmapDrawable
等。
Drawable
的内部宽/高这个参数比较重要,通过getIntrinsicWidth
和getIntrinsicHeight
这两个方法可以获取到它们。但是并不是所有的Drawable
都有内部宽/高,比如一张图片所形成的的Drawable
,它的内部宽/高就是图片的宽/高,但是一个颜色所形成的Drawable
,它就没有内部宽/高的概念。另外需要注意的是,Drawable
的内部宽/高不等同于它的大小,一般来说,Drawable
是没有大小概念的,当用作View
的背景时,Drawable
会被拉伸至View
的同等大小。
2. Drawable的分类
1. BitmapDrawable
这几乎是最简单的Drawable
了,它表示的就是一张图片。在实际开发中,我们可以直接引用原始的图片即可,但是也可以通过XML
的方式来描述它,通过XML
来描述的BitmapDrawable
可以设置更多的效果。
<?xml version="1.0" encoding="utf-8"?>
<bitmap
xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/mainback"
android:antialias="true"
android:dither="true"
android:filter="true"
android:gravity="center"
android:mipMap="false"
android:tileMode="repeat"/>
android:src
图片的资源id
android:antialias
是否开启图片抗锯齿功能。开启后会让图片变得平滑,同时也会在一定程度上降低图片的清晰度,但是这个降低的幅度较低以至于可以忽略,因此抗锯齿选项应该开启。
android:dither
是否开启抖动效果。当图片的像素配置和手机屏幕的像素配置不一致时,开启这个选项可以让高质量的图片在低质量的屏幕上还能保持较好的显示效果。在Android
中设置的Bitmap
一般会选用ARGB8888
这个模式,即ARGB
四个通道各占8位,在这种色彩模式下,一个像素所占的大小为4个字节,一个像素的位数总和越高,图像也就越逼真。
android:filter
是否开启过滤效果,当图片尺寸被拉伸或者压缩时,开启过滤效果可以保持较好的显示效果,因此此选项也应该开启。
android:gravity
当图片小于屏幕的尺寸时,设置此选项可以对图片进行定位。这个属性的可选项比较多,不同的选项可以通过|
来组合使用。
android:mipMap
这是一种图像相关的处理技术,也叫纹理映射,比较抽象,默认值为false,在日常开发中此选项不常用。
android:tileMode
平铺模式。这个选项有如下几个值:repeat
,mirror
,clamp
,disabled
。其中disabled
表示关闭平铺模式,这也是默认值。repeat
表示的是简单的水平和竖直方向上的平铺效果;mirror
表示一种在水平和竖直方向上的镜面投影效果;clamp
表示的效果就更加奇特,图片四周的像素会拓展到周围区域。
NinePatchDrawable
它表示的是一张.9
格式的图片,.9
图片可以自动地根据所需的宽/高进行相应的缩放,并保证不失真,和BitmapDrawable
一样,在实际的使用中直接引用图片即可,但是也可以通过XML来描述.9
图。
<?xml version="1.0" encoding="utf-8"?>
<nine-patch
xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/ic_launcher"
android:dither="true">
</nine-patch>
上述XML
中的属性的含义和BitmapDrawable
中的对应属性的含义是相同的。
2. ShapeDrawable
android:shape
表示图形的形状,有四个选项,rectangle
(矩形),oval
(椭圆),line
(线性),ring
(圆环)。它的默认值是矩形,另外line
和ring
这两个选项必须要通过<stroke>
标签来指定线的宽度和颜色等信息,否则将无法达到预期的显示效果。
针对ring
这个形状,有5个特殊的属性,android:innerRadius
,android:thickness
,android:innerRadiusRatio
,android:thicknessRatio
,android:useLevel
。含义如下表所示:
·corners·
表示shape
的四个角的角度,它只适用于矩形shape
,这里的角度是指圆角的程度。
android:radius
为4个角同时设定相同的角度,优先级较低,会被其他四个属性覆盖。
android:topLeftRadius
设定左上角的角度
android:topRightRadius
设定右上角的角度
android:bottomLeftRadius
设定左下角的角度
android:bottomRightRadius
设定右下角的角度
gradient
它与<solid>
标签是互相排斥的,其中solid
表示纯色填充,而gradient
则表示渐变效果。
android:angle
渐变的角度,默认为0
,其值必须为45
的倍数,0
表示从左到右,90
表示从下到上。
android:centerX
渐变的中心点的横坐标
android:centerY
渐变的中心点的纵坐标,渐变的中心点会影响渐变的具体效果
android:startColor
渐变的起始色
android:centerColor
渐变的中间色
android:endColor
渐变的结束色
android:gradientRadius
渐变半径,仅当android:type="radial"
时有效
android:useLevel
一般为false
,当Drawable
作为StateListDrawable
使用时为true
。
android:type
渐变的类型,有linear
(线性渐变),radial
(径向渐变),sweep
(扫描线渐变)三种,其中默认值为线性渐变。
solid
这个标签表示纯色填充,通过
android:colo
r即可指定shape
中填充的颜色
stroke
shape
的描边
android:width
描边的宽度,越大则shape
的边缘线就会看起来越粗。
android:color
描边的颜色
android:dashWidth
组成虚线的线段的宽度
android:dashGap
组成虚线的线段之间的间隔,间隔越大则虚线看起来空隙就越大。注意:如果android:dashWidth
和android:dashGap
有任何一个为0,那么虚线效果将不能生效。
padding
这个表示空白,但是它表示的不是shape
的空白,而是包含它的View
的空白,有四个属性:android:top
,android:right
,android:bottom
,android:left
。
size
设置的宽/高就是ShapeDrawable
的固有宽高,但是作为View
的背景时,shape
还会被拉伸或者缩小为View
的大小。
3. LayerDrawable
LayerDrawable
对应的XML
标签是layer-list
,它表示一种层次化的Drawable
集合,通过将不同的Drawable
放置到不同的层上面从而达到一种叠加后的效果。
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!--第一层-->
<item>
<shape android:shape="rectangle">
<solid android:color="#0ac39e"/>
</shape>
</item>
<!--第二层-->
<item android:bottom="6dp">
<shape android:shape="rectangle">
<solid android:color="#FFFFFF"/>
</shape>
</item>
<!--第三层-->
<item android:bottom="1dp"
android:left="1dp"
android:right="1dp">
<shape android:shape="rectangle">
<solid android:color="#FFFFFF"/>
</shape>
</item>
<item android:drawable="@drawable/ic_launcher"
android:gravity="right">
</item>
</layer-list>
一个layer-list
中可以包含多个item
,每个item
表示一个Drawable
,item
的结构也比较简单,比较常用的属性有android:bottom
,android:left
,android:right
,android:top
,它们分别表示Drawable
相对于View
的上下左右的偏移量,单位为px
。另外,我们可以通过android:drawable
属性来直接引用一个已有的Drawable
资源,也可以在item
中自定义Drawable
。默认情况下,layer-list
中的所有Drawable
都会被缩放至View
的大小,对于Bitmap
来说,需要使用android:gravity
属性才能控制图片的显示效果。layer-list
有层次的概念,下面的Item会覆盖上面的item,通过合理的分层,可以实现一些特殊的叠加效果。
4. StateListDrawable
StateListDrawable
对应于<selector>
标签,它也是表示Drawable
集合,每个Drawable
都对应着View
的一种状态,这样系统就会根据View
的状态来选择合适的Drawable
。
<selector
xmlns:android="http://schemas.android.com/apk/res/android"
android:constantSize="false"
android:dither="true"
android:variablePadding="false">
<item
android:drawable="@drawable/shape_main"
android:state_pressed="true"/>
<item
android:drawable="@color/colorAccent"/>
</selector>
android:constantSize
StateListDrawable
的固有大小是否随着其状态的改变而改变,因为状态的改变会导致StateListDrawable
切换到具体的Drawable
,而不同的Drawable
具有不同的固有大小。true
表示StateListDrawable
的固有大小保持不变,这时它的固有大小是内部所有Drawabl
e的固有大小的最大值,false
则会随着状态的改变而改变。此选项默认值为fasle
。
android:dither
是否开启抖动效果,开启此选项可以让图片在低质量的屏幕上依然获得较好的显示效果,此选项默认值为true
。
android:variablePadding
StateListDrawable
的padding
表示是否随着其状态的改变而改变,true
表示会随着状态的改变而改变,false
表示StateListDrawable
的padding
是内部所有Drawable
的padding
的最大值。此选项默认值为fasle
,不建议开启此选项。
<item>
标签表示一个具体的Drawable
,android:drawable
是一个已有Drawable
的资源id
,剩下的属性表示的是View
的各种状态,每个item
表示的都是一种状态下的Drawable
信息。
系统会根据View
当前的状态从<selector>
中选择对应的item
,每个item
对应着一个具体的Drawable
,系统按照从上到下的顺序查找,直至查找到第一条匹配的item
。一般来说,默认的item
都应该放在<selector>
的最后一条,并且不附带任何的状态,这样当上面的item
都无法匹配View
的当前状态时,系统就会选择默认的item
,因为默认的item
不附带状态,所以它可以匹配View
的任何状态。