阅读本章将了解:
Drawable是没有大小概念的,当用作view的背景时,Drawable会被拉伸到view同等大小
6.2、Drawable的分类
Drawable的种类繁多,常见的有BitmapDrawable、ShapeDrawable、LayerDrawable、StateListDrawable
6.2.1、BitmapDrawable :最简单的drawable
我们可以通过xml的方式来描述它,常见属性有:
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
//图片的资源id
android:src="@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"]
//平铺模式(默认关闭,当开启平铺时,gravity属性无效)
android:tileMode=["disabled" | "clamp" | "repeat" | "mirror"] />
下面我们来看看效果
需要注意的是:想要有平铺的效果,那么你的控件就必须要比你引用的图片尺寸要大
NinePatchDrawable,它表示一个.9的图片,跟BitmapDrawable 使用方式一样
6.2.2、ShapeDrawable
通过颜色来构造图形
常见属性有:
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
//rectangle(矩形)oval椭圆line横线ring圆环
android:shape=["rectangle" | "oval" | "line" | "ring"] >
<corners //当shape为rectangle时使用
android:radius="integer" //半径值会被后面的单个半径属性覆盖,默认为1dp
android:topLeftRadius="integer"
android:topRightRadius="integer"
android:bottomLeftRadius="integer"
android:bottomRightRadius="integer" />
<gradient //渐变
//渐变的角度,默认是0,值必须是45的倍数,0表示从左到右,90表示从上到下
android:angle="integer"
//渐变中心点的横坐标
android:centerX="integer"
//渐变中心点的纵坐标
android:centerY="integer"
//渐变的起始色
android:startColor="color"
//渐变的中间色
android:centerColor="integer"
//渐变的结束色
android:endColor="color"
//渐变半径,仅当android:type = "redial"时有效
android:gradientRadius="integer"
//渐变的类别:linear :线性渐变,radial:径向渐变,sweep:扫描线渐变
android:type=["linear" | "radial" | "sweep"]
//一般是false
android:useLevel=["true" | "false"] />
<padding //内边距
android:left="integer"
android:top="integer"
android:right="integer"
android:bottom="integer" />
<size //指定大小,一般用在imageview配合scaleType属性使用
android:width="integer"
android:height="integer" />
<solid //填充颜色
android:color="color" />
<stroke //边框
android:width="integer"
android:color="color"
android:dashWidth="integer"
android:dashGap="integer" />
</shape>
具体解释如下:
android:shape :表示图形的形状
<corners>:表示4个角的角度,只适用于shape是rectangle(矩形)的情况
<gradient> :它与<solid>是互相排斥的,<solid>表示纯色,<gradient>表示渐变
<solid> :纯色填充,通过andorid:color可以指定shape中填充的颜色
<stroke> :Shape的描边
android:width:描边的宽度,越大边框就越粗
android:color:描边的颜色
android:dishWidth:组成虚线的线段宽度
android:dishGap:组成虚线的每个线段之间的间隔空隙
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="#ff0000" />
<stroke
android:dashGap="2dp"
android:dashWidth="10dp"
android:width="2dp"
android:color="#00ff00" />
</shape>
<padding>:表示包含它的view与它的pading间距
<size> :shape的固有宽高,但是当作为view的背景时,这个宽高的意义就不大了。
6.2.3、LayerDrawable
对应的xml标签是: :重叠放置达到效果,类似FramLayout
一个 可以包含多个,下面的item会覆盖上面的item,每个item的常用属性是:
andorid:top = ""
andorid:bottom = ""
andorid:left = ""
andorid:right = ""
代表相对view的上下左右的偏移量
andorid:drawable = “@drawable/ic_est”
代表引用drawable资源
代码如下一个小例子:
<?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>
6.2.4、StateListDrawable
StateListDrawable对应的是我们常用的标签,常用属性如下:
android:constanSize :默认为false,表示固有大小是否随着包含的View的改变而改变
android:dither:是否开启抖动效果,默认true,让在低质量的屏幕上有较好效果
android:variablePadding:是否随着其状态的改变而改变,默认是false,不建议开启此选项
<item>标签表示一个具体的Drawable
android:drawable表示资源ID,其他表示drawable的各种状态
用的比较多,就不举例了。
6.2.5、LevelListDrawable
LevelListDrawable对应标签,同样表示一个drawable集合,根据不同的level(等级),会切换到对应的drawable
基本用法如下:
通过minLevel和maxLevel来设置等级,0~10000之间
使用场景:
有时候,我们为了在一个ImageView中显示不同的图片,往往会使用:
if (条件1)
{
image.setBackground(R.id.xxx1);
}
else if (条件2)
{
image.setBackground(R.id.xxx2);
} ...
可以用另一个简便的方法实现相同的功能
首先,在res/drawable下建立一个xml文件,内容如下
<level-list xmlns:Android="http://schemas.android.com/apk/res/android">
<item android:maxLevel="0" android:drawable="@drawable/battery_0" />
<item android:maxLevel="1" android:drawable="@drawable/battery_1" />
<item android:maxLevel="2" android:drawable="@drawable/battery_2" />
<item android:maxLevel="3" android:drawable="@drawable/battery_3" />
<item android:maxLevel="4" android:drawable="@drawable/battery_4" />
</level-list>
然后在layout中把image view的src设置成已创建好的xml文件
程序中变换图片时,只需要使用
imageview.getDrawable().setImageLevel(1);
…
Android会根据level的值自动选择对应的图片。手机显示剩余电量就是用这个方法来显示不同图片的。
6.2.6、TransitionDrawable
TransitionDrawable对应标签,transition是过渡,转变的意思,
对应于andnorid中的淡入淡出效果
基本使用如下:
![]()
代表相对于包含的view的上下左右的偏移量
具体使用如下:线性渐变转为径向渐变
<TextView
android:id="@+id/test_transition"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="@drawable/transition_drawable"
android:gravity="center"
android:text="" />
<?xml version="1.0" encoding="utf-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="@drawable/shape_drawable_gradient_linear"/>
<item android:drawable="@drawable/shape_drawable_gradient_radius"/>
</transition>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<gradient
android:centerColor="#00ff00"
android:endColor="#0000ff"
android:startColor="#ff0000"
android:centerX="0.5"
android:centerY="0.5"
android:angle="0"
android:type="linear" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<gradient
android:centerColor="#00ff00"
android:endColor="#0000ff"
android:startColor="#ff0000"
android:gradientRadius="60"
android:type="radial" />
</shape>
使用方法:
View v = findViewById(R.id.test_transition);
TransitionDrawable drawable = (TransitionDrawable) v.getBackground();
drawable.startTransition(1000);
拓展:
Android Transition Framwork 主要用来做三件事:
1. Activity间的转场动画;
2. 不同Activity或Fragment间元素共享,让交互更连贯;
3. 同一个Activity之间一些View的变换动画。
参见:http://www.jianshu.com/p/0af52be90ae6
6.2.7、InsetDrawable
insertDrawable对应标签,它可将其他Drawable内嵌到自己当中,适用于当一个view希望自己的背景比自己小的时候,LayerDrawable也可以实现这样的效果
基本用法如下:
这4个属性分别代表上下左右内凹的间距
<?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>
如图所示
6.2.8、ScaleDrawable
对应标签,可以根据自己的等级,将scale缩放的一定的比例
基本用法如下:
android:scaleGravity表示位置
android:scaleHeight和android:scaleWidth表示对指定drawable(即android:drawable = “”)的宽高缩放比例,单位为百分比
比如:
android:scaleHeight = 20%
下面一个案例来说明让一个图片缩小为原大小的30%
在res/drawable/scale.xml
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/image1"
android:scaleHeight="70%"
android:scaleWidth="70%"
android:scaleGravity="center" />
<TextView
android:id="@+id/test_scale"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="@drawable/scale"
android:gravity="center"
android:text=""
android:textColor="#ffffff" />
直接使用drawable资源是不行的,还要使用代码设置下等级为大于0小于10000的值
// test scale
View testScale = findViewById(R.id.test_scale);
ScaleDrawable testScaleDrawable = (ScaleDrawable) testScale.getBackground();
testScaleDrawable.setLevel(10);
6.2.8、ClipDrawable
ClipDrawable对应标签,可以根据当前等级来裁剪一个drawable
裁剪方向由android:clipOritation和andorid:grarity共同设置
基本用法如下:
android:clipOritation和LineaLayout的属性差不多,纵向和横向
andorid:grarity表示裁剪的方向
比如:bottom表示从上往下裁剪
下面举个例子,实现一张图片从上往下裁剪的效果:
首先在res/drawable/clip.xml
<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
android:clipOrientation="vertical"
android:drawable="@drawable/image1"
android:gravity="bottom" />
然后设置给view当做背景
<ImageView
android:id="@+id/test_clip"
android:layout_width="100dp"
android:layout_height="100dp"
android:gravity="center"
android:src="@drawable/clip" />
然后在代码中设置等级,同理这个等级也是0~10000之间,0表示完全裁剪(就啥都没有了),10000表示不裁剪(跟没裁剪一样)
// test clip
ImageView testClip = (ImageView) findViewById(R.id.test_clip);
ClipDrawable testClipDrawable = (ClipDrawable) testClip.getDrawable();
testClipDrawable.setLevel(8000);
我们这里设置等级为8000,表示保留8000,裁剪掉了2000,即20%的区域
6.3、自定义Drawable
drawable的使用很单一,作为imageView的图像展示和作为view的背景展示
第五章中,我们知道系统会调用drawable的draw方法来绘制view的背景,那么我们也可以重写drawable的draw方法来自定义drawable
通常我们不需要去自定义drawable,因为自定义的drawable无法在xml中直接使用
特殊情况下,我们想自定义drawable也是可以的
下面我们来自定义drawable 来绘制一个圆形的drawable,并且半径会随着view的变化而变化
步骤如下:
1、继承drawable类
2、draw,setAlpha,setcolorFilter,getOpacity这几个方法是必须要实现的,draw是主要方法
完整代码如下:
package com.ryg.chapter_6.ui;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
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 r = getBounds();
float cx = r.exactCenterX();
float cy = r.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 cf) {
mPaint.setColorFilter(cf);
invalidateSelf();
}
@Override
public int getOpacity() {
// not sure, so be safe
return PixelFormat.TRANSLUCENT;
}
}