其他
Android中的Drawable到底是个什么东西?
https://juejin.cn/post/7148630011010875422
Drawable 的宽高不等于其展示时的大小,我们可以认为 Drawable 不存在大小的概念,因为其用于 View 背景时,其会被拉伸至 View 的同等大小。 也并不是所有的 Drawable 都有内部宽高。比如由一个图片所形成的 Drawable,其相应的宽高也就是图片的宽高,而由颜色所形成的 Drawable,相应的内部也不存在宽高。
无状态
BitmapDrawable
<<bitmap
用于将图片转为 BitmapDrawable;
ShapeDrawable
<<shape
通过颜色来构造 Drawable;
VectorDrawable
<<vector
矢量图,Android 5.0及以上支持。便于在缩放过程中保证显示质量,以及一个矢量图支持多个屏幕,减少 apk 大小;
TransitionDrawable
<<transition
用于实现 Drawable 间的淡入淡出效果;
InsetDrawable
<<inset
用于将其他 Drawable 内嵌到自己当中,并可以在四周留出一定的间距。当一个 View 希望自己的背景比实际的区域小时,可以采用其来实现。
有状态
StateListDrawable
<<selector
用于有状态交互时的 View 设置,比如按下时的背景,松开时的背景,有焦点时的背景灯;
LevelListDrawable
<<level-list
根据等级(level)来切换不同的 Drawble。在 View 中可以通过设置 setImageLevel 更改不同的 Drawable;
ScaleDrawable
<<scale
根据不同的等级(level)指定 Drawable 缩放到一定比例;
ClipDrwable
<<clip
根据当前等级(level)来裁剪 Drawable ;
BitmapDrawable
android:src 资源 id android:antialias 开启图片抗锯齿,用于让图片变得平滑,同时抗锯齿也会一定程度上降低图片清晰度,不过幅度几乎无法感知; android:dither 开启抖动效果,为低像素机型做的自动降级显示,保证显示效果。比如当前图片彩色模式为 ARGB8888,而设备屏幕色彩模式为 RGB555,此时开启抖动就可以避免图片显示失真; android:filter 过滤效果。在图片尺寸被拉伸或者压缩时,有助于保持显示效果; android:gravity 当前图片小于容器尺寸时,此选项便于对图片进行定位,当titleMode开启时,此属性将失效; android:mipMap 纹理映射开关,主要是为了应对图片大小缩放处理时,Android 可以通过纹理映射技术提前按缩小的层级生成图片预存储在内存中,以此来提高速度与图片质量。默认情况下,mipmap 文件夹里的默认开启此开关, drawable 默认关闭。但需要注意,此开关只能建议系统开启此功能,至于最终是否真正开启,取决于系统。 android:tileMode 用于设置图片的平铺模式,有以下几个值:[disabled、clamp、repeat、mirror] disabled (默认值)关闭平铺模式 clamp 图片四周的像素会扩展到周围区域 repeat 水平和竖直方向上的平铺效果 mirror 在水平和竖直方向的的镜面投影效果
val drawable = BitmapDrawable(bitmap).apply {
setTileModeXY(Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)
isFilterBitmap = true
gravity = Gravity.CENTER
setMipMap(true)
setDither(true)
}
ivDrawable.background = drawable
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:dither="true"
android:filter="true"
android:gravity="center"
android:mipMap="true"
android:src="@drawable/test"
android:tileMode="repeat" />
ShapeDrawable
shape表示图形的形状,如下四个选项:rectangle(矩形)、oval(椭圆)、line(横线)、ring(圆环) corners 表示 shape 的四个角的角度,只适用于矩形 shape。 android:radius 为四个角设置相同的角度 android:topLeftRadius 设置左上角角度 android:bottomLeftRadius 设置左下角角度 android:bottomRightRadius 设定右下角的角度 gradient 用于表示渐变效果,与标签互斥(其表示纯色填充) android:angle 渐变的角度,默认为0,其值必须为45的倍数,0表示从左向右,90表示从下到上 android:centerX 渐变中心点的横坐标 android:centerY 渐变中心点纵坐标 android:startColor 渐变的起始色 android:centerColor 渐变的中间点 android:endColor 渐变的结束色 android:gradientRadius 渐变半径,仅当 android:type=“radial” 时有效 android:useLevel 是否使用等级区分,在 StateListDrawable 时有效,默认 false android:type 渐变类型,linear(线性渐变)、radial(径向渐变)、sweep solid 表示纯色填充 stroke 用于设置描边 android:width 描边宽度 android:color 描边颜色 android:dashWidth 描边虚线时的宽度 android:dashGap 描边虚线时的间隔 padding 用于表示空白,其代表了在 View 中使用时的空白。但其在 shape 中并没有什么作用,可以在 layer-list 中进行使用。 size 用于表示 shape 的固有大小,但其不代表 shape 最终显示的大小。因为对于 shape 来说,其没有宽/高的概念,因为其最终被设置到 View 上作为背景时,其会被自动拉伸或缩放。但作为 drawable,它拥有着固有宽/高,即通过 getIntrinsicWidth,getIntrinsicHeight 获取。对于某些 Drawable 而言,比如 BitMapDrawable 时,其宽高就是图片大小;而对于 shape 时,其就不存在大小,默认为-1。当然你也可以通过 size 设置大小,但其最终代表的是 shape 的固有宽高,作为背景时其并不是最终显示时的宽高。
LayerDrawable
StateListDrawable
constantSize 表示其固有大小是否随着状态而改变。因为每次切换状态时,都会伴随着 Drawable 的改变,如果此时不是用于背景,则如果 Drawable 的固有大小不一致,则会导致 StateListDrawable 的大小发生变化。如果此值为 true,则表示当前 StateDrawable 的固有大小是当前其内部所有 Drawable 中最大值。反之,则根据状态决定; android:dither 是否开启抖动效果,用于在低质量屏幕上获得较好的显示效果; variablePadding 表示 padding 是否随着状态而改变,true 表示跟随状态而决定,取决于当前显示的 drawable,false 则选取 drawable 集合中 padding 最大值。
LevelListDrawable
view.background.level = 200
TransitaionDrawable
InsetDrawable
android:inset 表示四边内凹大小 android:insetTop 表示顶部内凹大小 android:insetLeft 表示左边内凹大小 android:insetBottom 表示底部内凹大小 android:insetRight 表示右边内凹大小
ScaleDrawable
android:scaleGravity 类似于与 android:gravity android:scaleWidth 指定宽度的缩放比例(相对于原 drawable 缩放了多少) android:scaleHeight 指定高度的缩放比例(相对于原 drawable 缩放了多少) android:level(minSdk>=24)指定缩放等级,默认为0,即最小,最高10000,此值越大,最终显示的 drawable 越大
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/level2_drawable"
android:level="1"
android:scaleWidth="70%"
android:scaleHeight="70%"
android:scaleGravity="center" />
ClipDrawable
android:drawable 需要裁剪的 drawable android:clipOrientation 裁剪方向,有水平(horizontal)、竖直(vertical)两种 android:level(minSdk>=24)设置等级,为0时表示完全裁剪(即隐藏),值越大,裁剪的越小。最大值10000(即不裁剪,原图)。 android:gravity
private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
private val rectF = RectF()
private var progress = 0F
private val valueAnimator by lazy(LazyThreadSafetyMode.NONE) {
ValueAnimator.ofFloat(0f, 1f).apply {
duration = 2000
repeatCount = Animation.INFINITE
interpolator = LinearInterpolator()
addUpdateListener {
progress = it.animatedValue as Float
invalidateSelf()
}
}
}
init {
paint.style = Paint.Style.STROKE
paint.strokeWidth = 10f
paint.strokeCap = Paint.Cap.ROUND
paint.color = Color.GRAY
start()
}
override fun draw(canvas: Canvas) {
var min = (min(bounds.bottom, bounds.right) / 2).toFloat()
paint.strokeWidth = min / 10
min -= paint.strokeWidth * 3
val centerX = bounds.exactCenterX()
val centerY = bounds.exactCenterY()
rectF.left = centerX - min
rectF.right = centerX + min
rectF.top = centerY - min
rectF.bottom = centerY + min
paint.color = Color.GRAY
canvas.drawArc(rectF, -90f, 360f, false, paint)
paint.color = Color.GREEN
canvas.rotate(360F * progress, centerX, centerY)
canvas.drawArc(rectF, -90F, 30F + 330F * progress, false, paint)
}
override fun setAlpha(alpha: Int) {
paint.alpha = alpha
invalidateSelf()
}
override fun setColorFilter(colorFilter: ColorFilter?) {
paint.colorFilter = colorFilter
invalidateSelf()
}
override fun getOpacity(): Int {
return PixelFormat.TRANSLUCENT
}
override fun start() {
if (valueAnimator.isRunning) return
valueAnimator.start()
}
override fun stop() {
if (valueAnimator.isRunning) valueAnimator.cancel()
}
override fun isRunning(): Boolean {
return valueAnimator.isRunning
}
}