Creating a custom theme in Jetpack Compose
Recently, I’ve been studying Jetpack Compose, which is a new way to develop UI on Android, making declarative. By default, Jetpack Compose uses Material Design to create themes, it’s great and contains a design system consistent, and it’s very simple to use on Jetpack Compose.
here we have a composable method from MaterialTheme, it contains 4 parameters, colors, typography, shapes, and content. each one is to implement its own colors, typography, and shapes which desire as long as it follows the Material pattern. However, sometimes the pattern that offers is not enough, and with that comes the question… how create your own theme that maintains like Material Design?
Creating a custom theme!
For that, we need to understand a little bit of how the Material works “under the hood”:
This object contains all the properties that we pass in the MaterialTheme method, they support us when we need to use something from the theme within the context we are in, knowing that, we will create our own custom object.
In this example, we added a property called spaces to illustrate, which contains the type CustomSpaces that will have the role of performing the spaces (margins) within the theme. We also set colors as CustomColors, which will be a class created later. Also, the assignments (Locals) will be implemented later.
In this example, we use customSpaces with the following properties:
- small
- medium
- large
- extra large
For typography, we will use customTypography with the following properties:
- H1 (Headline 1)
- Body1
Finally, we will use customColors with the properties:
- Primary
- Text
- Background
- Success
- Error
- isLight
why use MutableStateOf?
The MutableStateOf creates a value stored in the cache, preventing the composable from recomposing every time the method is called by the composable, and it’s only emitted to the UI when its value is updated, so we need its uses to store color states and to maintain dynamics.
Because of MutableState we can’t create a Data Class, but we’ll create the copy and updateColorsFrom methods ’cause we will need it after
After creating our object, it’s time to store the values in the object we’ve created, and for that, we’ll need to use CompositionLocal, roughly speaking, it serves to provide data when it’s within its context, and need to be injected only once to use. We’ll use the staticCompositionLocalOf method because it’s static, also we won’t need (or almost never) to change the values after they are used by the provider, besides that the performance improves considerably.
lightColors/darkColors are methods that return CustomColors, if you have questions how to implement, click here to see in the project
After that, it’s only necessary to create our CustomTheme method, which is what we’ll use in our project. To provide our CompostionLocal, we will use the CompositionLocalProvider method, which accepts any providers. We also take advantage of the ProvideTextStyle method that makes the content already starts with a default text style (in the example it is body1).
at this point, we need to use the copy/updateColorsFrom methods of CustomColors, as they are placed to prevent the initial state changing their original value after instances on provider. The copy creates another instance of the class, and updateColorsFrom will do as a “double check” so that everything is the same as the original class creating no link to it by reference. The method will look like this:
If you want to add support for Dark Theme (System), there’s other method in which darkColors is an optional parameter:
now your content will be able to fully enjoy your theme, and if you want to use any property, remember to use the CustomTheme object to get the value.
Result
Conclusion
Themes are important and widely used in the developer’s day to day and Jetpack Compose got it right by making something customizable and easy to use. And remember, we used CompositionLocalProvider to create the theme, but it is capable of doing many other things, for example the Google accompanist insets that also uses.
Project repository
If you have any questions about anything or how the UI was implemented, I’ll post the repository link with the implementation of this article below.