这次来把Drawable翻了个遍
前言
说到Drawable
,大家肯定都很熟悉,这不就是那个那个那个。。哪个?那个表示图片的东西吗?
遇到这种概念性问题,有的小伙伴可能跟我一样就有点蒙了,用是每天用,但真要我解释还真不好说,那么今天就来一起揭开的它的神秘面纱吧~
Drawable是什么
Drawable
表示的是一种可以在Canvas
上进行绘制的抽象的概念,种类很多,最常见的颜色和图片都可以是一个Drawable。
所以他是一种抽象的概念,是表示一种图像,但是又不全是图片,也可以表示颜色,一般被用作View的背景或者填充图。
到这里有的小伙伴可能又要问了,Canvas
又是什么呢?
Canvas一个矩形区域, 没有边界, 我们可以在上面调用任意drawXXX开头的方法绘制到引用的Bitmap上. 同时提供对图形的处理, 比如裁剪, 缩放, 旋转(需要Matrix对象配合使用). 所以Canvas与其说是画布, 不如说是一个绘制工具,它实际操作和存储的像素数据都在它的私有成员 Bitmap 对象中,所谓的画到Canvas画布上,其实就是画到其Bitmap,存储到其Bitmap变量中。
说到这,又要提下Bitmap
了:
Bitmap是一个存储格式, 存储了一个矩形区域内各像素点的信息. 这种格式适合显示, 但是存储效率低.可以理解为int[] buffer,用来保存每个像素的信息。
所以这三者的关系简单点就是:
Drawable
表示一个可以被绘制的图像,是一个抽象概念,需要通过Canvas
绘制到Bitmap上,作为一个图像的存储。所以Bitmap
是Drawable存在的一种实体。
Drawable分类
Drawable的种类很多,这里列举几个比较常用的以及用法:
BitmapDrawablw 最常用的Drawable,表示的就是一张图片,一张带规则的图片,可以设置一些规则,比较适用于对图片有限制的情况,比如背景图。
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:gravity="clip_horizontal|clip_vertical"
android:dither="true"
android:src="@drawable/start_bg"
android:tileMode="disabled"/>
<!--属性解释-->
<!--android:src 图片资源id-->
<!--android:antialias是否开启抗锯齿,开启后会更平滑,应该开启-->
<!--android:dither是否开启抖动效果,可以让高质量的图片在低质量的屏幕中还能保持较好的显示效果,应该开启-->
<!--android:filter是否开启过滤效果,应该开启-->
<!--android:gravity 当图片小于容器尺寸,可以设置图片定位,也就是图片的显示方式,和ImageVIew的scaleType类似,默认为fill-->
<!--android:mipMap纹理映射,一般为false-->
<!--android:tileMode平铺模式四个值:disabled(默认值即关闭平铺模式)、clamp、repeat、mirror-->
NinePatchDrawable 和BitmapDrawablw类似,使用时src传.9图片即可。实际上BitmapDrawablw也可以直接用.9图片,所以这个NinePatchDrawable没有太大的实际作用。
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" />
<!-- 表示渐变效果,和solid互斥 -->
<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"] />
<!-- 表示包含它的View的空白。 -->
<padding
android:left="integer"
android:top="integer"
android:right="integer"
android:bottom="integer" />
<!-- 表示shape的大小 -->
<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>
LayerDrawable
这是一种层次化的Drawable,相当于一种Drawable的布局嵌套,或者说集合,通过不同的Drawable放置到不同的层上达到一种叠加后的效果。
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<solid android:color="" />
</shape>
</item>
<item>
<bitmap android:src="@drawable/test" />
</item>
</layer-list>
StateListDrawble
一般用作点击效果,对应标签是selector,可以设置按下,点击后,不点击时候的各种状态。
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true" android:drawable="@drawable/test1">
</item>
<item android:state_enabled="false"
android:drawable="@drawable/test2">
</item>
</selector>
LevelListDrawable 和LayerDrawable类似,也是一个Drawable的集合,但是他是有等级的概念的,也就是可以通过设置不同的等级来展示对应的drawable,有点像一个有多种样式的Drawable,可以通过代码来展示哪一个样式。
<?xml version="1.0" encoding="utf-8"?>
<level-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/test1" android:maxLevel="0"/>
<item android:drawable="@drawable/test" android:maxLevel="1"/>
</level-list>
可以通过ImageView的setImageLevel方法来切换Drawable。
TransitionDrawable
该Drawable可以实现两个Drawable之间的淡入淡出,对应的标签是transition。
<?xml version="1.0" encoding="utf-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/test1"/>
<item android:drawable="@drawable/test2"/>
</transition>
可以通过代码中进行动画切换:
TransitionDrawable drawable = (TransitionDrawable) iv.getDrawable();
//切换到第2个item
drawable.startTransition(1000);
//切回到第1个item
drawable.reverseTransition(1000);
InsetDrawable 可以将其他的Drawable内嵌到自己当中,当一个View希望自己的背景比自己的实际区域小的时候,就可以采用这个,通过LayerDrawable也可以实现。一般用作加大点击区域。
<?xml version="1.0" encoding="utf-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/onepiece"
android:insetBottom="20dp"
android:insetLeft="20dp"
android:insetRight="20dp"
android:insetTop="20dp">
</inset>
ScaleDrawable
用于缩放,并且和它的等级Level有关,等级为0则不可见。
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/image"
android:scaleGravity="center_vertical|center_horizontal"
android:scaleHeight="50%"
android:scaleWidth="50%" />
使用的时候必须设置等级:
ScaleDrawable drawable = (ScaleDrawable) imageview.getDrawable();
drawable.setLevel(1);
ClipDrawable 用作裁剪,会根据自己的等级来裁剪一个Drawable,等级0表示完全裁剪,即整个Drawable都不可见,等级10000表示不裁剪,所以主要是通过控制drawable的等级来完成裁剪功能:
<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/test"/>
</clip>
double scale = progress/max;
ClipDrawable drawable = (ClipDrawable) mImageShow.getBackground();
drawable.setLevel((int) (10000*scale));
参考
《Android开发艺术探索》 https://juejin.cn/post/6844903775153422343
拜拜
今天介绍了Drawable的概念,与其他绘制图类的关系,以及它的主要分类,内容还是比较简单,主要带大伙做一个回顾总结,巩固知识。晚安~