Adopting Jetpack Compose Theming
So Jetpack Compose is now stable and production-ready ๐ . With that comes the question, how can I integrate it into my existing project?
Obviously, we cannot hold back the updates to completely migrate all the screens and views to Compose UI. So it has to be done iteratively. So with that in mind, I recently did a small scoping exercise for adopting Compose for my work project (on my stream at twitch.tv/sasikanth, self-plug ๐. Feel free to follow). During that, I went over different aspects of adopting Compose to an existing project.
-
Theming
-
Compose in Views
-
Android Views in Compose
-
Navigation
-
Managing State
Today we are going, to begin with, the first and my favourite section theming ๐จ ๐. (Over the next few weeks I will publish articles covering the rest of the things)
Using existing Material themes
The first thing I looked into when adopting Compose was to see how much I can get away with the existing theming setup, I didnโt want to re-implement all the Material theming setup from XML to Compose theming.
Fortunately, good folks at Google have a solution for that, MDC-Android Compose Theme Adapter which enables us to reuse the Material themes defined in XML for theming in Compose. Once we have added the dependency, we can use MdcTheme
for composable instead of MaterialTheme
(Which is the default when using Compose UI Material package). The MdcTheme
will create the Compose theme based on the Activity/Context theme.
MdcTheme {
// MaterialTheme.colors, MaterialTheme.shapes, MaterialTheme.typography
// will now contain copies of the context's theme
}
One of the things I found useful was, you can customise the generated values from MdcTheme
by using the createMdcTheme
function and then modifying the colors, shapes and typography and creating a MaterialTheme
. This is useful to slowly start migrating the theming implementation to Compose.
val context = LocalContext.current
val layoutDirection = LocalLayoutDirection.current
var (colors, type, shapes) = createMdcTheme(
context = context,
layoutDirection = layoutDirection
)
// Modify colors, type or shapes as required. Then pass them
// through to MaterialTheme...
MaterialTheme(
colors = colors,
typography = type,
shapes = shapes
) {
// rest of layout
}
Custom attributes
One thing the MdcTheme
didnโt generate for us was custom attributes. For that we created Kotlin extension based on the type. For example, we had typography like Body0
, Body2Numeric
, Headline6Numeric
, ButtonBig
etc.,
val Typography.body0
get() = TextStyle(
fontWeight = FontWeight.Normal,
fontSize = 18.sp,
letterSpacing = 0.011.sp,
lineHeight = 28.sp
)
val Typography.buttonBig
get() = button.copy(
fontSize = 16.sp,
letterSpacing = 0.0781.sp,
lineHeight = 20.sp
)
This helped us get all of our custom attributes that are missed when using MdcTheme
.
Wrapping up
While the MDC theme adapter is great and covers the most commonly used theming functionality and attributes from the existing XML theming setup. It does have some limitations, so do take a look at those before using it. If youโre using an AppCompat or non-MDC theme, then use the AppCompat Compose Theme Adapter.
Overall this approach helped us quickly jump into writing Compose code and migrating our fragments/views into Composable functions without needing to spend a bunch of time reimplementing our theming setup.