Recently, I needed to make a composable look disabled, my friendly design team wanted something quite complex turned to greyscale and made slightly transparent. And it had to be dynamic with changeable data, so I could not just use a drawable for when the composable was in disabled mode, and overlaying a grey box was just not going to cut it design wise.
My first thought was, filters to the rescue! Couldn’t I could apply a filter to the whole composable and be done with it? Unfortunately, there is no filter wrapper for a composable or filter modifier. But, it is a pretty easy thing to create yourself!
If you just want to convert a simple image to black and white you can of course use a colour filter with a colour matrix and set the saturation to zero.
This works so well for a photo:
But if your composable involves more than just one photo, especially a more complex or dynamic layout, to acheive the same effect you would need to add logic in many places. For example, for a scene involving a background, photo and some text, the code becomes more complex:
I have been recently having fun with creating custom modifiers, so I thought that a good way to apply a filter to an entire composable would be with a modifier.
Here we can create a custom drawing modifier, create the saturation matrix and filter and then apply that to the painting of the drawing layer in the canvas:
This has the added benefit of removing the saturation evenly so you can use this for dynamic content and colours and not have to manually convert each colour and maintain legibility.
For example, if we start with:
Then apply the modifier at the top level:
It will apply consistently to all the images, and still show the shade difference between the images that were in different colours.
As I mentioned above, the original reason I wanted to turn my composables to greyscale was to make them look disabled so the user knows that they could not interact with them. Greyscale alone is not desirable, I needed to add in an alpha modifier. This can be combined into one modifier that can be reused throughout the codebase:
This looks much better and the code will be much easier to apply, even with conditional modifiers!
You can check out the full code and my other Jetpack Compose modifier experiments here:
The code used in this post was inspired by this Stack Overflow question & answers.