6.1Drawable的简介
Drawble表示的是一种在Canvas上进行绘制的抽象概念。有很多种类,最常见的就是图片和颜色。有其最重要的两个优点:1.比自定义的view简单;2.非图片类型的drawable比图片占用空间小,可减小APK的大小。
Drawable是一个抽象类,是所有Drawable的基类,比如ShapeDrawable以及BitmapDrawable等等。
Drawable的内部高和内部宽是通过getIntrinsicHeight和getIntrinsicWidth获取的,但不是所有的Drawable类型都有内部高内部宽,一般图片类型的才会有。图片的内部高内部宽都是图片本书的大小,而颜色这种类型的内部宽高则默认是-1.Drawable没有大小的概念,做View背景时一般被拉伸到view的大小。
6.2Drawable的分类
(1).BitmapDrawable和NinePatchDrawable(图片类型;开发中引用原始的图片资源也可通过XML描述,XML描述可设置更多效果)
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/drawable_resource"
android:alpha="0.9"
android:gravity=["top" | "bottom" | "left" | "right" | "center_vertical" |
"fill_vertical" | "center_horizontal"
| "fill_horizontal" | "center" | "fill" |
"clip_vertical" | "clip_horizontal" | "start" | "end"]
android:tintMode=["src_over"|"src_in"|"src_atop"|"multiply"|"screen"|"add"]
android:tint="#ffffff"
android:autoMirrored=["true"|"false"]
android:tileMode=["disabled"|"clamp"|"repeat"|"mirror"]
android:mipMap=["true"|"false"]
android:dither=["true"|"false"]
android:filter=["true"|"false"]
android:antialias=["true"|"false"]
>
</bitmap>
属性介绍:
src :必填项,指定图片资源,只能是图片(可以是.9格式的图片),不能是xml定义的drawable资源
alpha:设置图片透明度,值的范围0.0~1.0,0.0是全透明,1.0是全不透明,API11(3.0)之后的属性
gravity:图片在容器中的位置,默认是fill。其中fill、fill_vertical、fill_horizontal会改变图片的大小,clip_vertical、clip_horizontal会裁剪图片
tintMode:图片着色模式,是API21(Android 5.0)才添加的属性
tint:给图片着色,比如图片本来是其他色的,着色后可以变成设置色
autoMirrored:设置图片是否需要镜像反转,当布局方向是RTL,即从右到左布局时才有用,API19(Android 4.4)才添加的属性
tileMode:设置图片平铺的方式,disabled不做任何平铺,默认设置;repeat图片重复铺满;mirror图片镜像交替(投影)的方式重复图片的绘制;clamp复制图片边缘的颜色来填充容器剩下的空白部分;
mipMap:纹理映射,设置是否可以使用mipmap,API17(4.2)添加的属性
dither:是否设置抖动,图片与屏幕的像素配置不同时会用到,比如图片是ARGB 8888的,而屏幕是RGB565,开启抖动不会让图片过于失真,所以应该开启。
filter:是否开启过滤,当图片被拉伸或者缩小时,开启过滤可以保持很好的显示效果,应该开启
antialias:是否开始图片抗锯齿,开启后图片平滑,但是也会降低图片的清晰度,降低可忽略,所以应该开启。
(2).ShapeDrawable(颜色类型)
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape=["rectangle" | "oval" | "line" | "ring"]>
<corners android:bottomLeftRadius="integer" android:bottomRightRadius="integer" android:radius="integer" android:topLeftRadius="integer" android:topRightRadius="integer" />
<gradient android:angle="integer" android:centerColor="color" android:centerX="integer" android:centerY="integer" android:endColor="color" android:gradientRadius="integer" android:startColor="color" android:type=["linear" | "radial" |"sweep"] android:useLevel=["true" | "false"] />
<padding android:bottom="integer" android:left="integer" android:right="integer" android:top="integer" />
<size android:height="integer" android:width="integer" />
<solid android:color="color" />
<stroke android:dashGap="integer" android:dashWidth="integer" android:width="integer" android:color="color" />
</shape>
属性介绍:
shape:图片的形状,rectangle矩形,oval椭圆,line横线,ring圆环,默认矩形。line和ring这两种形状需要通过来制定线的宽度和颜色,否则看不到效果。针对ring这个形状,有5个特殊的属性:innerRadius圆环内半径,和innerRadiusRatio同存在时以innerRadius为准。thickness圆环厚度,外半径减掉内半径的大小,和thicknessRatio同存在以thickness为准;innerRadiusRatio内半径占整个drawable宽度的比例,默认9,如果为n,内半径=宽度/n;thicknessRatio厚度占整个drawable宽度的比例,默认3,如果为n,厚度=宽度/n;userLevel一般使用false,否则无法达到预期,除非它被作为LevelListDrawable使用。
<corners>:shape四个角的角度,只适用矩形shape,radius的优先级最低,会被其他几个属性覆盖;
<gradient>:与<solid>标签互斥,solid表示纯色填充,而它表示渐变效果。angle渐变角度,默认为0,值是45的倍数,0表示从左到右,90是从上到下。centerX渐变的中心点的横坐标;gradientRadius渐变半径,只有当type=radial时有效。useLevel一般为false,当作为StateListDrawable时为true;type渐变类别,linear线性渐变(默认),radial径向渐变,sweep描线渐变。
<solid>:纯色填充
<stroke>:shape描边,dashWidth组成虚线的线段的宽度;dashGap虚线之间的间隔,dashWidth和dashGap任何一个为0则虚线效果不生效。
<size>:ShapeDrawable默认情况下是没有宽高的概念的,但是可以如果指定了size,那么这个时候shape就有了所谓的固有宽高,但是作为view的背景时,shape还是会被拉伸或者缩小为view的大小。
(3).LayerDrawable
层次化的Drawable集合,对应XML标签是<layer-list>,可以包含多个item,下面的item会覆盖遮挡上面的item,达到一种叠加的效果。属性android:top/left/right/bottom表示drawable相对于view的上下左右的偏移量,单位为像素。
(4).StateListDrawable
对应XML的标签<selector>,Drawable集合,每个Drawable对应View的一种状态,根据View的状态选择合适的Drawable。StateListDrawable主要用于View的点击背景。
constantSize是否随着状态改变而改变Drawable的固有大小,false代表随着状态改变而改变,默认为false。state_pressed:按下状态;state_focused:View获取了焦点;state_selected:选择了View;
state_checked:选中了View,适用CheckBox;stata_enabled:View处于可用状态。一般来说,默认的item都应该放在selector的最后一条并且不附带任何的状态,因为系统从上到下的顺序查找。
(5).LevelListDrawable
对应标签<level-list>,Drawable的集合,每个Drawable都对应一个等级,根据等级切换Drawable(setLevel方法)。如果被用来作为ImageView的背景,还可以通过ImageView的setImageLevel方法切换。值的范围:0~10000,默认为0也是最低等级。
(6).TransitionDrawable
对应标签<transition>,用来实现两个Drawable的淡入淡出效果。
transition xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="@drawable/drawable_one"/>
<item android:drawable="@drawable/drawable_two"/>
</transition>
通过它的startTransition和reverseTransition方法来实现淡入淡出效果以及逆过程。
ransitionDrawable drawable = (TransitionDrawable) v.getBackground();
drawable.startTransition(1000);
(7).InsetDrawable
对应<inset>标签,它将其他Drawable内嵌到自己中,并可以在四周留在一定间距。一个View希望自己的背景比自己实际区域小的时候可以采用该实现,LayerDrawable也可以实现这样的效果。insetBottom、
insetLeft、insetRight、insetTop分辨表示各个方向距离边界的大小。
(8).ScaleDrawable
对应标签<scale>,根据等级将Drawable进行一定比例的缩放。scaleWidth和scaleHeight以百分比的形式表示。默认等级为0则无法显示,等级值范围0~10000,等级越大缩放越大。android:useIntrinsicSizeAsMinimum 设置drawable原有尺寸作为最小尺寸,设为true时,缩放基本无效,API Level最低要求为11
(9).ClipDrawable
对应标签<clip>,可根据等级去裁剪一个Drawable,裁剪方向通过clipOrientation和gravity这个两个属性共同控制。level越大,表示裁剪的区域越小。等级0表示完全裁剪整个Drawable都不可见。
android:clipOrientation 设置裁剪的方向, horizontal 在水平方向上进行裁剪,条状的进度条就是水平方向的裁剪;vertical 在垂直方向上进行裁剪
android:gravity 设置裁剪的位置,可取值如下,多个取值用 | 分隔:
top 图片放于容器顶部,不改变图片大小。当裁剪方向为vertical时,会裁掉图片底部
bottom 图片放于容器底部,不改变图片大小。当裁剪方向为vertical时,会裁掉图片顶部
left 图片放于容器左边,不改变图片大小,默认值。当裁剪方向为horizontal,会裁掉图片右边部分
right 图片放于容器右边,不改变图片大小。当裁剪方向为horizontal,会裁掉图片左边部分
center 图片放于容器中心位置,包括水平和垂直方向,不改变图片大小。当裁剪方向为horizontal时,会裁掉图片左右部分;当裁剪方向为vertical时,会裁掉图片上下部分
fill 拉伸整张图片以填满容器的整个高度和宽度。这时候图片不会被裁剪,除非level设为了0,此时图片不可见
center_vertical 图片放于容器垂直方向的中心位置,不改变图片大小。裁剪和center时一样
center_horizontal 图片放于容器水平方向的中心位置,不改变图片大小。裁剪和center时一样
fill_vertical 在垂直方向上拉伸图片以填满容器的整个高度。当裁剪方向为vertical时,图片不会被裁剪,除非level设为了0,此时图片不可见
fill_horizontal 在水平方向上拉伸图片以填满容器的整个宽度。当裁剪方向为horizontal时,图片不会被裁剪,除非level设为了0,此时图片不可见
clip_vertical 附加选项,裁剪基于垂直方向的gravity设置,设置top时会裁剪底部,设置bottom时会裁剪顶部,其他情况会同时裁剪顶部和底部
clip_horizontal 附加选项,裁剪基于水平方向的gravity设置,设置left时会裁剪右侧,设置right时会裁剪左侧,其他情况会同时裁剪左右两侧
6.3自定义Drawable
1)核心就是draw方法,自定义drawable要重写draw方法,当然还有setAlpha、setColorFilter和getOpacity这几个方法。当自定义Drawable有固有大小的时候最好重写getIntrinsicWidth和getIntrinsicHeight方法,自定义颜色填充的Drawable没有固定的大小,没有必要重写,这时内部大小为-1。
(2)Drawable的内部大小不等于Drawable的实际区域大小,Drawable的实际区域大小可以通过它的getBounds方法来得到,一般来说它和view的尺寸相同。