这些 Drawable 的小技巧,你都了解吗?

173

一、前言

在 Android 的开发过程中,Drawable 经常会被用到,一般会用 Drawable 为 View 设置一个显示的效果。而在 Android 下,也提供了很多 Drawable 的默认实现,它们涉及到的内容非常的多,从属性到方法,但是日常生活中,会用到的只有那么些方式。

本文就在工作中,Drawable 的常用方式,整理出一篇文章,会携带一些场景,如有缺漏的,可以在文末留言,本文采用精益编写,如有必要,会一直长期更新。

二、什么是 Drawabe

Drawable 实际上是一个抽象类,主要用于将一个可绘制的资源,按要求绘制成图形,显示在屏幕之上。

Android 为了让开发者更方便的使用 Drawable ,提供了很多 Drawable 的实现类,并提供对应的 xml 的属性配置。

例如:

/d-shapedefault.png

同时它也可以使用代码的方式实现,它们的效果是一样的。

/d-shapecode.png

实际上,不管是使用 xml 资源的方式,还是直接在逻辑中硬编码的方式,它们最终显示的效果都是一样的,如下图,一个蓝色的方块:

/d-shapeimage.png

Android 中,为我们提供了非常多默认的 Drawable,正常来说,一般是足够我们使用的,它们的关系如下图:

/d-normal.png

基本上,从 XxxDrawable 这种类名,就可以看出来它对应的 Xml 资源的命名,唯一需要注意的是 <shape/> 的实现类是 GradientDrawable ,而不是 ShapeDrawable。

三、Drawable 的常用实现

3.1 圆角的按钮

有些 App 中,按钮的圆角,如果背景只是一个纯色或者是简单的规则渐变,是可以使用 <shape/> 来完成的,如前面示例一样。

如果想要为其增加一个圆角,可以在 <shape/> 中使用 corners 属性,它支持设置一个 android:radius ,用来设置四个角落的圆角角度,当然也提供了单独的属性去设置某个角的圆角角度,例如,android:topLeftRadius 就是设置左上的圆角的。

/d-shapecornes.png

实现的效果如下:

/d-shapecornesimg.png

3.2 带边框的圆角按钮

想在圆角的 <shape/> 上,加一个边框,可以使用 stroke 属性,当然,不是设置 corners 属性,它就不是一个圆角的效果了。

stroke 用于设置边框,可以指定颜色和边框的宽度。

/d-strokexml.png

可以看到这里指定了一个黄色的边框,效果如下图:

/d-strokeimage.png

3.3 单边边框

在 <shape/> 中,如果使用 stroke 来设置边框,它会在四周都加上边框,但是有时候,我们只需要在底部或者单边绘制一个边框的效果,例如:一个列表页里每一项的分割线。

这个时候,就可以使用 <layout-list/>,使用两个 shape 来叠加实现。

bottom-line

这样的一个 Drawable,如果作为背景的话,显示效果就是在白色背景下,有一条 1px 的灰线。当然其他方向可以参考这个方案,截图发现 1px 的线不太明显,这里就不放图了。

3.4 渐变的背景色

<shape/> 除了支持一个纯色规则图案,它还可以实现渐变的效果,用的最多的,就是线性渐变。

例如一些视频 App 的 UI 设计,会将视频名称直接布局在视频海报上,就可以使用线性渐变的 <shape/> 来实现简单的背景效果,使其在白色的视频海报上,显示的效果依然能看得清楚文字。

例如一般的视频App :

/d-tengxun.png

看到其实海报下面的文字,底部是有一个渐变的背景色的。

这种渐变的效果,可以使用 gradient 标签来设置。

/d-gradientxml.png

gradient 支持的属性,基本上看名称就可以知道意思,唯一需要注意的是 android:angle 这个属性,用于设定渐变的角度,但是它不是任何值都支持的,只支持 45 的倍数。

效果如下图:

/d-gradientimage.png

3.5 海报的默认图

通常在图片加载的过程中,会为其定义一个默认图片。一般的设计都是会将这个默认图做的非常的简洁,例如中间一个 App 主题的 Icon,然后其它地方纯色铺平。

类似下面这种效果:

/d-aqiyi.png

这种默认的图片,当然你可以使用一张等大的图,但是这样不利于适配,不同的 UI 设计尺寸,你需要提供不同的图片。当然你也可以使用 9patch 的图片,但是你会发现有些 density 为 2.75 这种奇葩的手机下,图标会微微偏移,不在正中间。所以这里可以使用一个<layer-list/> 的 Drawable 来实现。

<layer-list/> 是一个带层级效果的 Drawable ,有点类似于布局中的 FrameLayout 的效果。它支持设置多个 Drawable ,并将它们叠加在一起。

所以这样的场景下,我们就需要一个纯色的背景加一张小图,即可实现默认图的效果。

下面是 xml 的实现代码:

/d-layerxml.png

下面是运行后的效果图:

/d-layerimage.png

3.6 带按下效果的按钮

对一个按钮,设计一个按下的效果。可以使用 <selector/> 这个 Drawable。它支持在不同的状态下,显示不同的 Drawable。

<selector> 同样也支持设置多个 Drawable ,区别在于你需要额外的为每个 Drawable 设置不同的状态,如果不设置,则为默认显示的状态。

这些不同的状态,在 xml 里,都是以 android:state_Xxx 开头来定义的,将其设置为 true 即可生效。

Android 为我们提供了非常多的状态,比较常用的有:

  • state_pressed:按下的效果。
  • state_checkable:是否可设置 checked 状态的效果。
  • state_selected:支持 selected 并且当前处于 selected 的效果。
  • state_checked:支持 checkeable 并且当前处于 checked 的效果。

接下来让我们看一个实际的按钮例子,这里只为其设置按下的效果,xml 代码如下:

/d-pressxml.png

实现效果如下:

/d-pressDemo.gif

3.7 一个带按下效果的圆角按钮

这个没啥好说的,结合上面的效果就可以做到。你可以选择将它们写在不同的 Drawable 中,也可以在一个 xml 文件中,使用不同 item 来完成。Item 标签是可以支持内部再嵌套一个 Drawable 的。

/d-cornespress.png

3.8 带按下动画

按下效果除了使用 <selector> 做一个变色的效果之外,在 Api Level 21 之后,可以尝试使用 StateListAnimator 来实现一个 Material Design 的按下效果。

具体细节可以看看我之前的一篇文章:《利用 StateListAnimator 为你的点击加个动画吧!

StateListAnimtor 使用起来非常的简单:

  1. 在 res 中创建一个 animator 目录。
  2. 在其中创建一个 xml 资源文件,就是一个 <selector/> 。
  3. 在 xml 资源中使用 <selector/> 中,定义我们 View 切换状态时候的动画,其实就是一个个 <objectAnimator/>。
  4. 最终将定义好的 animtor 通过 View 的 setStateListAnimator() 方法或者 android:stateListAnimator 属性,设置到 View 上。

举个例子。

首先在 /res/animtor 目录下,创建一个 btn_press_animator.xml 文件。

animator-xml

可以看到,和 StateListDrawable 一样,它也是通过 android:state_xxx 属性来定义不同的 Animator 的,如果存在多个 Animator ,可以使用 <set/> 标签将其包裹起来。 这里只是简单的在 state_pressed 的时候,做了一个缩小的动画。

然后,定义一个 View,为其设置属性 android:stateListAnimator="@animator/btn_press_animator"

来看看运行的效果:

[图片上传失败...(image-e0ebc3-1512715336178)]

3.9 三角形的 Drawable

�假如有类似气泡提示的效果,如下图。

qipao

这样的效果,除了使用 9patch 来实现之外,还可以拿两个 Drawable 来拼接实现,这就需要一个圆角的矩形和一个三角的 Drawable。

三角 Drawable 的实现思路很清奇,是使用一个矩形的 shape ,通过使用 rotate 实现的旋转,来达到尖角的效果。

daosanjiao

这个例子,就是上图的实现效果,是一个黄色的倒三角。如果想要的是一个正三角,只需要改变旋转的角度就可以了。

zhensanjiao

3.10 Tint 着色的 Drawable

在 Drawable 中,如果使用的是 BitmapDrawable 或者 NinePatchDrawable(9patch) 的资源的话,可以使用 android:tint 属性为其着色。

默认情况下,待着色的图片资源,会将其所有有颜色地方,都着色成我们指定的颜色,但是会保留透明度。

/d-tintxml.png

效果图如下,上面是原图,下面是使用 tint 之后的效果:

/d-tintimage.png

前面这里给的是 tint 默认的效果,还可以通过 android:tintMode 指定成不同的着色效果,例如下面将 android:tintMode 指定成 screen 之后,效果就完全不一样了。

/d-tintimage1.png

3.11 铺平的 Drawable

有时候,作为一些有规则的图片的背景,可以使用一张很小的图片,然后设定 android:tileMode 属性,为其设定一个平铺的效果。

[图片上传失败...(image-916a9a-1512715336178)]

tileMode 可以指定多个属性值,用于指定不同的效果,以下就是两个比较常用的,上图使用的是 repeat ,下图使用的是 mirror。

/d-tileimage.png

3.12 状态可控的层级 Drawable

如果想要一个 ImageView 上,根据不同的条件显示不同的 Drawable ,可以使用 <level-list/> 。从名字上就可以看出它是一个带层级的 Drawable 组合,和 <selector/> 很像,但是区别在于它的显示状态是我们逻辑可控的。最常见的例子是拿它实现一个开关的灯泡,两态的图片,一个表示开灯,一个表示关灯,相信大家应该都见过例子。

今天举一个例子,给某个图标加红点的逻辑。当然我们也可以使用通过一个 FrameLayout 来实现,但是今天我们试试用 <level-list/> 来实现它。

red-point

这里使用一个 <level-list/> ,内部根据不同的 maxLevel 和 minLevel 来控制范围,这里只有两态,所以直接让它们取值一致。红点使用 <layer-list> 做了一个层叠,在右上角上,直接画了一个大小为 5dp 的红色圆点。

最终我们可以通过 ImageView 的 setImageLevel() 方法来控制显示的内容。

d-red-demo

四、结语

到这里基本上涵盖了 Drawable 大部分的使用场景,在实际例子中学东西是印象最深刻的。当然,Drawable 的使用不止这些,还有一些例如拿 ClipDrawable 来实现一个切割进度的效果之类的,这种还需要写逻辑代码,就不在本文的范围内了,本文主要介绍一些静态能实现的效果。

你只需要掌握最基本的规则,什么 Drawable 能实现什么效果,具体碰到实际需求的时候,再来细致的研究,基本上微调一下就可以使用。

如果你还又什么更有意思的 Drawable 使用技巧,欢迎在文末留言,我们一起讨论一下,如有需要,会持续更新。

今天在承香墨影公众号的后台,回复『成长』。我会送你一些我整理的学习资料,包含:Android反编译、算法、设计模式、虚拟机、Linux、Kotlin、Python、爬虫、Web项目源码。

推荐阅读:

[图片上传失败...(image-b12cfc-1512715336178)]

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

推荐阅读更多精彩内容