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(#...)