简体   繁体   中英

How to make Jetpack Compose theme customizable?

I'm working on a Design System with Jetpack Compose, I have a lot of components all using my theme to access the colors, typography and dimensions. Now I'm looking into the possibility of allowing customization. For instance, overriding a color resulting in this to change for every component.

What I've attempted so far adding parameters to fun MyTheme, I have had some success with this approach, but the problem is that any dev could modify the theme at any time like this. I would like for it to be customizable only once, maybe like a singleton. Any ideas or recommendations?

Here is my theme:

private val LightColorPalette = LightColors()
private val DarkColorPalette = DarkColors()

private val LocalColors = compositionLocalOf<MyColors> {
    error("No typography provided! Make sure to wrap all usages of this components in a MyTheme.")
}

private val LocalTypography = compositionLocalOf<MyTypography> {
    error("No typography provided! Make sure to wrap all usages of this components in a MyTheme.")
}

private val LocalDimensions = staticCompositionLocalOf { MyDimensions() }

@Composable
fun MyTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),
    colors: MyColors = if (darkTheme) DarkColorPalette else LightColorPalette,
    typography: MyTypography = getTypography(LocalConfiguration.current),
    dimensions: MyDimensions = getDimensions(LocalConfiguration.current),
    content: @Composable () -> Unit
) {
    val shapes = MaterialShapes

    CompositionLocalProvider(
        LocalTypography provides typography,
        LocalColors provides colors,
        LocalDimensions provides dimensions,
    ) {
        MaterialTheme(
            colors = debugColors(darkTheme),
            content = content,
            shapes = shapes
        )
    }
}

I managed to get this working by making all my CompositionLocal variables public. With this, any new theme that overrides this variables with CompositionLocalProvider will have the composables under it using this new values.

@Composable
fun SecondaryTheme(
    content: @Composable () -> Unit
) {
    val configuration = LocalConfiguration.current

    val colors = SecondaryColors()
    val typography = getDefaultTypography(configuration)
    val dimensions = getDefaultDimensions(configuration)
    val shapes = MaterialShapes

    CompositionLocalProvider(
        LocalTypography provides typography,
        LocalColors provides colors,
        LocalDimensions provides dimensions,
    ) {
        MaterialTheme(
            colors = materialColors(darkTheme),
            content = content,
            shapes = shapes
        )
    }
}

I recommend checking the official documentation

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM