Drawable每天用,可你是否对Drawable家族有一个完整的认知?今天咱们就来系统的学习一下Drawable的使用。java
1.概述
用过Drawable的筒子都知道Drawable有不少种,有的时候Drawable是一张图片,有的时候Drawable是咱们经过颜色构造出来的某种图形。最多见的本身构造的Drawable图形莫过于ShapeDrawable,咱们在开发中可能常常须要本身绘制一个矩形、圆形、椭圆等等各类各样的图形。通常来讲,Drawable并没大小的概念(虽然能够经过getIntrinsicHeight和getIntrinsicWidth两个方法获取Drawable的宽和高,可是这两个方法并不老是有效,由于若是咱们的Drawable是图片的话,那么Drawable的大小就是图片的大小,若是咱们的Drawable自己就是颜色的话,那么就没有宽高的概念),由于咱们在用Drawable的时候,大多数时候都是把它看成某一个控件的背景来使用的,此时Drawable会被拉伸到和View相同的大小,此时Drawable的大小实际上就是控件的大小。接下来咱们来看看Drawable的继承关系:android

在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文件,代码以下:spa
- <?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属性值失效。下面咱们来看看这三种取值时的效果:.net
个人原图是这样的:3d

个人bitmapdrawable是这样的:xml
- <?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>
这是显示效果是这样的:blog

你们看到,当图片的大小小于控件的大小时,图片会在水平方向和垂直方向不断的重复。若是我把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则表示剪裁通常,其它值依此类推。