Android开发的艺术探索第六章

第6章 Android的Drawable

Drawable在开发中有着自己的优点:首先,它使用简单,比自定义View的成本要低;其 次,非图片类型的Drawable占用空间较小,这对减小apk的大小也很有帮助。

6.1 Drawable简介

在Android的设计中,Drawable是一个抽象 类,它是所有Drawable对象的基类,每个具体的Drawable都是它的子类。
Android开发的艺术探索第六章
Drawable的内部宽/高这个参数比较重要,通过getIntrinsicWidth和getIntrinsicHeight这 两个方法可以获取到它们。但是并不是所有的Drawable都有内部宽/高,比如一张图片所 形成的Drawable,它的内部宽/高就是图片的宽/高,但是一个颜色所形成的Drawable,它 就没有内部宽/高的概念。另外需要注意的是,Drawable的内部宽/高不等同于它的大小,
一般来说,Drawable是没有大小概念的,当用作View的背景时,Drawable会被拉伸至 View的同等大小。

6.2 Drawable的分类

Drawable的种类繁多,常见的有BitmapDrawable、ShapeDrawable、LayerDrawable以 及StateListDrawable等,这里就不一一列举了,下面会分别介绍它们的使用细节。

6.2.1 BitmapDrawable

Android开发的艺术探索第六章
android:src
图片的资源id.
android:antialias
是否开启图片抗锯齿功能。开启后会让图片变得平滑,同时也会在一定程度上降低图
片的清晰度,但是这个降低的幅度较低以至于可以忽略,因此抗锯齿选项应该开启。
android:dither
是否开启抖动效果。当图片的像素配置和手机屏幕的像素配置不一致时,开启这个选 项可以让高质量的图片在低质量的屏幕上还能保持较好的显示效果,比如图片的色彩模式 为ARGB8888,但是设备屏幕所支持的色彩模式为RGB555,这个时候开启抖动选项可以 让图片显示不会过于失真。在Android中创建的Bitmap一般会选用ARGB8888这个模式, 即ARGB四个通道各占8位,在这种色彩模式下,一个像素所占的大小为4个字节,一个像 素的位数总和越高,图像也就越逼真。根据分析,抖动效果也应该开启。
android:filter
是否开启过滤效果。当图片尺寸被拉伸或者压缩时,开启过滤效果可以保持较好的显 示效果,因此此选项也应该开启。
android:gravity
当图片小于容器的尺寸时,设置此选项可以对图片进行定位。这个属性的可选项比较 多,不同的选项可以通过“|”来组合使用
android:mipMap
这是一种图像相关的处理技术,也叫纹理映射,比较抽象,这里也不对其深究了,默 认值为false,在日常开发中此选项不常用。
android:tileMode
平铺模式。这个选项有如下几个值:[“disabled”|“clamp”|“repeat”|“mirror”],其中 disable表示关闭平铺模式,这也是默认值,当开启平铺模式后,gravity属性会被忽略。这 里主要说一下repeat、mirror和clamp的区别,这三者都表示平铺模式,但是它们的表现却 有很大不同。repeat表示的是简单的水平和竖直方向上的平铺效果;mirror表示一种在水平 和竖直方向上的镜面投影效果;而clamp表示的效果就更加奇特,图片四周的像素会扩展 到周围区域。

6.2.2 ShapeDrawable

ShapeDrawable是一种很常见的Drawable,可以理解为通过颜色来构造的图形,它既 可以是纯色的图形,也可以是具有渐变效果的图形。
android:shape
表示图形的形状,有四个选项:rectangle(矩形)、oval(椭圆)、line(横线)和 ring(圆环)。它的默认值是矩形,另外line和ring这两个选项必须要通过标签来 指定线的宽度和颜色等信息,否则将无法达到预期的显示效果。

表示shape的四个角的角度。它只适用于矩形shape,这里的角度是指圆角的程度,用 px来表示,它有如下5个属性:
android:radius——为四个角同时设定相同的角度,优先级较低,会被其他四个属性覆盖; android:topLeftRadius——设定最上角的角度;
android:topRightRadius——设定右上角的角度;
android:bottomLeftRadius——设定最下角的角度;
android:bottomRightRadius——设定右下角的角度

它与标签是互相排斥的,其中solid表示纯色填充,而gradient则表示渐变效 果,gradient有如下几个属性:
android:angle——渐变的角度,默认为0,其值必须为45的倍数,0表示从左到右,90 表示从下到上,具体的效果需要自行体验,总之角度会影响渐变的方向; android:centerX——渐变的中心点的横坐标; android:centerY——渐变的中心点的纵坐标,渐变的中心点会影响渐变的具体效果; android:startColor——渐变的起始色; android:centerColor——渐变的中间色; android:endColo——渐变的结束色; android:gradientRadius——渐变半径,仅当android:type= "radial"时有效; android:useLevel——一般为false,当Drawable作为StateListDrawable使用时为true; android:type——渐变的类别,有linear(线性渐变)、radial(径向渐变)、 sweep(扫描线渐变)三种,其中默认值为线性渐变。

这个标签表示纯色填充,通过android:color即可指定shape中填充的颜色。

Shape的描边,有如下几个属性:
android:width——描边的宽度,越大则shape的边缘线就会看起来越粗; android:color——描边的颜色; android:dashWidth——组成虚线的线段的宽度; android:dashGap——组成虚线的线段之间的间隔,间隔越大则虚线看起来空隙就越 大。
注意如果android:dashWidth和android:dashGap有任何一个为0,那么虚线效果将不能生 效。

这个表示空白,但是它表示的不是shape的空白,而是包含它的View的空白,有四个属性:android:left、android:top、android:right和android:bottom。

shape的大小,有两个属性:android:width和android:height,分别表示shape的宽/高。 这个表示的是shape的固有大小,但是一般来说它并不是shape最终显示的大小,这个有点 抽象,但是我们要明白,对于shape来说它并没有宽/高的概念,作为View的背景它会自适 应View的宽/高。我们知道Drawable的两个方法getIntrinsicWidth和getIntrinsicHeight表示的 是Drawable的固有宽/高,对于有些Drawable比如图片来说,它的固有宽/高就是图片的尺 寸。而对于shape来说,默认情况下它是没有固有宽/高这个概念的,这个时候 getIntrinsicWidth和getIntrinsicHeight会返回-1,但是如果通过标签来指定宽/高信 息,那么这个时候shape就有了所谓的固有宽/高。因此,总结来说,标签设置的宽/ 高就是ShapeDrawable的固有宽/高,但是作为View的背景时,shape还会被拉伸或者缩小为View的大小。

6.2.3 LayerDrawable

LayerDrawable对应的XML标签是,它表示一种层次化的Drawable集合,通 过将不同的Drawable放置在不同的层上面从而达到一种叠加后的效果。

6.2.4 StateListDrawable

StateListDrawable对应于标签,它也是表示Drawable集合,每个Drawable都对应着View的一种状态,这样系统就会根据View的状态来选择合适的Drawable。

6.2.5 LevelListDrawable

LevelListDrawable对应于标签,它同样表示一个Drawable集合,集合中的 每个Drawable都有一个等级(level)的概念。根据不同的等级,LevelListDrawable会切换为对应的Drawable。

6.2.6 TransitionDrawable

TransitionDrawable对应于标签,它用于实现两个Drawable之间的淡入淡出 效果,它的语法如下所示。
Android开发的艺术探索第六章

6.2.7 InsetDrawable

InsetDrawable对应于标签,它可以将其他Drawable内嵌到自己当中,并可以在 四周留出一定的间距。当一个View希望自己的背景比自己的实际区域小的时候,可以采 用InsetDrawable来实现,同时我们知道,通过LayerDrawable也可以实现这种效果。

6.2.8 ScaleDrawable

ScaleDrawable对应于标签,它可以根据自己的等级(level)将指定的 Drawable缩放到一定比例,它的语法如下所示。

6.2.9 ClipDrawable

ClipDrawable对应于标签,它可以根据自己当前的等级(level)来裁剪另一个 Drawable,裁剪方向可以通过android:clipOrientation和android:gravity这两个属性来共同控制。