Home > database >  Can I customize a color with a name in MaterialTheme in Jetpack Compose?
Can I customize a color with a name in MaterialTheme in Jetpack Compose?

Time:09-02

Before I define a color with a name in resources file such as Code A, and access it using such as Divider(color = colorResource(R.color.colorGrey)).

Now I read the article. I get the following warning:

Prefer colors from the theme rather than hard-coded colors. Even though it's possible to access colors using the colorResource function, it's recommended that the colors of your app are defined in a MaterialTheme which can be accessed from your composables like MaterialTheme.colors.primary.

So I study Code B, I find I can use such as MaterialTheme.colors.secondary to access a color.

I find there are only some preset colors with name in colors such as primary, primaryVariant, ...etc, it seems that I can only overwrite preset colors such as primary = Purple900.

I hope I can customize a color with a name in MaterialTheme, so I can use such as MaterialTheme.colors.myIcon to access color, how can I do?

Code A

<resources>
    <color name="purple_200">#FFBB86FC</color>
    <color name="colorGrey">#FF6200EE</color>
</resources>

Code B

@Composable
fun SoundMeterTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable() () -> Unit) {
    val colors = if (darkTheme) {
        DarkColorPalette
    } else {
        LightColorPalette
    }

    MaterialTheme(
        colors = colors,
        typography = Typography,
        shapes = Shapes,
        content = content
    )
}


private val DarkColorPalette = darkColors(
    primary = Purple200,
    primaryVariant = Purple700,
    secondary = Teal200
)

fun darkColors(
    primary: Color = Color(0xFFBB86FC),
    ...
): Colors = Colors(
    primary,
    ...
)

CodePudding user response:

Use compositionLocal to feed data into your composable.

simple example:

private val LocalMyColors = compositionLocalOf {
    DarkColorPalette
}

@Stable
object MyTheme {
    val colors: darkColors
        @Composable
        get() = LocalMyColors.current

    enum class Theme {
        Light, Dark
    }
}
@Composable
fun SoundMeterTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable() () -> Unit) {
    val colors = if (darkTheme) {
        DarkColorPalette
    } else {
        LightColorPalette
    }
    CompositionLocalProvider(LocalMyColors  provides colors) {
        MaterialTheme(
            colors = colors,
            typography = Typography,
            shapes = Shapes,
            content = content
        )
    }
}

fun darkColors(
    primary: Color = Color(0xFFBB86FC),
    ...
): Colors = Colors(
    primary,
    ...
)

use:

LocalMyColors.current.primary
MyTheme.colors.primary

CodePudding user response:

If you simply just want a named color, just a global static will work for you. There is no need to use MaterialTheme.

Just have a Color.kt file with top level public constant declarations.

val MyGrey = Color(#FF6200EE)

or you could sort of namespace them with

object MyColors {
   val Grey = Color(#FF6200EE)
}

Then you can just use it in your composables

Divider(color = MyColors.Grey)

The downside though is that now you are not supporting dark theme or other possible config changes. For that you can extend MaterialTheme and we have docs on how to do that here

For your example of myIcon it would be

import androidx.compose.material.Colors

val Colors.myIcon: Color
    get() = if (isLight) Color(#...) else Color(#...)
  • Related