Drawable表示了可绘制对象。
getIntrinsicWidth/getIntrinsicHeight获取固有的宽高。对于BitmapDrawable来说,该方法返回其图片的宽高,对于shape类型的,默认返回-1。显示在View中的drawable会被拉伸或缩小为View的大小,固有宽高和其最终显示在View中的宽高不一定相等。
一部分Drawable中用到的level的范围是0-10000。
1.分类
- BitmapDrawable
支持png/jpg/gif。可以直接通过resource id使用原始图片,或者在xml创建一个他的resource id别名。因为在build的过程中无损图片会被优化,放在res/raw下可以防止被优化。
<?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"] />
- android:src
资源id - android:antialias
抗锯齿 - android:dither
简单的说就是用现有的显示终端能够识别的颜色来模拟产生出其不能产生的像素,也就是用较小数量的颜色去模拟更多数量的颜色,如在16位色设备上显示24位色图片。就是牺牲分辨率换取更多感知颜色数。 - android:filter
用于图片拉伸或收缩时,可以保持较好的显示效果。 - android:gravity
设置图片小于其容器时在其容器中的位置。 - android:mipMap
纹理映射。 - android:tileMode
平铺模式。开启之后gravity会失效。repeat:在水平和竖直方向平铺;mirror:水平和垂直方向平铺,相邻的图片是镜像的;clamp:在超出图片原始边界的地方,复制其边缘的颜色。
- 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"] />
- ShapeDrawable
xml resource会被编译为GradientDrawable。
<?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="float"
android:centerY="float"
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>
- android:shape
rectangle:矩形,会填充其View。默认值。
oval:椭圆,会填充其View。
line:水平线,其宽度贯穿了其View。需要使用<stroke>
指定其线宽。
ring:圆环。
针对ring的5个属性: - android:innerRadius
圆环中心孔洞的半径。 - android:innerRaduisRatio
圆环中心孔洞的半径,用圆环宽度的比例表示。默认值为9,则innerRadius=width/9。该值会被android:innerRadius覆盖。 - android:thickness
圆环厚度。 - android:thicknessRatio
圆环厚度,用圆环宽度的比例表示。默认值为3,则thickness=width/9。该值会被android:thickness。 - android:useLevel
被当作LevelListDrawable时,设置为true。其他情况设置为false。
- android:shape
<corner>
矩形的圆角度数。用于rectangle。
android:radius 会被其他四个属性覆盖。
android:topLeftRadius
android:topRightRadius
android:bottomLeftRadius
android:bottomRightRadius
tips:每个corner的初始值要设置为大于1的值,否则所有的corner都没有圆角。如果希望某几个corner没有圆角,可以通过radius设置一个大于1的默认值,然后对需要有圆角的设置相应的值,不需要有圆角的设置为0dp。<gradient>
渐变色填充。
android:angle 渐变角度。0为左到右,必须为45倍数,逆时针旋转。默认为0。
android:centerX
android:centerY
android:centerColor
android:endColor
android:gradientRadius 渐变半径,type为radial时有效。
android:startColor
android:type linear线性,radial径向,sweep扫描。<solid>
纯色填充。<stroke>
描边。
android:width
android:color
android:dashWidth 虚线线段宽度
android:dashGap 虚线线段间距<padding>
指定其与其View的padding<size>
实则shape的固有宽高。shape类型的drawable默认没有固有宽高,getIntrinsicWidth/getIntrinsicHeight返回-1。设置了该属性后,会返回相应的值,但是作为View背景的时候,还是会被相应的拉伸或缩小。
- LayerDrawable
多个drawable叠加
<?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>
<item>
定义了一个drawable。可以包含<bitmap>
标签。
left/right/top/bottom表示的是offset。
默认情况下,drawable会缩放至View的大小,为了避免缩放,在item中使用bitmap的时候,使用bitmap标签,同时使用gravity设置不缩放的参数。
- 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>
<selector>
android:constantSize 其固有大小是否不随着state的改变而改变。
android:variablePadding 其padding是否会随着状态的改变而改变。- item的匹配顺序为从上至下,所以默认状态的drawable要放在最下面。
- 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>
通过setLevel方法或者ImageView的setImageLevel方法,使maxLevel>=level的item得到显示。
7. TransitionDrawable
实现两个drawable的淡入淡出。item不能超过两个。
<?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>
示例
<?xml version="1.0" encoding="utf-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/on" />
<item android:drawable="@drawable/off" />
</transition>
<ImageButton
android:id="@+id/button"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@drawable/transition" />
ImageButton button = (ImageButton) findViewById(R.id.button);
Drawable drawable = button.getDrawable();
if (drawable instanceof TransitionDrawable) {
((TransitionDrawable) drawable).startTransition(500);
}
- InsetDrawable
嵌入其他的drawable,并在四周留有一定的距离。当需要给View设置一个比起边界小的背景时可以用到。
<?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" />
9.ScaleDrawable
依据drawable的level将其缩放到一定的比例。
<?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" />
w -= (int) ((w - iw) * (MAX_LEVEL - level) * mState.mScaleWidth / MAX_LEVEL);
level越大,drawable越大;指定的percentage越大,drawable越小。在使用时,level不能为0,否则直接不显示。
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的裁剪。level为0为完全裁剪。经常用在进度条。
<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/android"
android:clipOrientation="horizontal"
android:gravity="left" />
<ImageView
android:id="@+id/image"
android:background="@drawable/clip"
android:layout_height="wrap_content"
android:layout_width="wrap_content" />
ImageView imageview = (ImageView) findViewById(R.id.image);
Drawable drawable = imageview.getBackground();
if (drawable instanceof CLipDrawable) {
((ClipDrawable)drawable).setLevel(drawable.getLevel() + 1000);
}
2.自定义Drawable
Drawable主要用于ImageView中的图像显示,以及View的背景。
View中绘制背景是调用了drawable的draw方法,所以通过实现draw方法可以实现自定义Drawable。
Drawable有固有大小时,需要实现getIntrinsicWidth/getIntrinsicHeight返回正确的数值。
区别于固有大小,实际大小通过getBounds获得。