Learn && Live
虚度年华浮萍于世,勤学善思至死不渝
前言
Hey,欢迎阅读Connor学Android系列,这个系列记录了我的Android原理知识学习、复盘过程,欢迎各位大佬阅读斧正!原创不易,转载请注明出处:http://t.csdn.cn/8mtej,话不多说我们马上开始!
1.Drawable简介
Drawable一般通过XML定义,也可以通过代码来创建具体的Drawable对象。在Android的设计中,Drawable是一个抽象的类,是所有Drawable对象的基类,每个具体的Drawable都是它的子类,比如ShapeDrawable、BitmapDrawable等
Drawable可以通过 getIntrinsicWidth 和 getIntrinsicHeight 获取其内部宽高,但不是所有Drawable都有内部宽高,如一个颜色所形成的Drawable;另外,Drawable的内部宽高不等同于它的大小,当用作View的背景时,Drawable会被拉伸至View的同等大小
2.Drawable分类
2.1 BitmapDrawable
对应标签 <bitmap> ,表示一张图片,在实际开发中,可以直接引用原始的图片,也可以通过XML的方式来描述它
<?xml version="1.0" encoding="utf-8"?>
<bitmap
xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@color/colorPrimary"
android:antialias="true"
android:dither="true"
android:filter="true"
android:gravity="center"
android:mipMap="false"
android:tileMode="disabled"
/>
android:src:图片的资源id
android:antialias:是否开启图片抗锯齿,开启后会让图片变得平滑,应该开启
android:dither:是否开启抖动效果,可以让高质量的图片在低质量的屏幕上保持较好显示效果,应该开启
android:filter:是否开启过滤效果,当图片被拉伸或压缩时仍能保持较好的显示效果
android:gravity:图片小于容器的尺寸时可用来对定位图片,如top、bottom等
android:minMap:纹理映射,默认值为false,日常开发不常用
android:tileMode:平铺模式,默认值为disable
- disable:关闭平铺模式
- repeat:水平和竖直方向上的平铺效果
- mirror:水平和竖直方向上的镜面投影效果
- clamp:图片四周的像素会扩展到周围区域
2.2 NinePatchDrawable
对应标签 <nine-patch> ,表示的是一张.9格式的图片,可以自动地根据所需的宽高进行相应的缩放且保证不失真
<?xml version="1.0" encoding="utf-8"?>
<nine-patch
xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@color/colorPrimary"
android:antialias="true"
android:dither="true"
android:filter="true"
android:gravity="center"
android:mipMap="false"
android:tileMode="disabled"
/>
2.3 ShapeDrawable
对应标签 <shape> ,通过颜色来构造的图形,既可以是纯色的图形,也可以是具有渐变效果的图形
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:radius="10dp"
android:topLeftRadius="10dp"
android:topRightRadius="10dp"
android:bottomLeftRadius="10dp"
android:bottomRightRadius="10dp"/>
<gradient
android:angle="45"
android:centerX="30"
android:centerY="30"
android:centerColor="@color/colorAccent"
android:endColor="@color/colorPrimary"
android:startColor="@color/colorPrimaryDark"
android:gradientRadius="20"
android:type="linear"
android:useLevel="true" />
<padding
android:left="10dp"
android:top="10dp"
android:right="10dp"
android:bottom="10dp" />
<size
android:width="200dp"
android:height="200dp" />
<solid
android:color="@color/colorPrimary"/>
<stroke
android:width="10dp"
android:color="@color/colorAccent"
android:dashWidth="5dp"
android:dashGap="3dp"/>
</shape>
<shape>标签创建的Drawable,其实体类实际上是GradientDrawable
android:shape:表示图形形状,可选:rectangle(默认)、oval、line、ring,其中line和ring必须通过<stroke>定义线的宽度和颜色
ring包含5个特殊属性:android:innerRadius、android:thickness、android:innerRadiusRatio、android:thicknessRatio、android:useLevel
<cornors>
表示shape的四个角的圆角角度,仅适用于矩形shape,用px表示,属性有android:radius、android:topLeftRadius、android:topRightRadius、android:bottomLeftRadius、android:bottomRightRadius
<gradient>:
表示渐变效果,与<solid>纯色填充互斥
- android:angle:渐变角度,默认为0,必须是45的整数倍,0表示从左到右,90表示从下到上
- android:centerX:渐变中心点的横坐标
- android:centerY:渐变中心点的纵坐标
- android:startColor:渐变起始色
- android:centerColor:渐变中间色
- android:endColor:渐变结束色
- android:gradientRadius:渐变半径,仅当android:type="radial"时有效
- android:useLevel:一般为false,StateListDrawable时为true
- android:type:渐变的类别,linear(线性渐变)、radial(径向渐变)、sweep(扫描线渐变),默认为linear
<solid>
纯色填充,可通过android:color指定颜色
<stroke>
shape描边,可以是实线或虚线
- android:width:描边宽度
- android:color:描边颜色
- android:dashWidth:虚线宽度
- android:dashGap:虚线线段之间的间隔
如果 dashWidth 和 dashGap 中任何一个为0,则虚线效果不能生效
<padding>
实际上是margin,是包含当前shape的View的空白
<size>
指定shape的固有宽高。shape在默认情况下没有固定宽高,此时 getIntrinsicWidth 和 getIntrinsicHeight 返回-1;而通过<size>指定固定宽高,shape就有了固定宽高,但作为View的背景时,shape还会被拉伸或压缩为View的大小
2.4 LayerDrawable
对应标签 <layer-list>,表示一种层次化的Drawable集合,不同的Drawable放置在不同的层上面从而达到一种叠加效果
一个layer-list中可以包含多个item,每个item可以通过android:drawable引用一个Drawable资源,在一个layer-list中,下面的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="#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>
2.5 StateListDrawable
对应标签 <selector> ,表示Drawable集合,每个Drawable对应View的一种状态,系统根据View的状态选择合适的Drawable。主要用于设置可单击的View的背景,如Button
一般来说,默认的item都应放在selector的最后一个且不附带任何状态,这样当上面的item都无法匹配View的当前状态时,会选择这个默认的item,因为默认的item不附带状态限制,即可以匹配任何状态
<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android"
android:constantSize="false" // StateListDrawable的固有大小是否根据状态而改变,默认false=根据状态而改变
android:dither="true" // 是否开启抖动-让高质量图片在低质量屏幕上依旧效果好,默认true开启
android:variablePadding="false" // padding是否根据状态的改变而改变,不建议开启(false)
>
<item android:state_pressed="true" // Button被按下后却没有松开的状态
android:drawable="@color/colorAccent"/>
<item android:state_focused="true" // View获取了焦点
android:drawable="@color/colorPrimary"/>
<item android:state_selected="true" // 用户选择了View
android:drawable="@color/colorPrimary"/>
<item android:state_checked="true" // 用户选中了View,一般用于CheckBox这类在选中和没有选中状态之间切换的View
android:drawable="@drawable/ic_launcher_background"/>
<item android:state_enabled="true" // View处于可用状态
android:drawable="@drawable/ic_launcher_foreground"/>
<item android:drawable="#FFFFFF"/> // 默认Drawable: 按顺序向下匹配,需要放在最下方,因为可以匹配任何状态
</selector>
2.6 LevelListDrawable
对应标签 <level-list> ,表示一个Drawable集合,每个Drawable都有一个level,根据不同level切换Drawable
level可以通过 android:minLevel 和 android:maxLevel 指定,范围0-10000,默认为0
<?xml version="1.0" encoding="utf-8"?>
<level-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:minLevel="0" android:maxLevel="10" android:drawable="@drawable/d1" />
<item android:minLevel="11" android:maxLevel="20" android:drawable="@drawable/d2" />
<item android:minLevel="21" android:maxLevel="30" android:drawable="@drawable/d3" />
<item android:minLevel="31" android:maxLevel="40" android:drawable="@drawable/d4" />
</level-list>
2.7 TransitionDrawable
对应标签 <transition> ,用于实现两个Drawable之间的淡入淡出效果
获得背景的 TransitionDrawable 后,通过 startTransition 和 reverseTransition 方法实现效果和逆过程
<?xml version="1.0" encoding="utf-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/transition_drawable"
android:drawable="@drawable/ic_launcher"
android:top="10dp" // 四周的偏移量
android:bottom="10dp"
android:right="10dp"
android:left="10dp"/>
<item android:drawable="@drawable/ic_launcher_round" />
</transition>
2.8 InsetDrawable
对应标签 <inset> ,可以将其他Drawable内嵌到自己中,并留出一定间距。当一个View希望自己的背景比自己的实际区域小的时候,可以通过InsetDrawable实现
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/ic_launcher"
android:insetTop="10dp" // 四周间距
android:insetBottom="10dp"
android:insetLeft="10dp"
android:insetRight="10dp">
</inset>
2.9 ScaleDrawable
(1)对应标签 <scale>
(2)根据自己的等级level(0~10000)将指定的Drawable缩放到一定比例
(3)android:scaleHeight="70%"用于指定宽高的缩放比例为原来的30%
(4)ScaleDrawable的level为0,不可见。为10000时,不缩放。
(5)level越大,内部Drawable就越大;缩放比例越大,内部Drawable就越小
(6)android:scaleGravity属性和gravity属性完全一致
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/ic_launcher"
android:scaleGravity="center"
android:scaleHeight="70%"
android:scaleWidth="70%">
</scale>
2.10 ClipDrawable
(1)对应标签 <clip>
(2)根据等级level来裁剪另一个Drawable,裁剪方向可以通过 android:clipOrientation 和 android:gravity 控制
(3)level范围0-10000,0表示完全裁剪,即不可见;10000表示不裁剪
(4)clipOrientation有水平、竖直两个方向,gravity与clipOrientation组合结果如下表