Extending the Jetpack Compose Material theme with more colors

Gustav Karlsson
2 min readMar 27, 2021

--

Creating and using a material theme in Jetpack Compose is simple, and setting up your own colors, typography, and shapes can be done in a matter of minutes. Material design defines 12 color variables, but the docs don't make it clear how they can be extended.

Suppose we want to add warning and onWarning colors to complement the built-in error and onError. The most straightforward approach would be to define the new colors globally and refer to them in our layout. But if we want them to change dynamically with our theme we need something more sophisticated. Let's get to it!

First of all, we need something like the Colors class, which holds all the theme color values. We can’t extend the built-in class, but in the spirit of compose we can make a new class composed of the material colors and our new colors:

The get() accessors are not strictly necessary but allow us to get all colors in the same way.

The result is a class that functions just like Colors but has two additional values. Next, let’s set up some light and dark color palettes:

Notice how I’m sticking with the defaults here when calling lightColors() and darkColors(). You probably want to override at least the brand colors.

With the palettes in place, we can create our theme. This will look similar to the code generated by the Android Studio new project wizard, but with a few important differences:

The first thing to note is LocalColors. This is a CompositionLocal, and I won't go into detail on how it works. But in short, it will allow us to access the colors defined by the current theme without having to pass them as arguments down our layout tree.

Inside our theme, we select the color palette as usual and assign its material colors to the MaterialTheme so they are still applied correctly.

CompositionLocalProvider defines a scope within which our LocalColors will be provided.

Finally, we need a way to access these colors easily from our composable functions.

That’s it! We can now easily access all colors using MaterialTheme.myColors and build UI:s that respond to theme changes with all the colors we need. As a bonus, this method can also be applied to extend typography and shapes!

Finally here is a simple demo that demonstrates our new warning colors in action:

--

--