ProAndroidDev

The latest posts from Android Professionals and Google Developer Experts.

Follow publication

Mastering Color Theming in Jetpack Compose

Stefano Natali
ProAndroidDev
Published in
6 min readAug 24, 2024

MaterialTheme in Jetpack Compose

@Composable
fun MyAppTheme(
darkTheme: Boolean = isSystemInDarkTheme()
,
content: @Composable () -> Unit
) {
val colors = if (darkTheme) {
darkColorPalette
} else {
lightColorPalette
}

MaterialTheme(
colors = colors,
typography = AppTypography,
shapes = AppShapes,
content = content
)
}

Defining Your Color Palette

// Color.kt
private val lightColorPalette = lightColors(
primary = md_theme_light_primary,
onPrimary = md_theme_light_onPrimary,
primaryContainer = md_theme_light_primaryContainer,
onPrimaryContainer = md_theme_light_onPrimaryContainer,
secondary = md_theme_light_secondary,
onSecondary = md_theme_light_onSecondary,
...
)

private val darkColorPalette = darkColors(
primary = md_theme_dark_primary,
onPrimary = md_theme_dark_onPrimary,
primaryContainer = md_theme_dark_primaryContainer,
onPrimaryContainer = md_theme_dark_onPrimaryContainer,
secondary = md_theme_dark_secondary,
onSecondary = md_theme_dark_onSecondary,
...
)

Customizing Your Theme with Extended Colors

@Immutable
data class ColorFamily(
val backgroundVariant: Color,
)

@Immutable
data class ExtendedColorScheme(
val extra: ColorFamily = extendedLight.extra,
)
val extendedLight = ExtendedColorScheme(
extra = ColorFamily(
backgroundVariant = Color(0xFFEEEEEE), // Example light variant
),
)
val extendedDark = ExtendedColorScheme(
extra = ColorFamily(
backgroundVariant = Color(0xFF333333), // Example dark variant
),
)
val LocalExColorScheme = staticCompositionLocalOf { ExtendedColorScheme() }
@Composable
fun MainTheme(
darkTheme: Boolean = isSystemInDarkTheme()
,
content: @Composable () -> Unit
) {
val colorScheme = if (darkTheme) DarkColorScheme else LightColorScheme
val extendedColorScheme = if (darkTheme) extendedDark else extendedLight

CompositionLocalProvider(
LocalExColorScheme provides extendedColorScheme
) {
MaterialTheme(
colorScheme = colorScheme,
typography = Typography,
content = content
)
}
}
@Composable
fun CustomBackgroundBox() {
Box(
modifier = Modifier
.fillMaxSize()
.background(LocalExColorScheme.current.extra.backgroundVariant)
) {
// Your content here
}
}

Integrating Dynamic Colors

@Composable
fun MainTheme(
darkTheme: Boolean = isSystemInDarkTheme()
,
dynamicColor: Boolean = true, // Enable dynamic colors
content: @Composable () -> Unit
) {
val colorScheme = when {
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
val context = LocalContext.current
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
}
darkTheme -> DarkColorScheme
else -> LightColorScheme
}

CompositionLocalProvider(
LocalExColorScheme provides if (darkTheme) extendedDark else extendedLight
) {
MaterialTheme(
colorScheme = colorScheme,
typography = Typography,
content = content
)
}
}

Why Use Dynamic Colors?

A Helpful Tool for Designing Your Theme

Conclusion

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Published in ProAndroidDev

The latest posts from Android Professionals and Google Developer Experts.

No responses yet

Write a response