Drawable天天用,可你是否对Drawable家族有一个完整的认知?今天我们就来系统的学习一下Drawable的使用。

1.概述

用过Drawable的筒子都知道Drawable有很多种,有的时候Drawable是一张图片,有的时候Drawable是我们通过颜色构造出来的某种图形。最常见的自己构造的Drawable图形莫过于ShapeDrawable,我们在开发中可能经常需要自己绘制一个矩形、圆形、椭圆等等各种各样的图形。一般来说,Drawable并没大小的概念(虽然可以通过getIntrinsicHeight和getIntrinsicWidth两个方法获取Drawable的宽和高,但是这两个方法并不总是有效,因为如果我们的Drawable是图片的话,那么Drawable的大小就是图片的大小,如果我们的Drawable本身就是颜色的话,那么就没有宽高的概念),因为我们在用Drawable的时候,大多数时候都是把它当作某一个控件的背景来使用的,此时Drawable会被拉伸到和View相同的大小,此时Drawable的大小实际上就是控件的大小。接下来我们来看看Drawable的继承关系:

在Drawable的这些继承类中我们常用的主要有以下几种:LayerDrawable、ShapeDrawable、NinePatchDrawable、BitmapDrawable、StateListDrawable、LevelListDrawable、TransitionDrawable、InsetDrawable、ScaleDrawable、ClipDrawable等,下面我们会就这些不同的Drawable一一介绍。

2.BitmapDrawable

BitmapDrawable算是最最最最常见的Drawable之一,我们构造一个Bitmap对象的时候,有时候会用到BitmapDrawable,那么BitmapDrawable的构造,除了在代码中new一个BitmaDrawable之外,我们还可以使用XML来构造一个BitmapDrawable对象,在项目的drawable文件中新创建一个xml文件,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:antialias="true"
android:src="@drawable/a2w"
android:dither="true"
android:filter="true"
android:gravity="top|left"
android:tileMode="mirror"
>
</bitmap>

这里只有src属性是必须的,该属性指这个BitmapDrawable要显示的图片,其他属性看单词意思都很容易明白,antialias表示是否开启抗锯齿,这个在自定义View创建Paint时经常用到;dither表示是否开启抖动效果,作用是手机像素配置和图片像素配置不一致时,系统会自动调整显示效果,关于图片像素问题参见Android开发之Bitmap二次采样文章;filter表示是否开启过滤效果,这个属性也是为了使图片被放大或者缩小时有一个较好的显示效果;gravity属性则表示当图片的大小小于控件的大小时,图片的显示位置,tileMode表示平铺模式,在我们的Windows电脑桌面设置的时候就有这个选项,该属性共有四种取值,分别是disable、repeat、mirror、clamp四种,默认情况下是disable,就是不做任何处理,当我们在这里使用了除disable之外的另外三种取值时,gravity属性值失效。下面我们来看看这三种取值时的效果:

我的原图是这样的:

我的bitmapdrawable是这样的:

<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:antialias="true"
android:src="@drawable/p2"
android:dither="true"
android:filter="true"
android:gravity="top|left"
android:tileMode="repeat"
>
</bitmap>

我的View是这样的:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="org.mobiletrain.drawable.MainActivity"> <View
android:layout_width="400dp"
android:layout_height="400dp"
android:background="@drawable/mybitmap"/>
</RelativeLayout>

这是显示效果是这样的:

大家看到,当图片的大小小于控件的大小时,图片会在水平方向和垂直方向不断的重复。如果我把tileMode属性的值改为clamp,我们再来看看显示效果:

大家看到,这时当图片小于控件的大小时,图片在水平方向或者垂直方向末端的颜色会自动延伸直至将控件填充满。最后我们再来看看mirror属性,为了方便看到效果,我这里把图片换一下,我们再来看看显示效果:

大家看到一个小飞机在水平方向和垂直方向以倒影的形式在不断的重复。这就是mirror的显示效果。

3.ShapeDrawable

shapeDrawable又是一个非常常用的Drawable,我们在开发中对于纯色的背景一般来说都是绘制的,因为直接使用图片会使App打包后变得比较大,通过XML来绘制纯色背景是一个不错的选择。关于这个我这里就不再多说了,大家查看这篇文章自行了解。android开发之shape详解。

4.LayerDrawable

LayerDrawable表示一个层次化的Drawable,这个要怎么理解呢?大家看看我之前的这篇文章就理解了博客关于ProgressBar的美化问题

LayerDrawable中可以有n多个item,每个item就是一个Drawable,每一个Drawable依据代码的顺序相互覆盖着显示出来。先写的先绘制,后写的后绘制,最终显示的效果是一个叠加的显示效果,我们来看下面一个例子:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="@color/lineColor"/>
</shape>
</item>
<item android:bottom="8dp">
<shape android:shape="rectangle">
<solid android:color="@color/lineColor2"/>
</shape>
</item>
<item android:bottom="1dp" android:left="1dp" android:right="1dp">
<shape android:shape="rectangle">
<solid android:color="@color/etbg"/>
</shape>
</item>
</layer-list>

我把这个Drawable作为EditText的背景,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="8dp"
tools:context="org.mobiletrain.drawable.MainActivity">
<EditText
android:background="@drawable/textview_background"
android:layout_width="match_parent"
android:text="江南一点雨"
android:layout_height="wrap_content"/>
<EditText
android:text="江南一点雨"
android:layout_marginTop="20dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>

显示效果如下(上面是加了背景的显示效果,下面是正常的EditText的显示效果):

大家看到,上面的EditText有一点不同,原因在于我在LayerDrawable中首先绘制了一个蓝色的矩形,然后又绘制了一个绿色的矩形,但是这个绿色矩形距离底部有8dp的高度,这就保证了输入框有两个向上翘起的蓝色边框,最后绘制整个背景色,整个背景色为黄色,但是背景色距离左右下三边的距离分别为1dp,这样就确保了另外三条线可以正常显示出来。OK,就是这么简单,更酷炫的用法参见关于ProgressBar的美化问题。

5.LevelListDrawable

LevelListDrawable,顾名思义就是一个等级Drawable,它就是根据控件的不同等级来切换Drawable,有点类似于selector中的根据控件的状态来更新Drawable。不同的是这里是根据控件的level来更新。比如下面一个简单的LevelListDrawable文件:

<?xml version="1.0" encoding="utf-8"?>
<level-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@drawable/p2"
android:maxLevel="10"
android:minLevel="0"/>
<item
android:drawable="@drawable/p1"
android:minLevel="11"
android:maxLevel="20"/>
</level-list>

这个levelListDrawable文件表示当控件的level处于0~10之间的时候,显示图片p2,当控件的level处于11~20之间的时候显示图片p1,我们来看看我的ImageView:

<ImageView
android:layout_width="200dp"
android:scaleType="centerCrop"
android:id="@+id/iv"
android:src="@drawable/level_list_drawable"
android:layout_height="200dp"/>

在ImageView中将刚才的LevelListDrawable对象作为它的src,然后当我点击按钮的时候改变ImageView的level,这个时候图片就会发生变化。点击事件代码如下:

public void toggle(View view) {
if (flag) {
iv.setImageLevel(5);
flag = false;
}else{
iv.setImageLevel(15);
flag = true;
}
}

显示效果如下:

这里大家需要注意的是level的取值范围为0~10000,默认值为0。

6.TransitonDrawable

TransitionDrawable主要是实现两个Drawable之间淡入淡出的效果。我们来看看TransitionDrawable文件:

<?xml version="1.0" encoding="utf-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/p1"/>
<item android:drawable="@drawable/p2"/>
</transition>

再来看看ImageView文件:

<ImageView
android:layout_width="200dp"
android:scaleType="centerCrop"
android:id="@+id/iv"
android:src="@drawable/transition_drawable"
android:layout_height="200dp"/>

点击事件如下:

public void toggle(View view) {
TransitionDrawable drawable = (TransitionDrawable) iv.getDrawable();
drawable.startTransition(2000);
}

显示效果如下 :

7.InsetDrawable

InsetDrawable表示可以将一个Drawable嵌入到自己当中。类似的效果使用LayerDrawable也能实现。来看看代码:

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

表示中心的圆形与控件的上下左右四边的间距都为20dp,当然这个设置图像的地方也可以像下面这种方式来写:

<?xml version="1.0" encoding="utf-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:insetBottom="20dp"
android:drawable="@drawable/p1"
android:insetLeft="20dp"
android:insetRight="20dp"
android:insetTop="20dp">
</inset>

8.ClipDrawable

表示根据一个Drawable的level对Drawable进行剪裁,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<clip
android:drawable="@drawable/p1"
android:clipOrientation="horizontal"
android:gravity="left"
xmlns:android="http://schemas.android.com/apk/res/android">
</clip>

drawable表示drawable图像,clipOrientation表示剪裁的方向,是从水平方向剪裁还是从垂直方向剪裁,这个属性配合gravity属性才会生效,至于每次剪裁的百分比则是和level属性的值有关,level属性的取值范围为0~10000,0表示完全剪裁,10000表示完全不剪裁,5000则表示剪裁一般,其它值依此类推。

以上。

玩转Android之Drawable的使用的更多相关文章

  1. 玩转Android Camera开发(二):使用TextureView和SurfaceTexture预览Camera 基础拍照demo

    Google自Android4.0出了TextureView,为什么推出呢?就是为了弥补Surfaceview的不足,另外一方面也是为了平衡GlSurfaceView,当然这是本人揣度的.关于Text ...

  2. Android使用Drawable资源之使用ClipDrawable资源 实现进入条

    以前我自定义的进度条(就是咱们现在工程中用的)是从android的源码中扒出来的一个XML,然后把里面的图片给替换了.一直不知道它的具体原理是什么. 今天得空研究了一下,发现它的原理其实就是用的and ...

  3. Android之drawable state各个属性详解

    android:drawable 放一个drawable资源android:state_pressed 是否按下,如一个按钮触摸或者点击.android:state_focused 是否取得焦点,比如 ...

  4. Android Studio中使用android:src="@drawable/ic_launcher"报错

    今天尝试着安装了Android Studio,界面确实不错,列表什么的也改了很多. 然后新建工程,习惯性在activity_main那里加上一段代码测试看看: <ImageView androi ...

  5. Android动画Drawable Animation

    Drawable Animation是逐帧动画,那么使用它之前必须先定义好各个帧.我们可以通过代码定义,也可以使用xml文件定义,一般使用后者.如下: <?xml version="1 ...

  6. Android 自定义Drawable

    1.使用BitmapShader实现图片圆角 public class CornerDrawable extends Drawable { private Paint mPaint; private ...

  7. Android的Drawable缓存机制源码分析

    Android获取Drawable的方式一般是Resources.getDrawable(int),Framework会返回给你一个顶层抽象的Drawable对象.而在Framework中,系统使用了 ...

  8. 玩转Android Camera开发(一):Surfaceview预览Camera,基础拍照功能完整demo

    杂家前文是在2012年的除夕之夜仓促完成,后来很多人指出了一些问题,琐事缠身一直没有进行升级.后来随着我自己的使用,越来越发现不出个升级版的demo是不行了.有时候就连我自己用这个demo测一些性能. ...

  9. Android 自带图标库 android.R.drawable

    在xml文件中调用. android:title="@string/secure_connect"android:orderInCategory="100"an ...

随机推荐

  1. Android fragment 回调函数改进

    由于fragment的onResume()等回调的调用时机与Activity不一样,导致用起来比较麻烦,所以我重新封装了一下回调函数,十分简单. 使用时只需要继承此基类,使用onFragmentXXX ...

  2. string.Split函数

    正文 string str = "a---b---c"; string[] array = str.Split(new char[]{'-'}); 分割之后array中的元素为 分 ...

  3. 同一客户代码下一个CPN对应多个FG会出现CPN描述一样的问题

    Q&A : D2E01客户下已经存在CPN: TP1062/A 对应FG: P5M2812512AFHHF0 直接在客户代码下无法新建,只能在交叉信息新建CPN: TP1062/A, 但无法修 ...

  4. zzzz

    using System; using System.Collections.Generic; using System.Diagnostics; using System.Management; u ...

  5. 【CSS】Beginner1:Applying CSS

    CSS(Cascading Style Sheets)   1.Applying CSS Three ways: 1.In-line 2.Internal 3.External   2.In-line ...

  6. 【待修改】nyoj 38 最小生成树

    package nyoj; import java.util.Scanner; public class Main { public static void main(String args[]) { ...

  7. 输入一个正数 n,输出所有和为 n 连续正数序列。 java实现

    用了半小时才写出来啊, 其实这种思路应用范围很广,利用有序性这个特点,比如本体只要是有序就行,例如两个集合是有序的,求交集,有序数组的查找,有序数组的归并,有序有了优化的可能. 输入一个正数 n,输出 ...

  8. hibernate4.0+版本和3.0+版本的区别总结

    自己总结下hibernate4.1版本中的新特性和hibernate3.3做区别 1.数据库方言设置 <property name=”dialect”>org.hibernate.dial ...

  9. POJ3107--Godfather(树的重心)

    vector建图被卡了..改为链式前向星500ms过的..差了四倍多?... 表示不太会用链表建图啊..自己试着写的,没看模板..嗯..果然错了..落了一句话orz 树的重心就是找到一个树中一个点,其 ...

  10. dut1305 台阶

    Description 如上图所示的一个台阶他的积水量是4 + 2 + 4 + 3 + 4 = 17. 给你一个长度是n的台阶.告诉你每个台阶的高度,求积水量是多少? Input 多组输入数据: 每组 ...