Android Drawable 详解

Android Drawable 详解


@(Technical)[Android, Drawable, StateListDrawable, LayerDrawable, AnimationDrawable]

1、Drawable 简介

Drawable——可简单理解为可绘制物,表示一些可以绘制在 Canvas 上的对象。在日常的工作开发中,我们为 UI 配置背景、图片、动画等等界面效果的时候,需要和众多的 Drawable 打交道。每种 Drawable 的适用范围不同,我们有必要了解每种 Drawable 的特点以及使用方式,才能在工作中得心应手,少走弯路。

具体的配置、使用方法以及最终的界面效果大家可以在本文的附件里面看到。Drawable 在 Android 中的继承关系如下,其中,红框标注的几种 Drawable 是我们在开发中比较常用的一些:

常用 Drawable

Drawable 中比较重要的方法有以下几种:

Drawable
    |- createFromPath
    |- createFromResourceStream
    |- createFromStream
    |- createFromXml
    |
    |- inflate   : 从XML中解析属性,子类需重写
    |- setAlpha  : 设置绘制时的透明度
    |- setBounds : 设置Canvas为Drawable提供的绘制区域
    |- setLevel  : 控制Drawable的Level值,这个值在ClipDrawable、RotateDrawable、ScaleDrawable、AnimationDrawable等Drawable中有重要作用;区间为[0, 10000]
    |- draw(Canvas) : 绘制到Canvas上,子类必须重写

其中,比较重要的方法是inflatedrawinflate 方法用于从 XML 中读取 Drawable 的配置,draw 方法则实现了把一个 Drawable 确切的绘制到一个 Canvas 上面——draw 方法为一个abstract抽象方法,子类必须进行重写。inflate 方法在Drawable.createFromXmlInner中被调用:

createFromXmlInner

我们可以看出,在从 XML 中创建一个 Drawable 时,步骤如下:

  1. 先根据 XML 节点名称来决定创造什么类型的 Drawable;然后 new 出相应的 Drawable;
  2. 再为该 Drawable 调用 inflate 方法,让其把配置加载起来——因为每种 Drawable 会重写 inflate 方法,所以,可以正确加载到各项配置及属性。XML 的配置我们稍后再讲。

setAlpha方法用于设置一个 Drawable 的透明度,setBounds用来指定当执行绘制时,在 Canvas 上的位置和区域。比如我们自定义一个 View,在其onDraw中绘制一个BitmapDrawable,我们设置了 BitmapDrawable 的 Alpha 和 Bounds,代码如下:

Drawable baseDrawable = getResources().getDrawable(R.drawable.base);
baseDrawable.setAlpha(100);
baseDrawable.setBounds(10, 20, 500, 300);
imageContent.setDrawable(baseDrawable);

绘制后的表现如下:

alpha 绘制表现

上图中,第一个区域是正常绘制的,第二个我们为 Drawable 设置了Alpha和Bounds,可以看出,右边深蓝色的纯色部分为整个 Canvas 的大小,设置了 100 的 Alpha 透明度后,图片把后面深蓝色的颜色也给透过来了,并且 Bounds 决定了 Canvas 上绘制该 Drawable 的区域大小和位置。

2、ColorDrawable

接下来我们逐一介绍 Drawable,着重介绍几种常用的 Drawable。由于在开发中这些 Drawable 大多在 XML 中进行配置,所以我们结合 XML 的配置类介绍。先从ColorDrawable开始,这个应该是最简单的一种 Drawable 了,它用一个颜色值来表示

color
    |- color="#xxxxxx | @color/color_value"
    |

比如我们的一个 ColorDrawable 的 XML 配置如下,以<color>作为根节点:

<color
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="#0000ff"/>

使用的时候和其他 Drawable 的使用方法类似,可以通过Resource.getDrawable来获取,或者在 XML 里面配置:

<RelativeLayout
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:background="@drawable/blue_drawable"/>

这个 View 的界面表现如你所想,是一坨蓝色:

蓝色

Java代码实现:
Resources res = getResources();
ColorDrawable colorDrawable = new ColorDrawable();
colorDrawable.setColor(res.getColor(R.color.skin_black_item));

3、BitmapDrawable

BitmapDrawable<bitmap>作为根节点:

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]"
    |

这个比较复杂一点了,我们逐一介绍各个属性:

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

其中,gravitytileMode这两个属性比较有意思,我们着重来进行介绍。gravity 的默认值为fill——亦即在水平和垂直方向均进行缩放,使得图片可以填充到整个 View 里面。

比如我们有一张如下的图片:

car

为了比较好的展现clamp 钳位模式,注意这张图,我们在右边缘和下边缘用了黑白交替的边线。我们的 XML 配置极其简单,以<bitmap>作为根节点:

<bitmap
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@drawable/car"
    android:tileMode="repeat"/>

当这个 BitmapDrawable 放入一个比它大的容器中时,tileMode 就起作用了:

  1. repeat模式:将重复贴该图,直到填充完容器:

repeat

  1. clamp模式:钳位模式,将沿用下边、右边边缘的像素值分水平、垂直两个方向扩展填充剩余位置:

clamp

  1. mirror模式:镜像模式,将按水平、垂直镜像重复来填充剩余位置:

mirror

  1. disabled:禁用任何填充方法,将使用整个位图进行缩放填充。

disabled

我们接着来看 gravity 属性,该属性也比较容易理解:

  1. top:在顶部水平中心绘制;其他类如 left、right、bottom 和 top 类似;

top

当然,我们可以使用“|”来组合,达到特殊的效果,比如当 gravity 为bottom|right时,表现如下:

bottom|right

  1. center_horizontalcenter_vertical将在水平、垂直两个方向上居中。当单独使用 top/left/right/bottom 四个值时,默认带了这两个中的值:比如 top == top|center_horizontal

  2. fill_horizontalfill_vertical将在水平、垂直两个方向上进行缩放填充,默认也是带了center_horizontal或者center_vertical这两个值的;

下面是“fill_vertical”的表现:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值