BitmapDrawable

  1. BitmapDrawable以**`**作为根节点:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    bitmap
    |- src="@drawable/res_id"
    |- antialias="[true | false]"
    |- dither="[true | false]"
    |- filter="[true | false]"
    |- tileMode="[disabled | clamp | repeat | mirror]"
    |- gravity="[top | bottom | left | right | center_vertical |
    | fill_vertical | center_horizontal | fill_horizontal |
    | center | fill | clip_vertical | clip_horizontal]"
    |
  2. 属性:

    • src:表示该 BitmapDrawable 引用的位图,该图片为 png、jpg 或者 gif;
    • antialias:表示是否开启抗锯齿,开启后使图片更加光滑,应该开启
    • dither:表示当位图和屏幕的像素配置不同时,是否允许抖动,开启后高质量图片在低质量屏幕上仍可以保持较好的显示效果,比如一张位图的像素为 ARGB_8888 32 位色,而屏幕像素为 RGB_565;一般应该开启
    • filter:是否允许为位图进行滤波以获取平滑的缩放效果;一般应该开启
    • gravity:定义位图的 gravity,当位图小于容器时,该属性指定了位图在容器中的停靠位置和绘制方式。
    • tileMode:表示当位图小于容器时,执行“平铺”模式,并且指定铺砖的方法。该属性覆盖 gravity 属性——当指定了该属性后,gravity 属性即使设置了,也将不起作用。

ShapeDrawable

  1. 通过颜色构造的图形既可以是纯色也可以是具有渐变效果的:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    <shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <corners android:radius="5dp"/>

    <gradient
    android:angle="90"
    android:endColor="#ddd"
    android:startColor="#343434"
    android:type="linear"/>
    <padding
    android:left="integer"
    android:top="integer"
    android:right="integer"
    android:bottom="integer"/>
    <size
    android:width="integer"
    android:height="integer"/>
    <solid
    android:color="color"/>

    <stroke
    android:width="2dp"
    android:color="#00f"/>
    </shape>

    shape标签创建的Drawable其实体类实际上是GradientDrawable

  2. 属性:

    • android: shape:有4个选项,rectangle(矩形)oval(椭圆)line(横线)ring(圆环),默认为rectangle,需要注意line和ring需要通过标签来指定线的宽度和颜色等信息,否则无法达到预期效果,针对ring这个形状有五个特殊属性:

    • < corners>:

      它只适用于矩形shape,表示矩形四个角的圆角程度,用px来表示,它有5个属性:

      1. android:radius—— 给四个角设置相同的角度,优先级较低,会被其他四个属性覆盖
      2. android:bottomLeftRadius——设定左下角的角度
      3. android:bottomRightRadius——设定右下角的角度
      4. android:TopLeftRadius——设定左上角的角度
      5. android:TopRightRadius——设定右上角的角度
    • < gradient>:

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

      1. android:centerX——渐变的中心点横坐标
      2. android:centerY——渐变的中心点纵坐标
      3. android: startColor——渐变的起始颜色
      4. android:centerColor——渐变的中间颜色
      5. android:endColor——渐变的结束颜色
      6. android:gradientRadiu——渐变半径,仅当android:type=”radial”时有效
      7. android:useLevel——一般为false,当Drawable作为StateListDrawable使用时为false
      8. android:type——渐变的类别,有linear(线性渐变)、radial(径向渐变)、sweep(扫描线渐变)三种,默认值为linear
      9. android:angle——渐变的角度,默认为0,其值必须是45的倍数,0表示从左到右,90表示从下到上。
    • **< solid>:**表示纯色填充,通过android:color即可指定填充的颜色

    • < stroke>:

      1. android:color——描边的颜色
      2. android:width——描边的宽度,越大则shape的边缘线越粗
      3. android:dashWidth——组成虚线的线段的宽度
      4. android:dashGap——组成虚线的线段之间的间隔

      需要注意:如果android:dashWidth和ndroid:dashGap有任何一个为0,那么虚线效果将不能生效

    • **:**表示包含它的View的空白

    • **< size>:**指shape的大小,一般不会用到。

LayerDrawable

LayerDrawable内部包含了一组Drawable,系统会按照这些Drawable对象的数组顺序来绘制他们,索引越大的Drawable将会被绘制的越上面。(简单一句话, 这些Drawable将会按顺序层叠在一起)。

LayerDrawable对象的xml文件的根元素是<layer-list>, 该元素内部包含多个<item>。item标签内部可以指定drawable、id和位置相关属性。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<layer-list>
<item>
<shape android:shape="rectangle">
<solid android:color="#0000ff" />
</shape>
</item>

<item
android:bottom="25dp"
android:left="25dp"
android:right="25dp"
android:top="25dp">
<shape android:shape="rectangle">
<solid android:color="#00ff00" />
</shape>
</item>

<item
android:bottom="50dp"
android:left="50dp"
android:right="50dp"
android:top="50dp">
<shape android:shape="rectangle">
<solid android:color="#ff0000" />
</shape>
</item>

</layer-list>

StateListDrawable

  1. 这个是开发中最常用的类型,StateListDrawable以**<selector>**作为根节点:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    selector
    |- item
    | |- drawable="@drawable/drawable_id"
    | |- state_pressed="[true | false]"
    | |- state_focused="[true | false]"
    | |- state_selected="[true | false]"
    | |- state_hovered="[true | false]"
    | |- state_checked="[true | false]"
    | |- state_checkable="[true | false]"
    | |- state_enabled="[true | false]"
    | |- state_activated="[true | false]"
    | |- state_window_focused="[true | false]"
    |
  2. 一个selector以多个item来组成,每个 item 由 0 个或者多个状态和一个 drawable 来表示,当控件的状态变化后,将根据控件当前的状态,来进行匹配,匹配一个最适合当前状态的 item,然后用这个 item 的 drawable 来进行绘制。比如,我们一个普通按钮的 selector 如下:

    1
    2
    3
    4
    5
    6
    7
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item
    android:state_pressed="true"
    android:drawable="@drawable/pressed_btn" />

    <item android:drawable="@drawable/normal_btn" />
    </selector>

    颜色也可以通过状态控制如下:

    1
    2
    3
    4
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:color="#fff"/>
    <item android:color="#e22"/>
    </selector>

LevelListDrawable

LevelListDrawable对应于标签,它同样表示一个Drawable集合,集合中每个Drawable都有一个等级(level)的概念。根据不通的等级,LevelListDrawable会显示对应的Drawable

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="utf-8"?>
<level-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@drawable/ic_sunny"
android:maxLevel="10"
android:minLevel="0" />
<item
android:drawable="@drawable/ic_night"
android:maxLevel="20"
android:minLevel="11" />
<item
android:drawable="@drawable/ic_cloudy"
android:maxLevel="30"
android:minLevel="21" />
</level-list>//等级默认为0,在1-10000范围内

1
2
3
4
5
6
7
8
9
10
var count = 0
iv_level_list.setOnClickListener {
count++
when (count % 3) {
0 -> iv_level_list.drawable.level = 5
1 -> iv_level_list.drawable.level = 15
2 -> iv_level_list.drawable.level = 25
}
}

TransitionDrawable

从Drawable的类继承图上可以看到TransitionDrawable是LayerDrawable的子类,但是不像LayerDrawable可以有多层drawable,TransitionDrawable只能管理两层drawable,并且提供了一个透明度变化的动画,可以控制从一层drawable过度到另外一层drawable的渐变动画效果。

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="utf-8"?>
<transition
xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:drawable="@[package:]drawable/drawable_resource"
android:id="@[+][package:]id/resource_name"
android:top="dimension"
android:right="dimension"
android:bottom="dimension"
android:left="dimension" />
</transition>
1
2
3
4
5
<?xml version="1.0" encoding="utf-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/onboarding_slide1"/>
<item android:drawable="@drawable/onboarding_slide2"/>
</transition>

可以使用startTransition和reverseTransition方法来接入实现淡入淡出效果

1
2
3
ImageView mImageView = (ImageView) findViewById(R.id.imageview);
TransitionDrawable trans = (TransitionDrawable) mImageView.getDrawable();
trans.startTransition(5000);

InsetDrawable

InsetDrawable 表示一个drawable根据指定的距离嵌入到另外一个drawable内部。(我们看到的其实还是同一张图片,只是会空出一些边距)当控件需要的背景比实际的边框小的时候比较适合使用InsetDrawable。

很像drawable的padding属性,区别在于 padding表示drawable的内容与drawable本身的边距,insetDrawable表示两个drawable和容器之间的边距。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<inset>
定义这个drawable为InsetDrawable,必须作为根节点。
属性:

xmlns:android
String类型。必须的,定义XML文件的命名空间,必须是"http://schemas.android.com/apk/res/android".
android:drawable
Drawable 资源 。必须的。引用一个drawable资源
android:insetTop
尺寸。与顶部的距离。可以使一个尺寸值,或者一个尺寸的资源。
android:insetRight
尺寸。与右边的距离。可以使一个尺寸值,或者一个尺寸的资源。
android:insetBottom
尺寸。与底部的距离。可以使一个尺寸值,或者一个尺寸的资源。
android:insetLeft
尺寸。与左边的距离。可以使一个尺寸值,或者一个尺寸的资源。
1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="utf-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/onepiece"
android:insetBottom="20dp"
android:insetLeft="20dp"
android:insetRight="20dp"
android:insetTop="20dp">
</inset>

ScaleDrawable

  1. 介绍:

    • ScaleDrawable对应标签,主要基于当前的level,对指定的Drawable进行缩放操作。
    • 有点需要特别注意的是我们如果定义好了ScaleDrawable,要将其显示出来的话,必须给ScaleDrawable设置一个大于0小于10000的等级(级别越大Drawable显示得越大,等级为10000时就没有缩放效果了)
  2. 语法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="utf-8"?>

<scale

xmlns:android="http://schemas.android.com/apk/res/android"

android:drawable="@drawable/drawable_resource"

android:scaleGravity=["top" | "bottom" | "left" | "right" | "center_vertical" |

"fill_vertical" | "center_horizontal" | "fill_horizontal" |

"center" | "fill" | "clip_vertical" | "clip_horizontal"]

android:scaleHeight="percentage"

android:scaleWidth="percentage" />

  • android:gravity

    当图片小于容器尺寸时,设置此选项可以对图片经典定位,这个属性比较多,不同选项可以使用‘|’来组合使用。

  • android:scaleHeight

    表示Drawable的高的缩放比例,值越大,内部Drawable的高度显示得越小,例如android:scaleHeight=”70%”,那么显示时Drawable的高度只有原来的30%。

  • android:scaleWidth

    表示Drawable的宽的缩放比例,值越大,内部Drawable的宽显示得越小,例如android:scaleWidth=”70%”,那么显示时Drawable的宽度只有原来的30%。

  • 必须在代码中调用设置level(默认为0)的代码才可以正常显示:

    1
    2
    3
    4
    5
    6
    ImageView scaleImage= (ImageView) findViewById(R.id.scaleImage);

    ScaleDrawable scale= (ScaleDrawable) scaleImage.getBackground();

    scale.setLevel(1);

ClipDrawable

  • ClipDrawable 是对一个Drawable进行剪切操作,可以控制这个drawable的剪切区域,以及相相对于容器的对齐方式,Android中的进度条就是使用一个ClipDrawable实现效果的,它根据level的属性值,决定剪切区域的大小

  • ClipDrawable是根据level的大小控制图片剪切操作的 level的大小从0到10000,level为0时完全不显示,为10000时完全显示。是用Drawable提供的setLevel(int level)方法来设置剪切区域。

  • 语法:

    • 定义这是个ClipDrawable,必须作为根元素。 **属性:**
      • xmlns:android

        String类型。必须的,定义XML文件的命名空间,必须是 “http://schemas.android.com/apk/res/android“.

      • android:drawable

        Drawable资源。 必须的。表示该ClipDrawable引用的drawable资源。

      • android:clipOrientation

        关键字。 裁剪的方向。

      • android:gravity
        关键字。指定从哪个地方裁剪。
        必须是下面一个或多个值(多个值之间用“|”分隔):

  • 举例:

    1
    2
    3
    4
    5
    6
    <?xml version="1.0" encoding="utf-8"?>
    <clip xmlns:android="http://schemas.android.com/apk/res/android"
    android:clipOrientation="horizontal"
    android:drawable="@drawable/onepiece"
    android:gravity="right"></clip>

    1
    2
    3
    4
    5
    6
    <ImageView
    android:id="@+id/clipimageview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:src="@drawable/clipdrawable"/>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    ImageView imageView = (ImageView) findViewById(R.id.clipimageview);
    final ClipDrawable clipDrawable = (ClipDrawable) imageView.getDrawable();
    final Handler handler = new Handler(){
    @Override
    public void handleMessage(Message msg) {
    if(msg.what == 0x123456){
    clipDrawable.setLevel(clipDrawable.getLevel()+200);
    }
    }
    };