6.1 Android中的Drawable

Android中的Drawable

Drawable表示的是一种可以在Canvas上进行绘制的抽象的概念,它的种类有很多,最常见的颜色和图片都可以是一个Drawable
Drawable在开发中有着自己的优点:首先,它使用简单,比自定义View的成本要低;其次,非图片类型的Drawable占用空间较小,这对减少apk的大小也很有帮助。

1. Drawable简介

Drawable有很多种,它们都表示一种图像的概念,但是它们又不全是图片,通过颜色也可以构造出各式各样的图像的效果。在Android的设计中,Drawable是一个抽象类,它是所有Drawable对象的基类,每个具体的Drawable都是它的子类,比如ShapeDrawableBitmapDrawable等。

Drawable的内部宽/高这个参数比较重要,通过getIntrinsicWidthgetIntrinsicHeight这两个方法可以获取到它们。但是并不是所有的Drawable都有内部宽/高,比如一张图片所形成的的Drawable,它的内部宽/高就是图片的宽/高,但是一个颜色所形成的Drawable,它就没有内部宽/高的概念。另外需要注意的是,Drawable的内部宽/高不等同于它的大小,一般来说,Drawable是没有大小概念的,当用作View的背景时,Drawable会被拉伸至View的同等大小。

Drawable的层次结构

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
当图片小于屏幕的尺寸时,设置此选项可以对图片进行定位。这个属性的可选项比较多,不同的选项可以通过|来组合使用。

gravity属性的可选项

android:mipMap
这是一种图像相关的处理技术,也叫纹理映射,比较抽象,默认值为false,在日常开发中此选项不常用。

android:tileMode
平铺模式。这个选项有如下几个值:repeatmirrorclampdisabled。其中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(圆环)。它的默认值是矩形,另外linering这两个选项必须要通过<stroke>标签来指定线的宽度和颜色等信息,否则将无法达到预期的显示效果。
针对ring这个形状,有5个特殊的属性,android:innerRadiusandroid:thicknessandroid:innerRadiusRatioandroid:thicknessRatioandroid:useLevel。含义如下表所示:

ring的属性值

·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(扫描线渐变)三种,其中默认值为线性渐变。

渐变的类别,从左到右依次为linear,radial,sweep

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

stroke
shape的描边
android:width
描边的宽度,越大则shape的边缘线就会看起来越粗。
android:color
描边的颜色
android:dashWidth
组成虚线的线段的宽度
android:dashGap
组成虚线的线段之间的间隔,间隔越大则虚线看起来空隙就越大。注意:如果android:dashWidthandroid: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表示一个Drawableitem的结构也比较简单,比较常用的属性有android:bottomandroid:leftandroid:rightandroid: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的固有大小保持不变,这时它的固有大小是内部所有Drawable的固有大小的最大值,false则会随着状态的改变而改变。此选项默认值为fasle

android:dither
是否开启抖动效果,开启此选项可以让图片在低质量的屏幕上依然获得较好的显示效果,此选项默认值为true

android:variablePadding
StateListDrawablepadding表示是否随着其状态的改变而改变,true表示会随着状态的改变而改变,false表示StateListDrawablepadding是内部所有Drawablepadding的最大值。此选项默认值为fasle,不建议开启此选项。

<item>标签表示一个具体的Drawableandroid:drawable是一个已有Drawable的资源id,剩下的属性表示的是View的各种状态,每个item表示的都是一种状态下的Drawable信息。

View的常见状态

系统会根据View当前的状态从<selector>中选择对应的item,每个item对应着一个具体的Drawable,系统按照从上到下的顺序查找,直至查找到第一条匹配的item。一般来说,默认的item都应该放在<selector>的最后一条,并且不附带任何的状态,这样当上面的item都无法匹配View的当前状态时,系统就会选择默认的item,因为默认的item不附带状态,所以它可以匹配View的任何状态。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,427评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,551评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,747评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,939评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,955评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,737评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,448评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,352评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,834评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,992评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,133评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,815评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,477评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,022评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,147评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,398评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,077评论 2 355

推荐阅读更多精彩内容

  • 优点:使用简单,比自定义View的成本低;非图片类型的Drawable占用空间较小,这对减小apk的大小也有很大的...
    小柏不是大白阅读 2,312评论 0 1
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,183评论 25 707
  • 6.1 Drawable 简介 Android 中的 Drawable 表示一种可以在 Canvas 上进行绘制的...
    kongjn阅读 1,575评论 0 1
  • 最近要考试,得去认真的准备一下了,所以画画可能会慢下来,但是还是会画下去的,不会放弃的(✧∇✧)╯╰(✧∇✧)̣
    一只好coffee阅读 100评论 0 0
  • 树/艾青 一棵树,一棵树 彼此孤离地兀立着 风与空气 告诉着它们的距离 但是在泥土的覆盖下 它们的根伸长着 在看不...
    姬亚琳阅读 1,426评论 19 17