Drawable是一个抽象类,是可绘制物件的抽象。与View不同,Drawable没有事件和交互的方法。一般情况下,Drawable附着在一个View上。不同的Drawable子类用于操作不同的资源类型,如BitmapDrawable用于操作位图,ColorDrawable用于操作颜色,ClipDrawable用于操作剪切板。
Drawable的原理:
Drawable主要调用本身的两个方法进行绘制:
draw(Canvas canvas):与View类似,该方法用于在canvas画布上进行绘制,而画布是由drawable上所附着的View对象决定的;
setBounds()方法用于指定绘制的边界,通常传入一个Rect矩形对象。
如需了解Drawable的官方介绍,您可以点击这个链接:《Android官方文档之App Resources(下)》。
BitmapDrawable
BitmapDrawable是对Bitmap的一种包装,可以设置它包装的Bitmap在BitmapDrawable区域内的绘制方式,如平铺填充、拉伸填充、或保持图片原始大小 等。
用法:
在res/drawable中创建一个bitmap.xml文件,并指定它的根标签为<bitmap>
,如下所示:
<!-- bitmap.xml -->
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:antialias="true"
android:src="@drawable/ic_launcher"
android:tileMode="mirror"
android:dither="true">
</bitmap>
其中,
- android:antialias为抗锯齿属性,设为true表示使得图片边缘显式更为平滑,但影响效率。
android:tileMode属性为平铺模式,默认为disable,即不平铺,还有三个属性:clamp ,复制边缘色彩;repeat ,X、Y 轴进行重复图片显示,也就是平铺; mirror,在水平和垂直方向上使用交替镜像的方式重复图片的绘制。
android:dither:抖动,Dither(图像的抖动处理,当每个颜色值以低于8位表示时,对应图像做抖动处理可以实现在可显示颜色总数比较低(比如256色)时还保持较好的显示效果。默认为true。
将该bitmap.xml设置为activity_main.xml的背景时的预览效果:
1、将tilemode属性设为mirror时:
2、将tilemode属性设为repeat时:
3、将tilemode属性设为clamp时:
4、将tilemode属性设为disabled时(默认):
dither属性对比图:(来自维基百科)
LayerDrawable
可以管理一组Drawable对象,并按照列表的顺序进行绘制,列表的最后一个Drawable绘制在最上层。
在res/drawable中创建一个layer.xml文件,并指定其根标签为<layer-list>
,如下所示:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@drawable/ic_launcher"
android:gravity="center" />
<item
android:drawable="@drawable/ic_launcher"
android:left="30dp"
android:top="30dp"
android:gravity="center" />
</layer-list>
其中第二个item将覆盖在第一个item之上,属性android:left与android:top分别表示基于第一个item的位置所向右偏移与向下偏移的距离。效果如下所示:
StateListDrawable
可以根据不同的状态提供不同的背景,比如一个按钮有多种状态:获取焦点、失去焦点、点击 等。
res/drawable中新建state_list.xml,并指定根标签为<state-list>
,代码如下:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/unclick" android:state_focused="true" />
<item android:drawable="@drawable/clicked" android:state_pressed="true" />
<item android:drawable="@drawable/unclick" android:state_selected="true" />
<item android:drawable="@drawable/unclick" />
</selector>
并在Button中应用,效果略。
LevelListDrawable
用于管理一组drawable资源,LevelListDrawable里的每一个drawable资源与一个最大数值结合起来,作为LevelListDrawable资源的一项;调用Drawable的setLevel()方法可以加载level-list或代码中的某个drawable资源。
在res/drawable目录下创建文件level_list.xml文件,并指定根标签为<level-list>
,如下:
<!-- level_list.xml -->
<level-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@drawable/unclick"
android:maxLevel="10"
android:minLevel="6" />
<item
android:drawable="@drawable/clicked"
android:maxLevel="20"
android:minLevel="12" />
</level-list>
其中属性 android:maxLevel与 android:minLevel分别最大级别和最小级别,在该级别之间时,将显示这个item中的图片。
将该level_list.xml文件设置给ImageView的background属性,并在Activity中调用
mImageView.setImageLevel(9);
方法,可以设置级别,在item中切换。
TransitionDrawable
TransitionDrawable是LayerDrawable的子类,不过它只负责管理两层drawable,并提供了一个透明度变化的动画,可以控制从一层drawable到另一层drawable的动画效果。
在res/drawable中创建transition.xml文件,并指定根标签为<transition>
,代码如下:
<!-- transition.xml -->
<transition xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/unclick" />
<item android:drawable="@drawable/clicked" />
</transition>
在Java代码中,在点击事件中添加代码:
TransitionDrawable drawable = (TransitionDrawable) mImageView.getBackground();
drawable.startTransition(2000);
drawable将在2秒内由第一个item的图片渐变到第二个item的图片。
InsetDrawable
表示将一个drawable嵌入到另一个drawable内部,并且在内部留一些间距,这一点很像drawable的padding属性。
在res/drawable中创建inset.xml文件,指定根标签为<inset>
:
<!-- inset.xml -->
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="#FF0000"
android:insetBottom="50dp"
android:insetLeft="50dp"
android:insetRight="50dp"
android:insetTop="50dp">
</inset>
属性android:insetBottom表示该drawable与底部的距离,类似于paddingBottom属性。在ImageView中指定其背景为inset.xml,效果如下:
ClipDrawable
ClipDrawable是对Drawable进行剪切操作,并控制剪切区域。
在Android中,进度条就是通过ClipDrawable实现的,它根据level这个属性值,确定裁剪的区域大小
ClipDrawable通过setLevel(int level)方法来设置剪切区域。level取值从0~10000,0表示完全不显示,10000表示完全显示。
在res/drawable在新建clip.xml,并指定根标签为<clip>
,如下所示:
<clip xmlns:android="http://schemas.android.com/apk/res/android"
android:clipOrientation="horizontal"
android:drawable="@drawable/ic_launcher">
</clip>
在Activity中设置剪裁尺寸:
mImageView = (ImageView) findViewById(R.id.mImageView);
ClipDrawable drawable = (ClipDrawable) mImageView.getDrawable();
drawable.setLevel(5000);
这表示只保留了图片的左半边区域。