Android样式的开发之drawable

0 概述

res/drawable目录下是Android用来存放图片资源文件的路径。这里除了有常规的图片外,还支持selector/shape等定制或自定义图片。

资源命名规则

下面将详细分析:

1.1 StateListDrawable

见selector部分详细分析

1.2 GradientDrawable

见shape分析部分

1.3 ShapeDrawable

2 BitmapDrawable

对应的xml标签为bitmap。

BitmapDrawable是对bitmap的包装,可以设置它包装的bitmap在BitmapDrawable区域内的绘制方式。如平铺、拉伸或保持图片原始大小,也可以使用gravity指定对齐方式。

android:src 必填项,指定图片资源,只能是图片,不能是xml定义的drawable资源

android:gravity 设置图片的对齐方式
    比如在layer-list中,默认会尽量填满整个视图,导致图片可能会被拉伸,
    为了避免被拉伸,就可以设置对齐方式,可取值为下面的值,多个取值可以用 | 分隔:

    top 图片放于容器顶部,不改变图片大小    
    bottom 图片放于容器底部,不改变图片大小
    left 图片放于容器左边,不改变图片大小
    right 图片放于容器右边,不改变图片大小
    center 图片放于容器中心位置,包括水平和垂直方向,不改变图片大小
    fill 拉伸整张图片以填满容器的整个高度和宽度,默认值
    center_vertical 图片放于容器垂直方向的中心位置,不改变图片大小
    center_horizontal 图片放于容器水平方向的中心位置,不改变图片大小
    fill_vertical 在垂直方向上拉伸图片以填满容器的整个高度
    fill_horizontal 在水平方向上拉伸图片以填满容器的整个宽度
    clip_vertical 附加选项,裁剪基于垂直方向的gravity设置
        设置top时会裁剪底部,设置bottom时会裁剪顶部,其他情况会同时裁剪顶部和底部
    clip_horizontal 附加选项,裁剪基于水平方向的gravity设置
        设置left时会裁剪右侧,设置right时会裁剪左侧,其他情况会同时裁剪左右两侧

android:antialias 设置是否开启抗锯齿

android:dither 设置是否抖动,图片与屏幕的像素配置不同时会用到。
    当每个颜色值以低于8位表示时,对应图像做抖动处理可以实现在可显示颜色总数比较低时
    还保持较好的显示效果。比如图片是ARGB 8888的,而屏幕是RGB565

android:filter 设置是否允许对图片进行滤波
    对图片进行收缩或者延展使用滤波可以获得平滑的外观效果

android:tint 给图片着色,设置的是颜色值.注意:使用android:tint指定颜色时一定要带透明度。
    比如图片本来是黑色的,着色后可以变成白色

android:tintMode 着色模式,也是API 21才添加的属性
    src_in  取两层绘制交集,显示上层 
    src_over    正常绘制显示,上下层绘制重叠
    src_atop    取下层非交集部分与上层交集部分。
    multiply    取两层绘制交集
    screen  上下层都显示
    add         混合遮罩,drawable颜色和透明度 
tintMode对应的Java设置
    PorterDuff.Mode.CLEAR 所绘制不会提交到画布上。
    PorterDuff.Mode.SRC 显示上层绘制图片
    PorterDuff.Mode.DST 显示下层绘制图片
    PorterDuff.Mode.SRC_OVER 正常绘制显示,上下层绘制叠盖。
    PorterDuff.Mode.DST_OVER 上下层都显示。下层居上显示。
    PorterDuff.Mode.SRC_IN 取两层绘制交集。显示上层。
    PorterDuff.Mode.DST_IN 取两层绘制交集。显示下层。
    PorterDuff.Mode.SRC_OUT 取上层绘制非交集部分。
    PorterDuff.Mode.DST_OUT 取下层绘制非交集部分。
    PorterDuff.Mode.SRC_ATOP 取下层非交集部分与上层交集部分
    PorterDuff.Mode.DST_ATOP 取上层非交集部分与下层交集部分
    PorterDuff.Mode.XOR 取两层绘制非交集。两层绘制非交集。
    PorterDuff.Mode.DARKEN 上下层都显示。变暗
    PorterDuff.Mode.LIGHTEN 上下层都显示。变亮
    PorterDuff.Mode.MULTIPLY 取两层绘制交集
    PorterDuff.Mode.SCREEN 上下层都显示。

tint着色效果图如下,(此处可以参考Android颜色渲染的Xfermode),会详细分析tint部分内容。

这里写图片描述

android:tileMode 设置图片平铺的方式,tile启用时,gravity将被忽略。tile取值如下:
    disable 不做任何平铺,默认设置
    repeat 图片重复铺满
    mirror 使用交替镜像的方式重复图片的绘制
    clamp 复制图片边缘的颜色来填充容器剩下的空白部分,
        比如引入的图片如果是白色边缘,那么图片所在的容器里除了图片,剩下的空间都会被填充成白色

android:alpha 设置图片的透明度
    xml中:取值范围为0-1之间,0为全透明,1为全不透明,API 11+才支持
    Java中:取值范围为0-255之间,0为全透明,255为全不透明,API 11+才支持

android:mipMap 设置是否可以使用mipmap,但API 17+

android:autoMirrored 设置图片是否需要镜像反转,
    当布局方向是RTL,即从右到左布局时才有用,API 19才添加的属性

android:tileModeXtileMode一样设置图片的平铺方式
    这个属性只设置水平方向的平铺方式,这是API 21才添加的属性

android:tileModeYtileMode一样设置图片的平铺方式
    这个属性只设置垂直方向的平铺方式,这是API 21才添加的属性

注:这里需要将BitmapDrawable设置为背景,而不是imageview的src,否则可能无效。

两种实现方式示例:
xml:

<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
    android:antialias="true"
    android:dither="true"
    android:src="@mipmap/ic_launcher"
    android:tileMode="mirror">
</bitmap>

java:

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
        BitmapDrawable bitmapDrawable = new BitmapDrawable(getResources(), bitmap);
        bitmapDrawable.setTileModeXY(Shader.TileMode.MIRROR, Shader.TileMode.MIRROR);
        bitmapDrawable.setAntiAlias(true);
        bitmapDrawable.setDither(true);

3 NinePatchDrawable

3.1 点9图片

点九图片文件扩展名为:.9.png,通过点九图片可以控制拉伸区域,做局部拉伸。

画点九图一般用Android SDK工具集里的draw9patch工具,只需要在四条边画黑线就可以了
这里写图片描述

拉伸区域就是图片会被拉伸的部分,可以为1个点,也可以为一条线,甚至也可以为断开的几个点或几条线,总之,有黑点的地方就会被拉伸,没有黑点的地方就不会被拉伸。

显示内容区域其实就等于默认给使用的控件设置了padding,控件的内容只能显示在内容区域内。
点9图片一般只适用于拉伸情况,不适用与压缩情况,故需要把图片做小,以适配小屏幕。

一般很少使用Java代码NinePatchDrawable创建点9图片,因为Android编译的时候会对点9进行特殊处理。

3.2 nine-patch标签

nine-patch标签可以对点九图片做一些设置处理:

android:src 必填项,必须指定点九类型的图片
android:dither 设置是否抖动,图片与屏幕的像素配置不同时会用到
android:tint 给图片着色
android:tintMode 着色模式,
android:alpha 设置图片的透明度
android:autoMirrored 设置图片是否需要镜像反转

以上属性同bitmap属性一致,当然.9图片也是可以直接使用bitmap标签的。这里需要注意的是src只能使用drawable中的资源,不能使用mipmap中资源示例:

<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@drawable/catt"
    android:alpha="0.3"
    >
</nine-patch>

4 InsetDrawable

InsetDrawable表示将一个Drawable嵌入到另一个Drawable中,且在内部保留一些间距。其用法和View的padding类似,只不过padding是设置Drawable内容与Drawable边界的距离,而InsetDrawable表示两个drawable与View容器之间的边界距离。其对于的xml文件标示为insert。

当控件需要的背景比实际的边框小的时候适合使用InsertDrawable。

android:drawable 指定drawable资源,如果不设置该属性,也可以定义drawable类型的子标签
android:visible 设置初始的可见性状态,默认为false
android:insetLeft 左边距
android:insetRight 右边距
android:insetTop 顶部边距
android:insetBottom 底部边距
android:inset 设置统一边距,会覆盖上面四个属性,但API 21+

使用示例,首先是定义:

<inset xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@mipmap/cat"
    android:visible="true"
    android:inset="100dp">

</inset>

然后是在xml中引用方式,设置到background或者src中。

android:src="@drawable/drawable_insert"

android:background="@drawable/drawable_insert"

5 ClipDrawable

ClipDrawable可以对drawable进行裁剪,可以控制这个Drawable的裁剪区域,以及相对于容器的对其方式。通过设置level值控制裁剪多少,level取值范围为0~10000,默认为0,表示完全裁剪,图片将不可见;10000则完全不裁剪,可见完整图片.例如在做进度条时很有用。
ClipDrawable的xml定义为clip

clip属性说明:

android:drawable 指定drawable资源,如果不设置该属性,也可以定义drawable类型的子标签

android:clipOrientation 设置裁剪的方向,取值为以下两个值之一:
    horizontal 在水平方向上进行裁剪,条状的进度条就是水平方向的裁剪
    vertical 在垂直方向上进行裁剪

android:gravity 设置裁剪的位置,可取值如下,多个取值用 | 分隔:
    top 图片放于容器顶部,不改变图片大小。当裁剪方向为vertical时,会裁掉图片底部
    bottom 图片放于容器底部,不改变图片大小。当裁剪方向为vertical时,会裁掉图片顶部
    left 图片放于容器左边,不改变图片大小,默认值。当裁剪方向为horizontal,会裁掉图片右边部分
    right 图片放于容器右边,不改变图片大小。当裁剪方向为horizontal,会裁掉图片左边部分
    center 图片放于容器中心位置,包括水平和垂直方向,不改变图片大小。
        当裁剪方向为horizontal时,会裁掉图片左右部分;
        当裁剪方向为vertical时,会裁掉图片上下部分
    fill 拉伸整张图片以填满容器的整个高度和宽度。
        这时候图片不会被裁剪,除非level设为了0,此时图片不可见
    center_vertical 图片放于容器垂直方向的中心位置,不改变图片大小。裁剪和center时一样
    center_horizontal 图片放于容器水平方向的中心位置,不改变图片大小。裁剪和center时一样
    fill_vertical 在垂直方向上拉伸图片以填满容器的整个高度。
        当裁剪方向为vertical时,图片不会被裁剪,除非level设为了0,此时图片不可见
    fill_horizontal 在水平方向上拉伸图片以填满容器的整个宽度。
        当裁剪方向为horizontal时,图片不会被裁剪,除非level设为了0,此时图片不可见
    clip_vertical 附加选项,裁剪基于垂直方向的gravity设置
        设置top时会裁剪底部,设置bottom时会裁剪顶部,其他情况会同时裁剪顶部和底部
    clip_horizontal 附加选项,裁剪基于水平方向的gravity设置
        设置left时会裁剪右侧,设置right时会裁剪左侧,其他情况会同时裁剪左右两侧

使用示例,首先是定义:

<clip xmlns:android="http://schemas.android.com/apk/res/android"
    android:clipOrientation="vertical"
    android:gravity="top">
    <bitmap
        android:gravity="center"
        android:src="@mipmap/girl5" />

</clip>

xml中引用方法同上,最后是在Java中定义level,level取值范围为0~10000,默认为0,表示完全裁剪,图片将不可见;10000则完全不裁剪.

imageView = (ImageView) findViewById(R.id.clip_drawable);
ClipDrawable clipDrawable = (ClipDrawable) imageView.getDrawable();
clipDrawable.setLevel(800);

6 ScaleDrawable

ScaleDrawable是一个对Drawable进行缩放操作的控件,其在xml中使用scale标签,和clip一样是通过设置level来控制缩放的比例。

android:drawable 指定drawable资源,如果不设置该属性,也可以定义drawable类型的子标签

android:scaleHeight 设置可缩放的高度,用百分比表示,格式为XX%,
    0%表示不做任何缩放,50%表示只能缩放一半

android:scaleWidth 设置可缩放的宽度,用百分比表示,格式为XX%,
    0%表示不做任何缩放,50%表示只能缩放一半

android:scaleGravity 设置drawable缩放后的位置,取值和bitmap标签的一样,默认值是left

android:useIntrinsicSizeAsMinimum 设置drawable原有尺寸作为最小尺寸,
    设为true时,缩放基本无效,API 11+

7 LayerDrawable

LayerDrawable管理一组drawable,每个drawable处于不同的层,绘制的时候按照顺序全部绘制到画布上,可能会由重叠,但是处于不同层的Drawable不会互相影响。

在xml文件中使用layer-list作为根节点来定义LayerDrawable,通过子节点item来定义每一层的Drawable,layer-list没有属性节点。

item 中可以指定drawable,参数

bottom  下边距
top     上边距
left    左边距
right   右边距
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:bottom="100dp">
        <bitmap
            android:alpha="0.3"
            android:src="@mipmap/girl1" />
    </item>
    <item android:top="100dp">
        <bitmap
            android:alpha="0.3"
            android:src="@mipmap/girl2" />
    </item>
</layer-list>

8 LevelListDrawable

LevelListDrawable管理一组drawable,每个drawable对应一个level范围,当它们被绘制的时候,根据level属性值选取对应的drawable绘制到画布。
在xml中由level-list实现,level-list通过添加item子标签来添加相应的drawable。

当需要在一个View中显示不同图片的时候,level-list就可以派上用场了。例如Android的电量显示就是使用的此控件。

android:drawable 指定drawable资源,如果不设置该属性,也可以定义drawable类型的子标签
android:minLevelitem的最小levelandroid:maxLevelitem的最大level

9 RotateDrawable

使用RotateDrawable可以对一个drawable进行旋转操作.可以使用level属性控制旋转的角度。
在xml中使用rotate结点来定义RotateDrawable。

android:drawable 指定drawable资源,如果不设置该属性,也可以定义drawable类型的子标签

android:fromDegrees 起始的角度度数

android:toDegrees 结束的角度度数,正数表示顺时针,负数表示逆时针

android:pivotX 旋转中心的X坐标,浮点数或是百分比。
    浮点数表示相对于drawable的左边缘距离单位为px,如5; 
    百分比表示相对于drawable的左边缘距离按百分比计算,如5%; 
    另一种百分比表示相对于父容器的左边缘,如5%p; 
    一般设置为50%表示在drawable中心

android:pivotY 旋转中心的Y坐标,同上。

android:visible 设置初始的可见性状态,默认为false

要让它可以旋转,还需要设置level值。level取值范围为0~10000,应用到rotate,则与fromDegrees~toDegrees相对应,如上面例子的角度范围为0~180,那么,level取值0时,则旋转为0度;level为10000时,则旋转180度;level为5000时,则旋转90度。因为level默认值为0,所以图片没有转变。那么,我们想转180度,其实可以将fromDegrees设为180,而不设置toDegrees,这样,不用再在代码里设置level图片就可以旋转180了

10 TransitionDrawable

TransitionDrawable是LayerDrawable的子类,它只负责两层的drawable,并且提供了一个透明度变化的动画,用来控制从一层drawable过渡到另一层drawable的动画效果。默认的过渡动画为淡入淡出效果。

xml中使用transition标签生成TransitionDrawable,要切换时,需要主动调用

item参数说明:

id:资源ID,可以通过findViewById找到以及修改此资源
top:    与顶部距离
bottom:与下边距离
right:  与右边距离
left:与左边距离
start:  效果同left
end:    效果同right

TransitionDrawable的startTransition()方法,参数为动画的毫秒数,也可以调用reverseTransition()方法逆向切换。另外,如果在Activity的onCreate()方法里直接调用start()方法会没有效果,因为view还没有初始化完成是播放不了动画的。一般使用handler的post方法延迟处理

11 AnimationDrawable

AnimationDrawable对应于Android帧动画,就是把一系列的Drawable按照一定的顺序,一帧一帧的播放。对应的xml根结点为animation-list标签。

animation-list通过添加item子标签设置每一帧使用的drawable资源,以及每一帧持续的时间。

android:oneshot属性设置是否循环播放,设为true时,只播放一轮就结束,设为false时,则会轮询播放。

android:duration属性设置该帧持续的时间,以毫秒数为单位。

animation-list对应的Drawable类为AnimationDrawable,要让动画运行起来,需要主动调用
AnimationDrawable的start()方法。另外,如果在Activity的onCreate()方法里直接调用start()方法会没有效果,因为view还没有初始化完成是播放不了动画的。一般使用handler的post方法延迟处理

12 animated-rotate

rotate标签只是将原有的drawable转个角度变成另一个drawable,它是静态的。而animated-rotate则会让drawable不停地做旋转动画。

android:drawable 指定drawable资源,如果不设置该属性,也可以定义drawable类型的子标签
android:pivotX 旋转中心的X坐标
android:pivotY 旋转中心的Y坐标
android:visible 设置初始的可见性状态,默认为false

14 animated-selector

api21+才支持。它是基于状态的,根据view的选中与激活等状态,使用相应的transition来过渡到正确的状态。里面包含两种标签 item和transition

13 VectorDrawable

VectorDrawable矢量图,无论放大缩小都不回失真。支持API21+.Android官方提供了一个VectorDrawableCompat以支持低版本的库。

VectorDrawable对应的xml文件为vector。

vector属性说明

height  矢量图绝对高度,必填(Used to define the intrinsic width of the drawable.)
weight 矢量图绝对宽度,必填(Used to define the intrinsic height the drawable)
ViewportWidth 画布canvas宽度 (Used to define the width of the viewport space.
     Viewport is basically the virtual canvas where the paths are drawn on.)
viewportHeight  画布canvas高度(Used to define the height of the viewport space.)
    以上两个属性必填,定义的Path路径必须在这个画布大小里去绘制,超出画布就显示不出来。
tint    着色
tintMode 着色模式
autoMirrored  RTL时使用,是否镜像。
alpha 透明度   

vector可以包含group/path/clip-path三个子标签.使用android:name属性给每个group和path指定一个唯一的名字,这样你可以从动画的定义中找到他们

group元素定义一系列路径或者子组,可以给一组path定义动画。

path元素定义可绘图的路径

android:fillColor属性定义绘制颜色
android:pathData定义绘制路径。

pathData中支持的path指令

M = moveto(M X,Y) :将画笔移动到指定的坐标位置
L = lineto(L X,Y) :从当前点画直线到指定的坐标位置
H = horizontal lineto(H X):从当前点画水平线到指定的X坐标位置,H为垂直点
V = vertical lineto(V Y):从当前点画垂直线到指定的Y坐标位置,V为垂直点
C = curveto(C X1,Y1,X2,Y2,ENDX,ENDY):三次贝赛曲线
S = smooth curveto(S X2,Y2,ENDX,ENDY)
Q = quadratic Belzier curve(Q X,Y,ENDX,ENDY):二次贝赛曲线
T = smooth quadratic Belzier curveto(T ENDX,ENDY):映射
A = elliptical Arc(A RX,RY,XROTATION,FLAG1,FLAG2,X,Y):弧线
    RX,RY指所在椭圆的半轴大小
    XROTATION指椭圆的X轴与水平方向顺时针方向夹角。
    FLAG1只有两个值,1表示大角度弧线,0为小角度弧线。
    FLAG2只有两个值,确定从起点至终点的方向,1为顺时针,0为逆时针
    X,Y为终点坐标
Z = closepath():关闭路径

pathData中的path指令使用原则

①坐标轴为以(0,0)为中心,X轴水平向右,Y轴水平向下。
②所有指令大小写均可。大写绝对定位,参照全局坐标系;小写相对定位,参照父容器坐标系
③指令和数据间的空格可以省略
④同一指令出现多次可以只用一个

注意,'M'处理时,只是移动了画笔, 没有画任何东西。 它也可以在后面给出上同时绘制不连续线。

使用path属性来设置矢量图,一般使用工具(比如Expression Design)来制作,再导出为XAML Silverlight画布格式的内容,赋值给path属性的pathData就可以绘制出该矢量图。矢量图可以参考

clip-path Defines path to be the current clip.

14 AnimatedVectorDrawable

子类AnimatedVectorDrawable可以让VectorDrawable动起来:通过改变VectorDrawable的属性来让其呈现动画效果,实际是实现了属性动画。其xml实现为animated-vector

实现AnimatedVectorDrawable步骤:

drawable使用xml中实现vector
drawable使用xml中实现animated-vector
animator中实现一个或多个objectAnimator

AnimatedVectorDrawable属性

drawable 指定矢量图

AnimatedVectorDrawable子标签

target 根据name找到相应的group name等于name的group,执行animation定义的动画效果(可以是animator动画)。

Animated vector drawable可以让和元素的属性动态变化。定义一组path或者子group,而元素定义需要绘制的路径。当你想让VectorDrawable呈现动画效果,在定义VectorDrawable的时候需要为group和path的android:name属性设置一个唯一的名字,以便在Animated vector drawable中找到它们

15 RippleDrawable

RippleDrawable,水波纹效果。对应的xml中为ripple。

16 源码地址

github

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值