Drawable 的分类
1 BitmapDrawable:
BitmapDrawable
算是最常见的Drawable
之一,我们构造一个Bitmap
对象的时候,有时候会用到BitmapDrawable
,那么BitmapDrawable
的构造,除了在代码中new
一个BitmaDrawable
之外,我们还可以使用XML来构造一个BitmapDrawable
对象,在项目的drawable
文件中新创建一个xml
文件,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:antialias="true"
android:dither="true"
android:filter="true"
android:gravity="center"
android:mipMap="true"
android:src="drawable/xmyh"
android:tileMode="clamp">
</bitmap>
-
android:src
这个是资源,可以是图片也可以是颜色 -
android:antialias
是否开启图片抗锯齿,开启后图片会变得平滑一点,同时也会在一定程度上降低清晰度,不过这个降低我们完全可以无视,所以这个可以开启 -
android:dither
是否开启抖动效果,当图片的像素配置和手机不一致的时候,开启这个选项可以让高质量的图片在低分辨率的屏幕上保持比较好的显示效果,比如图片的色彩模式ARGB8888,但是设备只支持RGB555,这个时候开启抖动模式可以让图片不会过于失真,在Android中创建的Bitmap一般会使用ARGB8888这个模式,即ARGB四个通道各占8位,在这个色彩下,一个像素所占为4个字节,一个像素的位数综合越高,图片越逼真,抖动也应该开启。 -
android:gravity,可以选项比较多,不同的选项可以取值可以荣国 “ | ”组合使用可以取值
可选项 | 含义 |
---|---|
top | 将图片放在容器顶部,不改变图片大小 |
bottom | 将图片放在容器底部,不改变图片大小 |
left | 将图片放在容器左侧,不改变图片大小 |
right | 将图片放在容器右侧,不改变图片大小 |
center_vertical | 是图片垂直居中,不改变图片大小 |
fill_vertical | 图片垂直方向填充容器 |
center_horizontal | 图片水平居中,不改变图片大小 |
fill_horizontal | 图片水平方向填充容器 |
center | 图片在水平和竖直方向同时居中 ,不改变图片大小 |
fill | 图片在水平和竖直方向均填充容器,默认值 |
clip_vertical | 竖直方向裁剪,较少使用 |
clip_horizontal | 水平方向裁剪,较少使用 |
- android:mipMap
这是一种图片相关的处理技术,也叫纹理映射,比较抽象,默认为false,不常用 - android:filter
是否开启过滤效果,当图片尺寸被拉伸或者压缩时,开启过滤效果会保持比较好的显示效果,所以这个也可开启。 - android:tileMode
平铺模式,有四种选项[“disabled” | “clamp” | “repeat” | “mirror”]。当开启平铺模式后,gravity属性会被忽略。repeat是指水平和竖直方向上的平铺效果;mirror是指在水平和竖直方向上的镜面投影效果;clamp是指图片四周的像素会扩展到周围区域,这个比较特别。
还有.9图片的使用
<?xml version="1.0" encoding="utf-8"?>
<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
android:dither="true"
android:src="@drawable/nine_pic">
</nine-patch>
.9图片的使用大多在可拉伸图片的场景下使用。例如微信聊天的文字背景,语音背景就是简单地例子。
2 ShapeDrawable
ShapeDrawable
主要用来画一些 shape,和各种颜色。语法比较多。
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="line">
<corners
android:bottomLeftRadius="10dp"
android:bottomRightRadius="10dp"
android:radius="10dp"
android:topLeftRadius="10dp"
android:topRightRadius="10dp" />
<gradient
android:angle="10"
android:centerColor="@color/colorPrimary"
android:centerX="10"
android:centerY="10"
android:endColor="@color/colorPrimary"
android:gradientRadius="10dp"
android:startColor="@color/colorAccent"
android:type="linear"
android:useLevel="true" />
<padding
android:bottom="10dp"
android:left="10dp"
android:right="10dp"
android:top="10dp" />
<size
android:width="100dp"
android:height="100dp" />
<solid android:color="@color/colorAccent" />
<stroke
android:width="100dp"
android:color="@color/colorPrimaryDark"
android:dashGap="@dimen/activity_horizontal_margin"
android:dashWidth="10dp" />
</shape>
-
android:shape
表示图片的形状,有四个选项,line(横线),oval(椭圆),rectangle(矩形),ring(圆环),他的默认值是矩形,而且line(横线)和ring(圆环)都必须通过stroke标签来指定宽高,颜色等信息,否则无法达到预期的效果 -
针对
ring
的形状,有五个特殊的属性
android:innerRadius
android:tickness
android:innerRadiusRatio
android:ticknessRatio
android:useLevel
value | 含义 |
---|---|
android:innerRadius | 圆环的内半径,和 android:innerRadiusRatio同时存在时候以 前者为准 |
android:tickness | 圆环厚度,即外半径减去内半径,android:innerRadiusRatio同时存在时候以 前者为准 |
android:innerRadiusRatio | 内半径占整个drawable的比例 ,默认为9,如果为n,内半径=宽度/n |
android:ticknessRatio | 厚度占整个宽度的比例,默认为3,如果为n,厚度=宽度/n |
android:useLevel | 一般使用false,除非被当做LeveListDrawable 使用 |
-
表示shape的四个角度,它只是用于矩形的shape,这里的角度是指圆角的成都,用px来表示,他有五个属性
android:radius
:为四个角同时设置相同的角度,优先级较低,会被其他四个覆盖
android:topLeftRadius
:设置最上角的角度
android:topRightRadius
:设置右上角的角度
android:bottomLeftRadius
:设置最下角的角度
android:bottomRightRadius
:设置右下角的角度 -
< gradient>
他与solid标签是互相排斥的,因为solid表示纯色,而他表示渐变,属性如下
android:angle
:渐变的角度,默认为0,其值必须为45的倍数,0表示从左往右,90表示从上到下
android:centerColor
:渐变的中心颜色
android:centerX
:渐变中心点的横坐标
android:centerY
:渐变中心点的纵坐标
android:endColor
:渐变的结束颜色
android:gradientRadius
:渐变半径,只有当type = radial 时才有效
android:startColor
:渐变的开始颜色
android:type
:渐变的类型 (linear–线性、radial–径向渐变、sweep–扫描渐变,线性渐变默认)
android:useLevel
:false -
< solid>
这个标签表示纯色填充,通过android:color
来表示填充颜色 -
shape的描边
android:width
:宽度
android:color
:颜色
android:dashwidth
:虚线线段的宽度
android:dashGap
:组成虚线的线段之间的间隔
注意:如果android:dashGap
和android:dashwidth
有任何一个为0的话,那么虚线就不能生效了 -
< padding>
这个表示空白,但是他表示的不是shape的空白,而是包含他view的空白,而且有四个属性
android:left
android:right
android:top
android:bottom
类似View 的padding -
< size>
shape的大小,有两个属性,android:width
和android:height
分别表示shape的宽和高。但是作为背景的时候,会被拉伸或者缩放为View 的宽和高。
整体的看一些例子
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="line">
<stroke
android:width="4dp"
android:color="@android:color/holo_red_light"
android:dashGap="4dp"
android:dashWidth="4dp" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke
android:width="4dp"
android:color="@android:color/holo_red_light"
android:dashGap="4dp"
android:dashWidth="4dp" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke
android:width="4dp"
android:color="@android:color/holo_red_light" />
<corners
android:radius="20dp" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="ring"
android:innerRadius="10dp"
android:thickness="20dp"
android:useLevel="false">
<stroke
android:color="@android:color/holo_red_light"
android:width="4dp"
/>
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="ring"
android:innerRadius="10dp"
android:thickness="50dp"
android:useLevel="false">
<stroke
android:width="0dp"
android:color="@android:color/holo_red_light"
/>
<gradient
android:type="sweep"
android:startColor="@android:color/holo_red_light"
android:endColor="@android:color/holo_blue_bright"
/>
</shape>
具体看需求
-
3 LayerDrawable
LayerDrawable
对应的xml是<layer-list>
,他可以理解为图层,通过不同的view达到叠加的效果
属性很简单,一个layer-list包含多个item,形成叠加的图层效果,我们可以看一个例子<?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="#f00" /> </shape> </item> <item android:bottom="111dp"> <shape android:shape="rectangle"> <solid android:color="#fff" /> </shape> </item> <item android:bottom="1dp" android:left="1dp" android:right="1dp"> <shape android:shape="rectangle"> <solid android:color="#fff"/> </shape> </item> </layer-list>
-
4 StateListDrawable
StateListDrawable
对应的是<selector>
标签,他会根据view
的状态来选择出现的drawable
,语法如下<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android" android:constantSize="true" android:dither="true" android:variablePadding="true"> <item android:drawable="@drawable/ic_launcher" android:state_pressed="true" android:state_focused="true" android:state_hovered="true" android:state_selected="true" android:state_checkable="true" android:state_checked="true" android:state_enabled="true" android:state_activated="true" android:state_window_focused="true" /> </selector>
-
android:constantSize
StateListDrawable
的固有大小是不随其状态的改变发生改变的,因为状态的改变会导致他切换不同的drawable
,而不同的drawable
具有不同的drawable
,true
表示StateListDrawable
的固有大小不变,这时他的固有大小就是内部所有drawable
的固有大小的最大值,false
则是跟随状态改变,默认false
-
android:dither
是否开启抖动效果,这个在之前就已经提过,开启此选项可以让图片在低质量的屏幕上显示较好的效果,默认为true
-
android:variablePadding
StateListDrawable
的pading
是跟随其状态发生改变的而改变,fasle
为最大值,跟constantSize
类似,不建议开启,默认false
<item>
标签标示的是一个具体的Drawable
,他的结构也比较简单,其中drawable
标示已经资源的id,剩下的就是各种状态了:含义 roid:state_pressed roid:state_focused roid:state_selected roid:state_checked roid:state_enabled roid:state_hovered roid:state_checkable roid:state_activated roid:state_window_focused
来看一个例子吧:
``` <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android" android:constantSize="false" android:dither="true" android:variablePadding="true"> <item android:drawable="@color/gray" android:state_pressed="true" /><!--press--> <item android:drawable="@color/white" /> <!--normal--> </selector> ```
图片按下去的时候是另外一种状态,背景颜色会发生改变,这就是所谓的背景选择器,大多用在按钮。当然也可以给其他空间来定义属于它们的漂亮的选择器 -
-
5 LevelListDrawable
LevenlListDrawable
对应着标签,同样表示一个drawable
的集合。集合中的每一个Drawable
都有一个等级,根据不同的等级切换不同的Item
<?xml version="1.0" encoding="utf-8"?> <level-list xmlns:android="http://schemas.android.com/apk/res/android" > <item android:drawable="@color/red" android:maxLevel="1" /> <item android:drawable="@color/orange" android:maxLevel="2" /> <item android:drawable="@color/green" android:maxLevel="3" /> </level-list>
这样的等级在我们的APP 中还是很常见的比如:输入密码的时候等级检测旁边就会显示不同颜色的密码等级;在五星好评也可以使用这种思路来做(LayerDrawable 和 此LevenlListDrawable相结合)。
-
6 TransitionDrawable
TransitionDrawable
对应的是用于实现两个Drawable
的淡入淡出语法如下:
<?xml version="1.0" encoding="utf-8"?> <transition xmlns:android="http://schemas.android.com/apk/res/android"> <item android:bottom="@dimen/activity_horizontal_margin" android:drawable="@color/colorAccent" android:left="@dimen/activity_horizontal_margin" android:right="@dimen/activity_horizontal_margin" android:top="@dimen/activity_horizontal_margin" /> </transition>
android:bottom
android:left
android:right
android:top
对应着drawable
在对应方向上面的margin。
大多数用于View
的drawable
属性,图片的淡入淡出效果,如下
<?xml version="1.0" encoding="utf-8"?> <transition xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@color/colorAccent" /> <item android:drawable="@color/colorPrimary" /> </transition>
接着将上面的设置为View的背景,最后通过startTransition和resetTransition来操作
TransitionDrawable drawable = (TransitionDrawable) view.getBackground(); drawable.startTransition(1000);
-
7 InsetDrawable
InsetDrawable对应的是,他可以将其他的Drawable内嵌到自己当中,并且可以在四周留下一定的距离
<?xml version="1.0" encoding="utf-8"?> <inset xmlns:android="http://schemas.android.com/apk/res/android" android:insetBottom="60dp" android:drawable="@color/red" android:insetLeft="30dp" android:insetRight="30dp" android:insetTop="60dp" > </inset>
-
8 ScaleDrawable
ScaleDrawable
对应的是,他可以指定自己的等级将指定的Drawable
缩放带一定的比例,语法如下<?xml version="1.0" encoding="utf-8"?> <scale xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@mipmap/ic_launcher" android:scaleGravity="center" android:scaleHeight="10%" android:scaleWidth="50%"> </scale>
在上门的属性中,
scaleGravity
的含义等同于shape中的gravity,而这个宽高就是缩放比例,以百分比的形式
android:scaleHeight
的百分比越大图片上线高度就比较低,值越小,上线拉伸的高度越高。注意:在使用的时候还要配合这个代码ImageView view = (ImageView) findViewById(R.id.imgView); ScaleDrawable drawable = (ScaleDrawable) view.getDrawable(); drawable.setLevel(1); // 这个数值小于10000就好
因为这个
ScaleDrawable
源码中有这么一段代码@Override public void draw(Canvas canvas) { final Drawable d = getDrawable(); if (d != null && d.getLevel() != 0) { d.draw(canvas); } }
-
9 ClipDrawable
ClipDrawable
对应的是<clip>
标签,他可以根据自己的等级裁剪另一个Drawable
,裁剪的方法可以通过android:clipOrientation
和android:gravity
来共同控制,先看下语法<?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"] />
其中
android:clipOrientation
表示裁剪方向,android:gravity
可选参数比较多,可以通过|
符号来组合使用。
下面我们举个例子来实现一张图片从上往下进行裁剪的效果,那么我们定义一个ClipDrawable
<?xml version="1.0" encoding="utf-8"?> <clip xmlns:android="http://schemas.android.com/apk/res/android" android:clipOrientation="vertical" android:gravity="bottom"> <shape android:shape="rectangle" > <solid android:color="@color/green"/> </shape> </clip>
ImageView 的使用
<ImageView android:layout_width="18dp" android:layout_height="40dp" android:id="@+id/imgView" android:background="@drawable/clip_drawable"/>
在配合如下代码设置一下Level.
ImageView view = (ImageView) findViewById(R.id.imgView); mClipDrawable = (ClipDrawable)view.getBackground(); mClipDrawable.setLevel(50*100);
这个知识点我做了一个小电池充电的效果 : 充电效果demo
-
10 自定义Drawable
drawable
的用途很简单,就是给View
做背景,或者作为ImageView
的图像演示。其中最重要的就是onDraw
方法public class CustomDrawable extends Drawable { private Paint mPaint; public CustomDrawable(int color) { mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setColor(color); } @Override public void draw(Canvas canvas) { final Rect f = getBounds(); float cx = f.exactCenterX(); float cy = f.exactCenterY(); canvas.drawCircle(cx, cy, Math.min(cx, cy), mPaint); } @Override public void setAlpha(int alpha) { mPaint.setAlpha(alpha); invalidateSelf(); } @Override public void setColorFilter(ColorFilter colorFilter) { mPaint.setColorFilter(colorFilter); invalidateSelf(); } @Override public int getOpacity() { return PixelFormat.TRANSLUCENT; } }
上面的例子中这几个方法都必须要实现,虽然简单,但是五脏俱全。