'Referencing or enumerating Jetpack Compose MaterialTheme theme colors outside Composable function
I wish to provide a parameter to a @Composable function that accepts a color, but only one from a discrete list.
Something along the lines of this:
enum class SpecialColor(val color: Color) {
ALPHA(MaterialTheme.colors.onSurface),
BETA(MaterialTheme.colors.onSecondary)
}
@Composable
fun ColorSample(specialColor: SpecialColor) {
Box(
modifier = Modifier
.width(100.dp)
.height(100.dp)
.background(specialColor.color)
)
}
@Preview
@Composable
fun PreviewSample() {
CustomTheme {
ColorSample(specialColor = SpecialColor.ALPHA)
}
}
As the above is referencing MaterialTheme.colors outside a composable context, the following error occurs:
@Composable invocations can only happen from the context of a @Composable function
If a color is referenced directly, instead of via MaterialTheme, the color won't properly update for things like light/dark mode.
One tactic might be to map enumerated values to MaterialTheme colors within the @Composable function itself. But this is cumbersome, bulky, and doesn't scale well - imagine a much longer list of colors and the same SpecialColor list desired to be reused for many function.
Another tactic might be to modify the theme colors directly with LocalContentColor or similar, but this is too broad of a brush and will change colors for more than just the targeted function.
Returning a color from a utility @Composable function is also not an option, as @Composable functions don't have return values.
So...
Any thoughts on how to provide one of an enumerated list of Compose Material colors as a parameter?
In a clean and extendable way that scales well?
Solution 1:[1]
This is actually not true:
@Composable functions don't have return values.
You can annotate both function with return types and even getter only properties with @Composable. For example this is part of Material theme source code.
Here's how you can define your color:
enum class SpecialColor {
ALPHA,
BETA,
;
val color: Color
@Composable
@ReadOnlyComposable
get() = when(this) {
ALPHA -> MaterialTheme.colors.onSurface
BETA -> MaterialTheme.colors.onSecondary
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Pylyp Dukhov |
