Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set the entire component to GrayScale compose

I'm trying to implement a disabled state for a custom component in compose. The disabled state involves having the entire component set to grayscale with an alpha of 0.8f. I tried drawing a rect on top of the component content with BlendMode.Saturation like so;

Surface(
 modifier = modifier.then(Modifier.drawWithCache {
  onDrawWithContent {
   drawContent()
   drawRect(backgroundColor, blendMode = BlendMode.Saturation)
  }
 }.graphicsLayer { alpha = 0.8f }

While this works perfectly fine, the only issue is BlendMode.Saturation is supported API 29 and above. How can I achieve the same behavior on API<29?

Attaching the component screenshot as reference.Screenshot for component

like image 609
Programmer123 Avatar asked Oct 11 '25 12:10

Programmer123


2 Answers

Just to add something that could be nice for people that want to use this, following @Programmer123's answer and the official documentation for creating custom modifiers I did this:

fun Modifier.grayScale(): Modifier {
  val saturationMatrix = ColorMatrix().apply { setToSaturation(0f) }
  val saturationFilter = ColorFilter.colorMatrix(saturationMatrix)
  val paint = Paint().apply { colorFilter = saturationFilter }

  return drawWithCache {
    val canvasBounds = Rect(Offset.Zero, size)
    onDrawWithContent {
      drawIntoCanvas {
        it.saveLayer(canvasBounds, paint)
        drawContent()
        it.restore()
      }
    }
  }
}

I think it is very readable and reusable, you can simply use it as

    Column(
        modifier = Modifier
            .padding(6.dp)
            .grayScale()
    )
like image 161
cesonha Avatar answered Oct 14 '25 20:10

cesonha


Building on top of @Nikola's answer this is what worked for me.

onDrawWithContent {
      val saturationMatrix = ColorMatrix().apply { setToSaturation(0f) }

      val saturationFilter = ColorFilter.colorMatrix(saturationMatrix)
      val paint = Paint().apply {
        colorFilter = saturationFilter
      }
      drawIntoCanvas { canvas ->
        canvas.saveLayer(Rect(0f, 0f, size.width, size.height), paint)
        drawContent()
        canvas.restore()
      }
    }
like image 20
Programmer123 Avatar answered Oct 14 '25 20:10

Programmer123



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!