Android开发艺术探索 第6章 Android的Drawable 读书笔记

6.1 Drawable简介

  1. Drawable表示的是一种可以在Canvas上进行绘制的抽象概念,它的种类有很多,最常见的就是颜色和图片。优点:使用简单,比自定义View成本低很多,非图片类型的Drawable占用空间较小。
    全面理解Drawable的使用细节还是很有必要的,这也是本章的出发点
  2. Drawable有很多种,都表示图像的概念,但不全是图片。Drawable是所有Drawable对象的基类。
  3. Drawable内部宽/高可以通过getIntrinsicWidth/getIntrinsicHeight这两个方法获取。但并不是所有Drawable都有宽高;图片Drawable的内部宽/高就是图片的宽/高,但是颜色形成的Drawable并没有宽/高的概念。

6.2 Drawable的分类

6.2.1 BitmapDrawable
<?xml version="1.0" encoding="utf-8"?>
<bitmap  / nine-pathch
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:antialias="true"
    android:dither="true"
    android:filter="true"
    android:gravity="center"
    android:mipMap="false"
    android:src="@mipmap/haimei1"
    android:tileMode="clamp"></bitmap>

android:src 资源id
android:antialias 是否开启图片抗锯齿功能,开启后图片会变得平滑,也会轻微降低图片清晰度,建议开启。
android:dither 是否开启抖动效果,当图片的像素配置与手机屏幕像素配置不一致时,开启这个选项可以让高质量图片在低质量屏幕上还能保持较好的显示效果,建议开启。
android:filter 是否开启过滤效果,当图片被拉伸或压缩时,开启过滤效果可以保持较好的显示效果,建议开启。
android:gravity 当前图片小于容器的尺寸时,设置此选项可以对图片进行定位。
android:titleMode 平铺模式,有这几个选项[disabled | clamp | repeat | mirror], 开启平铺模式后gravity属性会失效,disable表示关闭平铺模式(默认值),repeat表示水平和竖直方向上的平铺效果;
mirror表示水平和竖直上的镜面投影效果;而clamp表示图片四周的像素扩散到周围区域。

6.2.2 ShapeDrawable

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <corners
        android:bottomLeftRadius="10dp"
        android:bottomRightRadius="10dp"
        android:radius="5dp"
        android:topLeftRadius="10dp"
        android:topRightRadius="10dp" />

    <gradient
        android:angle="0"
        android:centerColor="#cccccc"
        android:centerX="100"
        android:centerY="20"
        android:endColor="#abcdef"
        android:gradientRadius="100dp"
        android:startColor="#000000"
        android:type="linear"
        android:useLevel="false" />

    <solid android:color="#cccccc" />

    <stroke
        android:width="1dp"
        android:color="#cccccc"
        android:dashGap="2dp"
        android:dashWidth="50dp" />
</shape>

android:shape 表示图片的形状,选项:rectangle(矩形)、oval(椭圆)、line(横线)、ring(圆环)。默认值是矩形,另外line和ring这两个选项必须通过<stroke>标签来指定宽度和颜色,否则看不到效果。

<corners> 表示shape的四个角的角度(圆角程度)。只适用于矩形shape。其中android:radius是同时为4个角设置相同的角度,优先级较低,会被topLeftRadius这种具体指定角度的属性所覆盖。

<gradient> 与<solid>标签相互排斥的,其中shlid表示纯色填充,而gradient表示渐变效果;gradient有如下几个属性:

  • android:angle 渐变的角度,默认为0,其值必须是45的倍数,0表示从左往右,90表示从下到上。
  • android:gradientRadius 渐变半径,仅当android:type="radial"时有效。
  • android:type 渐变的类型,有linear(线性渐变)、radial(镜像渐变)、swepp(扫描线渐变)三种,默认是线性渐变。

<solid>表示纯色填充,通过android:color即可指定shape中填充的颜色。

<stroke> Shape的描边,有如下属性:

  • android:width 描边的宽度
  • android:color 描边的颜色
  • android:dashWidth 组成虚线的线段的宽度
  • android:dashGap 注册虚线之间的间距

<size> shape的大小,有两个属性:android:width和android:height,分别表示shape的宽高。通过<size>标签指定宽高后,ShapeDrawable就有固定宽/高了。

6.2.3 LayerDrawable

它表示一种层次化的Drawable集合,通过将不同的Drawable放置在不同层后达到一种叠加效果。

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/res_haimei1"
        android:bottom="10dp"
        android:drawable="@mipmap/haimei1"
        android:left="10dp"
        android:right="10dp"
        android:top="10dp" />

    <item
        android:id="@+id/res_icon"
        android:width="30dp"
        android:height="30dp"
        android:drawable="@mipmap/ic_launcher"
        android:gravity="center" />
</layer-list>
6.2.4 StateListDrawable

它表示Drawable集合,每个Drawable对应View的一种状态,这样系统就会根据View的状态来选择合适的Drawable。主要用于设置可点击View的背景。

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" 
    android:constantSize="false" 
    android:dither="true" 
    android:variablePadding="false">
    <item android:drawable="@mipmap/ic_launcher" android:state_pressed="true" />
    <item android:drawable="@mipmap/haimei1" android:state_pressed="false" />
</selector>
6.2.5 LevelListDrawable

同样表示Drawable集合,集合中的每个Drawable都会有一个等级的概念,根据等级不同来切换对于的Drawable。当它作为View的背景时,可以通过Drawable的setLevel方法来设置不同的等级从而切换具体的Drawable。level的值从0-10000。

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@mipmap/haimei1" android:maxLevel="0" />
    <item android:drawable="@mipmap/haimei2" android:maxLevel="1" />
</selector>
6.2.6 TransitionDrawable

用来实现两个Drawable之间淡入淡出的效果。

<?xml version="1.0" encoding="utf-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@mipmap/haimei2" />
    <item android:drawable="@mipmap/haimei3" />
</transition>

TransitionDrawable drawable = (TransitionDrawable) imageView.getBackground();
drawable.startTransition(1000);
6.2.7 InsetDrawable

它可以将其他Drawable内嵌到自己当中,并可以在四周留下一定的间距。当一个View希望自己的背景比自己的实际区域小的时候,可以采用InsetDrawable来实现。

<?xml version="1.0" encoding="utf-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@mipmap/haimei1"
    android:insetBottom="10dp"
    android:insetLeft="10dp"
    android:insetRight="10dp"
    android:insetTop="10dp">
    <shape android:shape="rectangle">
        <solid android:color="#abcdef" />
    </shape>
</inset>
6.2.8 ScaleDrawable

它可以根据自己的等级(level)将指定的Drawable缩放到一定比例。
ScaleDrawable的xml所定义的缩放比例越大,那么内部Drawable看起来越小。如果level设置的越大,那么Drawable看起来就越大。

<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@mipmap/haimei2"
    android:scaleGravity="center"
    android:scaleHeight="70%"
    android:scaleWidth="70%">
</scale>

ScaleDrawable scaleDrawable = (ScaleDrawable) imageView.getBackground();
caleDrawable.setLevel(1);
6.2.9 ClipDrawable

它也通过自己的当前等级(level)来裁剪另一个Drawable,裁剪方向通过android:clipOrientation和android:gravity这两个属性来共同控制。等级0表示完全裁剪,8000表示裁剪了2000,即设置方向上裁剪了20% 。

<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
    android:clipOrientation="horizontal"
    android:drawable="@mipmap/haimei2"
    android:gravity="center">
</clip>

ClipDrawable clipDrawable = (ClipDrawable) ivLevei.getBackground();
clipDrawable.setLevel(7000);

6.3 自定义Drawable

  1. draw、setAlpha、setColorFilter和getOpacity这几个方法都是必须要实现的,其中draw是最重要的。当自定义Drawable有固有大小的时候最好重写getIntrinsicWidth和getIntrinsicHeight这两个方法。
  2. 内部大小不等于Drawable的实际区域大小,Drawable实际区域的大小可以通过getBounds方法来得到,一般来说它和View的尺寸相同。
  3. 具体代码可以查看主席的github
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容