Android custom color reduction Progress imageView

Let’s start with the renderings

First the base image is gray, and then restore the color image according to the progress. The existing imageView is perfect for retrofitting.

  • Inherit the imageView
  • Set ColorFilter to the imageView to make the base image gray
  • Rewrite the onDraw method to set the canvas clipping area and draw the color map
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: Var cm = ColorMatrix() cm.setsaturation (0f) val CMF = ColorMatrixColorFilter(cm) var 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)} // Sets the clipping region canvas.clipRect(createClipRect()) // Draw the primary color image on the base image pDrawable!! .draw(canvas) canvas.restore() } } override fun setImageDrawable(drawable: Drawable?) { super.setImageDrawable(drawable) if(pDrawable ! = drawable && drawable ! 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){prevent multiple Settings if(progress < this.progress){return} this.progress = progress if(this.progress > 100f){this.progress  = 100f } invalidate() } }Copy the code

To make the two images overlap consistently, you can directly reuse the imageView Matrix so that the zoom modes of the two images remain consistent.

Set ColorFilter to the imageView to make the base image gray

Overwrite the setImageDrawable method to create the drawable color diagram here

drawable.constantState? .newDrawable()? .mutate()Copy the code

ConstantState can be used to create a new drawable with a constantState. Note that both drawables share the same drawable state. If clearColorFilter() is called, the gray base will be restored to the original color, so mutate() will be called after newDrawable(), so resources will not be shared.

Set the canvas clipping area and draw the color map

When drawing the color map, use the clipRect() method in canvas to draw the picture of the part of the progress area

The code is relatively simple, directly paste the source code