android 自定义还原色进度imageView
先上个效果图
首先底图是灰色,然后根据进度还原色彩图像。现有的imageView 就非常适合进行改造了。
- 继承imageView
- 给imageView设置ColorFilter让底图变灰
- 重写onDraw方法,设置canvas裁剪区域,绘制色彩图
class ProgressImageView(context: Context?, attrs: AttributeSet?, defStyleAttr: Int)
: AppCompatImageView(context, attrs, defStyleAttr) {
constructor(context: Context?): this(context, null, 0)
constructor(context: Context?, attrs: AttributeSet?): this(context, attrs, 0)
private var pWidth = 0
private var pHeight = 0
private var pDrawable: Drawable ? = null
private var progress: Float = 0f
init {
//设置图片饱和度为0就能显示黑白图片
val cm = ColorMatrix()
cm.setSaturation(0f)
val cmf = ColorMatrixColorFilter(cm)
colorFilter = cmf
}
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
if(pDrawable != null && canvas != null && progress != 0f){
canvas.save()
if (imageMatrix != null) {
canvas.concat(imageMatrix)
}
//设置裁剪区域
canvas.clipRect(createClipRect())
//绘制原色彩图在底图之上
pDrawable!!.draw(canvas)
canvas.restore()
}
}
override fun setImageDrawable(drawable: Drawable?) {
super.setImageDrawable(drawable)
if(pDrawable != drawable && drawable != null){
//这里要注意必须调用mutate()这个方法
pDrawable = drawable.constantState?.newDrawable()?.mutate()
configBound()
}
}
//创建显示原图的区域
private fun createClipRect(): Rect {
val height = pHeight * (progress / 100f)
val rect = Rect(0, 0, pWidth, height.toInt())
return rect
}
private fun configBound(){
pDrawable?.apply {
this.clearColorFilter()
pWidth = this.minimumWidth
pHeight = this.minimumHeight
this.setBounds(0, 0, pWidth, pHeight)
}
}
fun setProgress(progress: Float){
//防止多次设置
if(progress < this.progress){
return
}
this.progress = progress
if(this.progress > 100f){
this.progress = 100f
}
invalidate()
}
}
为了让两张图片重叠一致,可以直接复用imageView的Matrix,这样两张图片的缩放模式能够保持一致性。
给imageView设置ColorFilter让底图变灰
重写setImageDrawable方法,在这里进行色彩图drawable的创建
drawable.constantState?.newDrawable()?.mutate()
可以利用constantState创建新的drawable,这里要注意一下,此时虽然是两个drawable,但是两个drawable是共享同一个constantState的,这也就意味着两个drawable使用的同一个ColorFilter如果调用clearColorFilter(),那么灰色的底图也会被还原成原来的色彩图,所以需要在newDrawable() 后面调用 mutate(),这样就不会共享资源了。
设置canvas裁剪区域,绘制色彩图
在绘制彩色图的时候,利用canvas中的clipRect() 方法绘制进度部分区域的图片
代码比较简单,直接贴源码了