- Drawable简介
- Drawable种类
- 自定义Drawable
一.Drawble简介
1.简介
Drawable是个抽象类,是所有Drawable对象的基类.它表示是一种可以在Canvas上进行绘制的抽象的概念.比较常见的颜色和图片就是一个Drawable.
2.优点
它使用简单,比自定义View的成本低,并且非图片类型的Drawable占用空间较小
3.Drawable的宽高
Drawable可以通过getIntrinsicWidth和getIntrinsicHeight这两个方法获取内部宽高,但是并不是所有Drawble都有内部宽高,比如一张图片所形成的Drawble,它的内部宽高就是图片的宽高,而一个颜色所形成的Drawble,就没有内部宽高的概念.另外需要注意,Drawable的内部宽高不等同于它的大小,一般来说,Drawable没有大小的概念.
二.Drawable的种类
- BitmapDrawable
- NinePatchDrawable
- ShapeDrawable
- LayerDrawable
- StateListDrawable
- LevelListDrawable
- TransitionDrawable
- InsetDrawable
- ScaleDrawable
- ClipDrawable
1.BitmapDrawable
(1)用xml定义BitmapDrawable
表示一张图片,可以引用原始图片,也可以通过xml的方式来描述.下面是通过xml来表示一张图片。
// res/drawable/bitmapdrawable_test.xml
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/ic_launcher_background"//图片的资源id
android:antialias="true"//抗锯齿,图片会更加平滑,但是会降低清楚度
android:dither="true"//是否开启抖动效果,开启后让高质量的图片适配低质量的屏幕,让图片不会失真
android:filter="true"//过滤效果,图片拉伸或压缩时,开启可以保持较好的显示效果
android:gravity="center"//显示位置
android:mipMap="false"//纹理映射,默认是false
android:tileMode="disabled">//平铺模式,开启后gravity属性会被忽略
</bitmap>
android:gravity属性的可选值如下图所示:
android:tileMode属性可选值如下图所示:
具体效果如图:
(2)具体使用
//xml中定义
<ImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bitmapdrawable_test"></ImageView>
//代码定义
ImageView imageView = findViewById(R.id.image);
//通过图片id获取bitmap
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.bitmapdrawable_test);
BitmapDrawable bitmapDrawable = new BitmapDrawable(bitmap);
bitmapDrawable.setAntiAlias(true);
bitmapDrawable.setGravity(Gravity.RIGHT);
bitmapDrawable.setTileModeXY(Shader.TileMode.MIRROR, Shader.TileMode.MIRROR);
imageView.setImageDrawable(bitmapDrawable);
//通过图片id获取drawable
Drawable drawable = getResources().getDrawable(R.drawable.bitmapdrawable_test);
imageView.setImageDrawable(drawable);
2.NinePatchDrawable
对应<nine-patch>
标签,表示一张.9格式图片:
表示一张.9格式图片,可以直接引用图片,也可以用xml表示.
<?xml version="1.0" encoding="utf-8"?>
<nine-patch xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/ic_launcher_background"
android:dither="true">
</nine-patch>
3.ShapeDrawable
对应<shape>
标签,通过颜色来构造的图形,它既可以是纯色的图形,也可以是具有渐变效果的图形.
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="[ring | rectangle | oval | line]">//圆环/矩形/椭圆/横线
<corners android:bottomLeftRadius="integer"//左下角的角度
android:topLeftRadius="integer"//左上角
android:topRightRadius="integer"//右上角
android:bottomRightRadius="integer"//右下角
android:radius="integer"/>//为四个角同时设定,优先级低
<gradient android:angle="integer"//渐变效果,与solid互斥,angle表示渐变角度,默认为0,值是45的倍数,0表示从左到右,90表示从上到下
android:centerX="integer"//渐变的中心点的x坐标
android:centerY="integer//渐变的中心点的y坐标
android:startColor="color"//渐变的起始色
android:centerColor="color"//渐变中间色
android:endColor="color"//渐变结束色
android:gradientRadius="integer"//渐变半径,仅当type为radial时有效
android:type="[radial | linear | sweep ]"//渐变类别(径向/线性/扫描线)
android:useLevel="[true | false]"/>//一般为false,使用SateListDrawable时为true
<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:color="color"//shape的描边
android:width="integer"//描边的宽度
android:dashGap="integer"//组成虚线的线段之间的间隔
android:dashWidth="integer"/>//组成虚线的线段的宽度
</shape>
其中圆环额外的几个属性:
4.LayerDrawable
对应<layer-list>
标签,表示一种层次化的Drawable集合
表示一种层次化的drawable集合.
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_launcher_background"
android:id="@+id/layer"
android:top="10dp"
android:right="10dp"
android:bottom="10dp"
android:left="10dp"/>
</layer-list>
可以有多个item,下面的item会覆盖上面的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="@color/colorPrimary"/>
</shape>
</item>
<item android:bottom="6dp">
<shape android:shape="rectangle">
<solid android:color="@color/colorAccent"/>
</shape>
</item>
<item android:bottom="1dp"
android:left="1dp"
android:right="1dp">
<shape android:shape="rectangle">
<solid android:color="@color/colorAccent"/>
</shape>
</item>
</layer-list>
5.StateListDrawable
对应于<selector>
标签,表示Drawable集合,每个Drawable都对应着View的一种状态,这样系统会根据View的状态来选择合适的Drawable,主要用于设置可点击的View的背景.
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:constantSize="false"//固有大小是否随着状态的改变而改变,默认false,会改变,true不会改变,是固定值,内部所有Drawable的固有大小中的最大值
android:dither="false"//是否开启抖动效果
android:variablePadding="false">//padding是否随状态的改变而改变,默认false,不会改变,是固定值,内部所有Drawable的padding的最大值
<item android:state_pressed="true"
android:drawable="@drawable/xxx"/>
<item android:state_focused="true"
android:drawable="@drawable/xxx"/>
<item android:drawable="@drawable/xxx"/>
</selector>
表示各种状态的属性:
6.LevelListDrawable
对应于<level-list>
标签,表示一个Drawable集合,集合中的每个Drawable都有一个等级的概念,根据不同的等级,LevelListDrawable会切换为对应的Drawable.等级范围是0-1000,0是最小等级,也是默认值.
<?xml version="1.0" encoding="utf-8"?>
<level-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/xxx"
android:maxLevel="5"
android:minLevel="1"/>
<item android:drawable="@drawable/xxx"
android:minLevel="6"
android:maxLevel="9"/>
</level-list>
//需要在代码中调用setLevel()方法,若作为ImageView背景,需调用setImageLevel()方法
//当某item的minLevel和maxLevel之间的数值 等于 setLevel所设置的数值时就会被加载。若都没有匹配的则都不显示
7.TransitionDrawable
对应<transition>
标签,用于实现两个Drawable之间的淡入淡出效果.
<?xml version="1.0" encoding="utf-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/drawable1"/>
<item android:drawable="@drawable/drawable2"/>
</transition>
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/transition"/>
TextView textView = findViewById(R.id.tv);
TransitionDrawable transitionDrawable = (TransitionDrawable) textView.getBackground();
transitionDrawable.startTransition(1000);
//反向切换
//transitionDrawable.reverseTransition(1000);
8.InsetDrawable
对应<inset>
标签,它可以将其它Drawable内嵌到自己当中,并可以在四周留出一定的距离.当一个View希望自己的背景比自己的实际区域小的时候,可以用InsetDrawable来实现.
<?xml version="1.0" encoding="utf-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:insetTop="15dp"
android:insetBottom="15dp"
android:insetLeft="15dp"
android:insetRight="15dp">
<shape android:shape="rectangle">
<solid android:color="@color/colorAccent"/>
</shape>
</inset>
9.ScaleDrawable
对应于<scale>
标签,它可以根据自己的等级将指定的Drawable缩放到一定比例.
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/ic_launcher_background"
android:scaleGravity="center"
android:scaleHeight="75%"
android:scaleWidth="75%">//比例越大,内部drawable看起来越小
</scale>
TextView textView = findViewById(R.id.tv);
ScaleDrawable scaleDrawable = (ScaleDrawable) textView.getBackground();
scaleDrawable.setLevel(1);
//level取值范围0到10000,但不能为0.
10.ClipDrawable
对应<clip>
标签,它可以根据自己当前的等级来裁剪另一个Drawable,裁剪的方向可以通过clipOrientation和gravity这两个属性来共同控制.
<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/ic_launcher_background"
android:clipOrientation="vertical"//裁剪的方向
android:gravity="bottom">//drawable放在容器中的位置
</clip>
ImageView imageView = findViewById(R.id.img);
ClipDrawable clipDrawable = (ClipDrawable) imageView.getDrawable();
clipDrawable.setLevel(8000);
//等级范围是0到10000,0表示完全裁剪,不可见,10000表示不裁剪,等级越大,表示裁剪的区域越小,上面代码表示顶部裁剪了20%的区域.
gravity属性的可选值有:
三.自定义Drawable
//它的主要功能,一个是作为ImageView中的图像来显示,一个是作为View的背景
//其工作原理,核心是draw()方法.
//自定义一个圆形的Drawable,它的半径会随着view的变化而变化.
public class CustomDrawable extends Drawable {
private final Paint mPaint;
public CustomDrawable(int color) {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(color);
}
@Override
public void draw(@androidx.annotation.NonNull Canvas canvas) {
Rect bounds = getBounds();
float cx = bounds.exactCenterX();
float cy = bounds.exactCenterY();
canvas.drawCircle(cx,cy,Math.min(cx,cy),mPaint);
}
@Override
public void setAlpha(int alpha) {
mPaint.setAlpha(alpha);
invalidateSelf();
}
@Override
public void setColorFilter(@androidx.annotation.Nullable ColorFilter colorFilter) {
mPaint.setColorFilter(colorFilter);
invalidateSelf();
}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
}