掌握Drawable可以做出一些特殊的效果.
1.Drawable的内部宽高
通过getIntrinsicWidth和getIntrinsicHeight这两个方法可以获取到。并不是所有的Drawable都有内部宽高,比如一张图片所形成的的Drawable,它的内部宽高就是图片的宽高,但是一个颜色所形成的的Drawable,就没有内部宽高的概念。
另外需要注意的是,Drawable的内部宽高不等同于它的大小,一般来说,Drawable是没有大的概念的,当用作View的背景的时候,Drawable会被拉伸至View的同等大小。
2.Drawable的分类
2.1.BitmapDrawable
<?xml version="1.0" encoding="utf-8"?>
<bitmap
xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@[package:]drawable/drawable_resource"
android:antialias=["true" | "false"]
android:dither=["true" | "false"]
android:filter=["true" | "false"]
android:gravity=["top" | "bottom" | "left" | "right" | "center_vertical" |
"fill_vertical" | "center_horizontal" | "fill_horizontal" |
"center" | "fill" | "clip_vertical" | "clip_horizontal"]
android:mipMap=["true" | "false"]
android:tileMode=["disabled" | "clamp" | "repeat" | "mirror"] />
表示的就是一张图片,在实际的开发中,可以直接引用原始的图片即可,也可以通过xml的方式来描述。
src:图片的资源id
antialias:是否开启图片的抗锯齿,开启后会让图片更加圆滑,同时会在一定的程度上面降低图片的清晰度,但是这个降低的幅度较低以至于可以忽略。因此抗锯齿选项应该开启。
dither:是否开启抖动效果。根据分析,抖动效果应该开启。
filter:是否开启过滤效果。当图片尺寸被拉伸或者压缩的时候,开启过滤效果可以保持较好的显示效果,因此应当开启。
gravity:当图片的尺寸小于容器的尺寸的时候,设置此选项可以对图片进行定位。
mipMap:图片相关的处理技术叫纹理映射,默认值为false,开发中此选项不常用。
tileMode:平铺模式。disabled表示关闭平铺模式,默认值。当开启平铺模式之后gravity属性会被忽略。
repeat表示简单的水平和竖直方向的平铺效果;
mirror表示在水平和竖直方向上的镜面投影效果;
clamp表示图片四周的像素会扩展到周围区域。
2.2.NinePatchDrawable
<?xml version="1.0" encoding="utf-8"?>
<nine-patch
xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@[package:]drawable/drawable_resource"
android:dither=["true" | "false"] />
xml中的属性和BitmapDrawable中标签的属性是一样的,表示一张.9格式的图片。.9图片可以自动地根据所需的宽/高进行相应的缩放并保证不失真,和BitmapDrawable一样,在实际开发中可以直接引用,实际使用过程中发现bitmap标签也可以使用.9图。
2.3.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:radius="integer"
android:topLeftRadius="integer"
android:topRightRadius="integer"
android:bottomLeftRadius="integer"
android:bottomRightRadius="integer" />
<gradient
android:angle="integer"
android:centerX="integer"
android:centerY="integer"
android:centerColor="integer"
android:endColor="color"
android:gradientRadius="integer"
android:startColor="color"
android:type=["linear" | "radial" | "sweep"]
android:useLevel=["true" | "false"] />
<padding
android:left="integer"
android:top="integer"
android:right="integer"
android:bottom="integer" />
<size
android:width="integer"
android:height="integer" />
<solid
android:color="color" />
<stroke
android:width="integer"
android:color="color"
android:dashWidth="integer"
android:dashGap="integer" />
</shape>
shape:图形的形状,矩形,椭圆,横线,圆环,默认矩形,另外,line和ring这两个选项必须通过stroke指定闲的宽度和颜色等信息。
针对ring这个环状,有5个特殊的属性:
android:innerRadius圆环的内半径,和android:innerRadiusRatio同时存在时,以android:innerRadius为准。
android:innerRadiusRatio内半径占整个Drawable宽度的比例,默认为9。如果为n,那么内半径=宽度/n
android:thickness圆环的厚度,即外半径减去内半径的大小,和android:thicknessRatio同时存在时,以android:thickness为准。
android:thicknessRatio厚度占整个Drawable宽度的比例,默认值为3。如果为n,那么厚度=宽度/n
android:useLevel一般应该使用false,否则有可能无法达到预期的显示效果,除非被当做LevelListDrawable。
corners:表示shape的四个角的角度。只适用于矩形shape,这里的角度指的是圆角的程度用px来表示。
android:radius为四个角同时设定相同的角度,优先级较低,会被其他四个属性覆盖。
android:topLeftRadius设定左上角的角度
android:topRightRadius设定右上角的角度
android:bottomLeftRadius设定左下角的角度
android:bottomRightRadius设定右下角的角度
gradient:与solid标签是互相排斥的,其中solid表示纯色填充,而gradient表示渐变效果。
android:angle渐变的角度。默认为0,其值必须为45的倍数,0表示从左到右,90表示从下到上。
android:centerX渐变的中心点的横坐标
android:centerY渐变的中心点的纵坐标
android:startColor渐变的起始色
android:centerColor渐变的中间色
android:endColor渐变的结束色
android:gradientRadius渐变半径,仅当android:type为radial有效
android:useLevel一般为false,当Drawable作为StateListDrawable使用时为true
android:type渐变的类型,有linear线性渐变,radial径向渐变,sweep扫描线渐变三种,默认为线性渐变。
solid:这个表示纯色填充,通过color即可指定shape中填充的颜色。
stroke:shape的描边。
android:width描边的宽度,越大则shape的边缘线就会看起来约粗
android:color描边的颜色
android:dashWidth组成虚线的线段的宽度
android:dashGap组成虚线的线段之间的间隔,间隔越大看起来空隙就越大
注意:如果android:dashWidth和android:dashGap有任何一个为0,那么虚线效果将不能生效
padding:表示空白,但是它表示的不是shape的空白,而是包含它的view的空白。
size:shape的大小,属性android:width,android:height。
表示shape的固有大小,一般来说不是shape最终显示的大小,shape没有宽高的概念,作为view的背景会自适应view的宽高。Drawable的两个方法getIntrinsicWidth和getIntrinsicHeight表示的是Drawable的固有宽高,对于有些Drawable比如图片来说,它的固有宽高就是图片的尺寸,对于shape来说,默认情况下,它是没有固有宽高这个概念的,这个时候那两个方法就会返回-1,但是如果通过size标签设置宽高信息,shape就有了所谓的固有宽高。
总结来说,size标签设置的宽高就是ShapeDrawable的固有宽高,但是作为view的背景时,shape还会被拉伸或者缩小为view的大小。
2.4.LayerDrawable
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:drawable="@[package:]drawable/drawable_resource"
android:id="@[+][package:]id/resource_name"
android:top="dimension"
android:right="dimension"
android:bottom="dimension"
android:left="dimension" />
</layer-list>
表示一种层次化的Drawable集合,通过将不同的Drawable放置在不同的层上面从而达到一种叠加后的效果。这些属性分别表示Drawable相对于View的上下左右的偏移量。
类似微信的文本输入框:
<?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="#0AC39E"/>
</shape>
</item>
<item android:bottom="6dp">
<shape android:shape="rectangle">
<solid android:color="#FFFFFF"/>
</shape>
</item>
<item
android:bottom="1dp"
android:left="1dp"
android:right="1dp">
<shape android:shape="rectangle">
<solid android:color="#FFFFFF"/>
</shape>
</item>
</layer-list>
2.5.StateListDrawable
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:constantSize=["true" | "false"]
android:dither=["true" | "false"]
android:variablePadding=["true" | "false"] >
<item
android:drawable="@[package:]drawable/drawable_resource"
android:state_pressed=["true" | "false"]
android:state_focused=["true" | "false"]
android:state_hovered=["true" | "false"]
android:state_selected=["true" | "false"]
android:state_checkable=["true" | "false"]
android:state_checked=["true" | "false"]
android:state_enabled=["true" | "false"]
android:state_activated=["true" | "false"]
android:state_window_focused=["true" | "false"] />
</selector>
表示Drawable集合,每个Drawable对应着View的一种状态,这样系统就会根据View的状态来选择合适的Drawable。
属性:
android:constantSizeDrawable的固有大小是否不随着其状态的改变而改变,默认值为false。
android:dither抖动效果是否开启,默认为true
android:variablePaddingDrawable的padding表示是否随着状态的改变而改变,默认false。
item标签表示一个具体的Drawable。
2.6.LevelListDrawable
<?xml version="1.0" encoding="utf-8"?>
<level-list
xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:drawable="@drawable/drawable_resource"
android:maxLevel="integer"
android:minLevel="integer" />
</level-list>
表示Drawable集合,集合中的每个Drawable都有一个等级的概念,根据不同的等级,Drawable会切换为对应的Drawable。
作为View的背景的时候,可以通过Drawable的setLevel方法来设置不同的等级从而切换具体的Drawable,被用作ImageView的前景时,可以通过ImageView的setImageLevel方法来切换Drawable。范围0-10000。
2.7.TransitionDrawable
<?xml version="1.0" encoding="utf-8"?>
<transition
xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:drawable="@[package:]drawable/drawable_resource"
android:id="@[+][package:]id/resource_name"
android:top="dimension"
android:right="dimension"
android:bottom="dimension"
android:left="dimension" />
</transition>
表示两个Drawable之间的淡入淡出效果。
可以使用它的startTransition和reverseTransition方法来实现淡入淡出的效果以及它的逆过程。
2.8.InsetDrawable
<?xml version="1.0" encoding="utf-8"?>
<inset
xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/drawable_resource"
android:insetTop="dimension"
android:insetRight="dimension"
android:insetBottom="dimension"
android:insetLeft="dimension" />
可以将其他Drawable内嵌到自己当中,并可以在四周留出一定的间距。当一个view希望自己的背景比自己的实际区域小的时候,可以采用它实现。
<?xml version="1.0" encoding="utf-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:insetBottom="15dp"
android:insetLeft="15dp"
android:insetRight="15dp"
android:insetTop="15dp" >
<shape android:shape="rectangle" >
<solid android:color="#ff0000" />
</shape>
</inset>
shape距离view的边界15dp。
2.9.ScaleDrawable
<?xml version="1.0" encoding="utf-8"?>
<scale
xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/drawable_resource"
android:scaleGravity=["top" | "bottom" | "left" | "right" | "center_vertical" |
"fill_vertical" | "center_horizontal" | "fill_horizontal" |
"center" | "fill" | "clip_vertical" | "clip_horizontal"]
android:scaleHeight="percentage"
android:scaleWidth="percentage" />
可以根据自己的等级level将指定的Drawable缩放到一定的比例。android:scaleHeight,android:scaleWidth分别表示对指定Drawable宽和高的缩放比例,以百分比的形式表示。想要ScaleDrawable可见,需要等级不能为0。范围0-10000。
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/image_bg"
android:scaleHeight="70%"
android:scaleWidth="70%"
android:scaleGravity="center" />
View testScale = findViewById(R.id.test_scale);
ScaleDrawable testScaleDrawable = (ScaleDrawable) testScale.getBackground();
testScaleDrawable.setLevel(10);
2.10.ClipDrawable
<?xml version="1.0" encoding="utf-8"?>
<clip
xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/drawable_resource"
android:clipOrientation=["horizontal" | "vertical"]
android:gravity=["top" | "bottom" | "left" | "right" | "center_vertical" |
"fill_vertical" | "center_horizontal" | "fill_horizontal" |
"center" | "fill" | "clip_vertical" | "clip_horizontal"] />
可以根据自己的等级level来裁剪另一个Drawable。
将一张图片从上到下裁剪:
<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
android:clipOrientation="vertical"
android:drawable="@drawable/image_bg"
android:gravity="bottom" />
ImageView testClip = (ImageView) findViewById(R.id.test_clip);
ClipDrawable testClipDrawable = (ClipDrawable) testClip.getDrawable();
testClipDrawable.setLevel(8000);
等级设置为8000表示,裁剪2000,在顶部裁掉20%。