在 Composable 函数之外引用或枚举 Jetpack Compose MaterialTheme 主题颜色

Dav*_*ave 10 android android-resources android-jetpack-compose

我希望向 @Composable 函数提供一个参数,该函数接受一种颜色,但仅接受离散列表中的一种颜色。

类似这样的事情:

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

由于上面在可组合上下文之外引用MaterialTheme.colors,因此会发生以下错误:

@Composable 调用只能在 @Composable 函数的上下文中发生

如果直接引用颜色,而不是通过 MaterialTheme,则颜色将无法针对亮/暗模式等内容正确更新。

一种策略可能是将枚举值映射到 @Composable 函数本身内的 MaterialTheme 颜色。但这很麻烦、庞大,并且不能很好地扩展 - 想象一下更长的颜色列表和相同的 SpecialColor 列表需要重复用于许多功能。

另一种策略可能是直接使用 LocalContentColor 或类似的方法修改主题颜色,但这过于宽泛,并且会改变不仅仅是目标功能的颜色。

从实用程序 @Composable 函数返回颜色也不是一个选项,因为 @Composable 函数没有返回值。

那么...
关于如何提供 Compose Material 颜色的枚举列表之一作为参数有什么想法吗?
以一种干净且可扩展且可扩展的方式?

Phi*_*hov 12

这实际上是不正确的:

@Composable 函数没有返回值。

您可以使用返回类型注释这两个函数,甚至可以使用@Composable. 例如,是 Material 主题源代码的一部分。

以下是定义颜色的方法:

enum class SpecialColor {
    ALPHA,
    BETA,
    ;

    val color: Color
        @Composable
        @ReadOnlyComposable
        get() = when(this) {
            ALPHA -> MaterialTheme.colors.onSurface
            BETA -> MaterialTheme.colors.onSecondary
        }
}
Run Code Online (Sandbox Code Playgroud)