神奇的 Drawable 文件夹——介绍篇


Android 原生支持 MVC 模式,我们不必用 java 代码来 new 出界面中所有控件类,再组合起来,最后加载到界面上,而是利用 xml 文件的层级关系和节点的可自定义,组合出我们想要的布局方式,并且强大的 IDE 可以实时预览界面。所有的 xml 文件中的节点都对应一个存在的类,可能是控件或者下面说到的 Drawable,Drawable 是一种可以用来给控件设置背景等的图形对象,在 xml 文件中定义 Drawable,更方便设置控件的背景或者文本颜色等。

Drawable 的各种实现类可以在项目的 src/main/res/drawable 下建立 xml 文件,增加不同的节点来实现。下表是一些常用的 Drawable,和对应节点以及说明。

序号节点Drawable 具体子类说明
1bitmapBitmapDrawable对bitmap的封装
2colorColorDrawable表示纯颜色的 Drawable
3shapeShapeDrawable绘制基础的形状图形,可用于定义圆角、渐变色、圆环等效果
4selectorStateListDrawable表示一组有状态的 Drawable 集合,即选择器
5level-listLevelListDrawable表示一组有等级的图像的集合
6layer-listLayerDrawable表示图层
7nine-patchNinePatchDrawable对.9.png的封装
8clipClipDrawable对drawable裁剪
9insetInsetDrawable有内边距的 Drawable 对象
10rippleRippleDrawable波纹点击效果,API21以上

下面看怎样在 xml 文件中使用这些 Drawable,当然和布局文件中的 view 一样,我们也可以使用 java 代码来创建这些对象,但是我们一般不这样做,就像我们不会用 java 代码创建一个复杂的布局一样。 注:必要时也需要用 java 代码的方式来实现。

一、BitmapDrawable

在 drawable 文件夹下创建一个名为bitmap.xml的文件(名称可以随意),修改 <selector/> 根节点为 <bitmap/>,并且增加 src 属性,像下面这样:

<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@drawable/ic_launcher">
</bitmap>

这样我们就可以在文件文件中设置 view 的背景 android:background="@drawable/bitmap",bitmap 的使用就这么简单,一般使用 bitmap 也是配合别的 Drawable,用于包装图片资源,比如在 StateListDrawable(selector节点)下,对应每一个drawable 设置不同的 BitmapDrawable。

bitmap 节点下不能再包含子节点。所有的设置都通过属性来完成。

下表列出所有的属性供参考。

属性参数类型说明
android:srcDrawable resource显示的图片,不能为color等,只能为图片资源
android:alphafloat透明度0-1,值越小,越透明
android:antialiasboolean是否开启抗锯齿
android:autoMirroredboolean设置图片是否需要镜像反转,当布局方向是RTL,即从右到左布局时才有用,API19以上
android:ditherboolean是否抖动
android:filterboolean设置是否允许对图片进行滤波
android:gravitycenter…图片对其方式,同布局文件中view的gravity属性
android:mipMapboolean设置是否可以使用mipmap API18以上
android:tileModedisabled、mirror、clamp、repeatX、Y轴平铺方式, disabled(默认):不使用平铺;mirror:镜面;clamp:复制图片边缘的颜色来填充容器剩下的空白部分;repeat:图片重复铺满
android:tileModeX同上X轴平铺方式,参数意义同上
android:tileModeY同上Y轴平铺方式,参数意义同上
android:tintcolor给图片着色
android:tintModeadd、multiply、screen、src_atop、src_in、src_over着色模式

二、ColorDrawable

ColorDrawable 对应xml文件中的 <color/> 节点,同样在 drawable 文件夹下新建一个名为color.xml的文件(名称可以随意),内容如下:

<?xml version="1.0" encoding="utf-8"?>
<color xmlns:android="http://schemas.android.com/apk/res/android"
       android:color="@color/colorAccent">
</color>

color 节点只有唯一一个也是必须的属性,android:color 使用color资源文件中的color赋值即可。同样没有子节点,最为简单的一个 Drawable ,把 color 值转化为了 Drawable 对象,以便在其他需要 Drawable 的地方使用。

三、ShapeDrawable

使用 <shape/> 节点用来定义形状,可以定义矩形、椭圆、线、圆环四种类型的形状。shape 节点包含一些属性和子节点:

属性:

属性参数类型说明
android:shaperectangle、oval、line、ring定义形状的类型,rectangle(矩形)、oval(椭圆)、line(线)、ring(圆环)默认为矩形
android:innerRadiusint圆环内圆的半径
android:innerRadiusRatioint内半径占整个Drawable宽度的比例,默认值为9
android:thicknessint圆环的厚度
android:thicknessRatioint厚度占整个Drawable宽度比例,默认值为3
android:useLevelboolean设置等级,配合LevelListDrawable使用时设置
android:visibleboolean设置是否可见
android:ditherboolean是否抖动
android:tintcolor给图片着色
android:tintModeadd、multiply、screen、src_atop、src_in、src_over着色模式

子节点:

3.1 solid 填充色

表示形状的填充色,只有一个属性:android:color

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@color/colorAccent"/>
</shape>

solid1

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="oval">
    <solid android:color="@color/colorAccent"/>
</shape>

solid2

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:innerRadius="50dp"
       android:shape="ring"
       android:thickness="10dp"
       android:useLevel="false">
    <solid android:color="@color/colorAccent"/>
</shape>

solid3

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="line">
    <stroke
        android:width="4dp"
        android:color="@color/colorAccent"
        android:dashGap="8dp"
        android:dashWidth="4dp"/>
</shape>

solid4

3.2 corners 圆角

表示圆角的半径,对应有四个角的属性,和一个总体的属性

属性参数类型说明
android:radiusint统一设置圆角半径
android:bottomLeftRadiusint设置左下角圆角半径
android:bottomRightRadiusint设置右下角圆角半径
android:topLeftRadiusint设置左上角圆角半径
android:topRightRadiusint设置右上角圆角半径
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="rectangle">
    <corners
        android:bottomLeftRadius="3dp"
        android:radius="5dp"/>
    <solid android:color="@color/colorAccent"/>
    <size
        android:width="30dp"
        android:height="30dp"/>
</shape>

radius

3.3 gradient 渐变色

表示渐变色,可以设置形状填充的颜色为渐变色

属性参数类型说明
android:angleint设置旋转的角度,45的倍数
android:startColorcolor颜色变化的起始值
android:endColorcolor颜色变化的结束值
android:centerColorcolor中间的颜色
android:centerXint渐变中心点的横坐标
android:centerYint渐变的中心点的纵坐标
android:gradientRadiusint渐变的梯度,当android:type=”radial”有效
android:typelinear 、 radial 、 sweep渐变类别,linear(线性)为默认值,radial(径内渐变),sweep(扫描渐变)
android:useLevelboolean设置等级,配合LevelListDrawable使用时设置
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <gradient
        android:type="sweep"
        android:endColor="@color/colorAccent"
        android:startColor="@color/colorPrimary"/>
    <size
        android:width="30dp"
        android:height="30dp"/>
</shape>

gradient

3.4 stroke 边框

表示边框。

属性参数类型说明
android:colorcolor边框颜色
android:widthint边框宽度
android:dashGapint边框虚线间隙大小
android:dashWidthint边框虚线每个小节的宽度
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <stroke
        android:width="2dp"
        android:color="@color/colorAccent"
        android:dashGap="2dp" // 和dashWidth一起设置,若不设置则为实线
        android:dashWidth="3dp"/>
    <size
        android:width="30dp"
        android:height="30dp"/>
</shape>

stroke

3.5 size 大小

设置背景大小,width 和 height 两个属性。一般来说这个值不是 shape 的最终显示大小,因为 shape 作为背景时会根据 View 的大小而填充其背景,所以 Shape 的大小很多时候是 View 的大小决定的。

3.6 padding 内边距

表示内容或子标签边距,4个属性top、bottom、left、right,需要注意的是这个标签的作用是为内容设置与当前应用此 shape 的 View 的边距,而不是设置当前 View 与父元素的边距。

四、StateListDrawable

StateListDrawable 对应 drawable 文件夹下的xml文件的 <selector/> 节点,表示drawable集合。selector 可以包含不止一个 item 节点,每个 item 节点对应两类属性,一类只有一个 android:drawable, 另一类是类似于 android:state_pressed,表示当前所在 view 的状态,有按下、选择、获得焦点等十几种状态,需要注意不是每一个 view 都有这么多状态。 最常见的场景是给 Button 设置点击和正常状态下的 drawable。

selector 节点 属性:

属性参数类型说明
android:autoMirroredboolean设置图片是否需要镜像反转
android:constantSizeboolean设置自身大小是否随着其状态改变而改变
android:enterFadeDurationint状态改变时,新状态展示时的淡入时间,以毫秒为单位
android:exitFadeDurationint状态改变时,新状态消失时的淡入时间,以毫秒为单位
android:variablePaddingbooleanpadding是否随状态的改变而改变,默认false

子节点 item 属性:

属性参数类型说明
android:drawabledrawable对应drawable,可以为color、bitmap、shape等单一drawable
android:android:state_xxxboolean设置不同的状态
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@color/button_press"
          android:state_pressed="true"/>
    <item android:drawable="@color/button_norm"
          android:state_pressed="false"/>
</selector>

子节点 item 还可以包含许多子节点,如 bitmap、shape、color、动画相关的等,下面给出两个例子说明用法。

在布局文件中给view设置 android:background="@drawable/button_seleter" 即可,实现在点击view时显示不同的背景图,有点击的效果反馈。

这里需要注意一点: 如果上边所说的view是 Button 的话,直接可以看到效果,但是,实际开发中,我们可能要给 LinearLayout、TextView 设置点击效果,使用上面的方法是没有效果的。

解决方法:给这个 view 添加点击事件的监听。

上边代码中的 android:drawable 不只可以设置为 color 类型的 drawable,还可以设置为 bitmapDarwable、ShapeDrawable 等,下面看一个圆角点击效果的例子。

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="false">
        <shape>
            <corners android:radius="10dp"/>
            <solid android:color="@color/button_norm"/>
        </shape>
    </item>
    <item android:state_pressed="true">
        <shape>
            <corners android:radius="10dp"/>
            <solid android:color="@color/button_press"/>
        </shape>
    </item>
</selector>

设置在 view 上的效果为有圆角效果,并且按下的时候,背景后改变。 以上代码在 selector 节点下有两个 item 节点,item 节点设置了是否点击的状态,并且包含了一个 shape 节点,作为对应状态下的 drawable 对象。

五、LevelListDrawable

LevelListDrawable 对应xml文件中的 <level-list/> 节点,表示一组由等级大小标志的 drawable,不同的等级可以为之设置不同的背景 drawable。

此节点没有参数,只能包含不止一个的 item 子节点。

item 节点的属性:

属性参数类型说明
android:drawabledrawable对应drawable,可以为color、bitmap、shape等单一drawable
android:maxLevelint设置等级范围的最大值
android:minLevelint设置等级范围的最小值
<?xml version="1.0" encoding="utf-8"?>
<level-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:drawable="@color/colorAccent"
        android:maxLevel="10"
        android:minLevel="1"/>
    <item
        android:drawable="@color/colorPrimary"
        android:maxLevel="20"
        android:minLevel="11"/>
</level-list>

简单起见,使用 ColorDrawable 来设置对应的 android:drawable,有两种不同的背景,对应都有不同的等级范围。 设置给view 作为背景,像这样:android:background="@drawable/level"

在 java 代码中,获取到此 view 的 background,再设置其 level 属性的值,就会变为对应等级的背景。

boolean flag;

public void onClick(View v) {
    if (flag) {
        view.getBackground().setLevel(3);
    } else {
        view.getBackground().setLevel(13);
    }
    this.flag = !this.flag;
}

六、LayerDrawable

LayerDrawable 也表示 drawable 集合,对应xml文件中的<layer-list/>节点,根据名称我们可以知道其中的每一个 drawable 都代表一个图层,新加入的 drawable 位于背景图片的最高图层。 item 的 android:drawable 属性也是可以设置为复杂的 drawable 的,方便起见,这里使用 colorDrawable。

属性参数类型说明
android:opacitytransparent、translucent、opaque设置透明度:transparent透明、translucent半透明、opaque不透明
android:paddingXxxint设置等级范围的最大值

子节点 item 属性,都是定位的属性,像height,width,gravity,bottom,top,left,right等。

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:bottom="10dp"
        android:drawable="@color/colorAccent"
        android:left="10dp"
        android:right="10dp"
        android:top="10dp"
        />
    <item
        android:bottom="50dp"
        android:drawable="@color/colorPrimary"
        android:left="50dp"
        android:right="50dp"
        android:top="50dp"
        />
</layer-list>

效果如下:

layer

七、NinePatchDrawable

NinePatchDrawable 是点九图的封装,xml文件中对应 <nine-patch/> 标签,属性和 BitmapDrawable 中属性的含义相同。

<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"   
    android:src="@drawable/btn_bk"
    android:dither="true"/> 

八、ClipDrawable

ClipDrawable 代表可以裁剪的 drawable,对应xml文件中的<clip/>标签,通过当前设置的比例来裁剪Drawable,ClipDrawable 的 setLevel() 方法可以控制显示比例,ClipDrawable的level值范围在[0,10000],level 的值越大裁剪的内容越少,当 level 为 10000 时则完全显示,而 0 表示完全裁剪,不可见。

<clip/>标签的属性:

属性参数类型说明
android:drawabledrawable对应drawable,可以为color、bitmap、shape等单一drawable
android:clipOrientationhorizontal、vertical裁剪的方向,horizontal水平、vertical垂直
android:gravityright、top等设置drawable所在位置,配合android:clipOrientation属性一起用

android:gravity 可以设置下表所示的值:

属性描述说明
top将这个对象放在容器的顶部,不改变其大小。当clipOrientation 是”vertical”,裁剪从底部开始
bottom将这个对象放在容器的底部,不改变其大小。当clipOrientation 是”vertical”,裁剪从顶部开始
left将这个对象放在容器的左部,不改变其大小。当clipOrientation 是 “horizontal”,裁剪从drawable的右边(right)开始,默认值
right将这个对象放在容器的右部,不改变其大小。当clipOrientation 是 “horizontal”,裁剪从drawable的左边(left)开始
center将这个对象放在水平垂直坐标的中间,不改变其大小。当clipOrientation 是 “horizontal”裁剪发生在左右。当clipOrientation是”vertical”,裁剪发生在上下。
center_vertical将对象放在垂直中间,不改变其大小,如果clipOrientation 是 “vertical”,那么从上下同时开始裁剪
center_horizontal将对象放在水平中间,不改变其大小,clipOrientation 是 “horizontal”,那么从左右两边开始裁剪
fill填充整个容器,不会发生裁剪。(除非drawable的level是 0,才会不可见,表示全部裁剪完)。
fill_vertical垂直方向上不发生裁剪。(除非drawable的level是 0,才会不可见,表示全部裁剪完)
fill_horizontal水平方向上不发生裁剪。(除非drawable的level是 0,才会不可见,表示全部裁剪完)
clip_vertical附加选项,表示竖直方向的裁剪,很少使用
clip_horizontal附加选项,表示水平方向的裁剪,很少使用
<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
      android:clipOrientation="horizontal"
      android:drawable="@drawable/ic_launcher"
      android:gravity="right">
</clip>

上边代码定义了一个 ClipDrawable 对象,设置进行水平方向裁剪,并且从左边开始裁剪。drawable 为 app 启动图标。

在布局文件的view中使用像 android:background="@drawable/clip" 代码来使用上边定义的 ClipDrawable。

在 java 代码中,通过设置 ClipDrawble 的 level 属性的值,来进行图片背景的裁剪。

linearLayout = (LinearLayout) findViewById(R.id.lll);
linearLayout.getBackground().setLevel(5000); // 裁剪一半,0~10000

效果如下图:

clip

九、InsetDrawable

InsetDrawable 用距离边框的距离表示 drawable 大小,比如我们需要让view的背景不是完全填充这个 view,并且需要一定的距离,就可以使用 InsetDrawable 来完成。InsetDrawable 对应xml文件中的 <inset/> 标签。

属性:

属性参数类型说明
android:drawabledrawable对应drawable,可以为color、bitmap、shape等单一drawable
android:insetdimen统一设置距离边框的距离
android:insetTopdimen设置距容器上边的距离
android:insetBottomdimen设置距容器下边的距离
android:insetLeftdimen设置距容器左边的距离
android:insetRightdimen设置距容器右边的距离
android:visibleboolean设置是否可见
<?xml version="1.0" encoding="utf-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"
       android:drawable="@color/colorAccent"
       android:inset="10dp">
</inset>

十、RippleDrawable

RippleDrawable 可以在 Android5.0 即 API21 以上实现波纹点击效果,对应 xml 文件中的 <ripple/> 标签。由于此标签必须在 API21 以上才可以使用,我们也不能设置 minSdkVersion 为21,毕竟要适配更多的API版本,我们可以在建立一个 drawable-v21 的文件夹,在里面新建一个xml文件即可。

在 Android studio 中,就更方便了,选中 Drawable 文件夹—>右键—>选择new—>单击 Drawable resource file 选项,就来到了如下对话框:

ripple

填写文件名,选择最后一个 Version,单击中间的表示向右的按钮,填写 21,点击 ok,就会自动生成对应文件和新建文件。

<ripple/> 标签的属性:

属性参数类型说明
android:colorcolor波纹的颜色,会覆盖在背景上
android:radiusdimen圆角,不太懂,设置大小效果都一样
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="@color/gray">
    <!--有界-->
    <item
        android:id="@android:id/mask"
        android:drawable="@color/gray"/>
</ripple>

需要注意的是 android:id="@android:id/mask",没有设置时,是无边界的波纹效果,添加后为有边界。

ripple2

参考博文:

领略千变万化的Android Drawable (一)

领略千变万化的Android Drawable (二)

Android样式的开发:drawable汇总篇

参考视频教程:

[慕课网]Android的各种Drawable讲解

评论