如何在 Android Jetpack Compose 的 MaterialTheme 中添加额外的颜色?

Val*_*kov 4 android android-jetpack android-jetpack-compose

Android Jetpack Compose Colors类包含一组可以实现材质主题应用程序的颜色类型。如果我的应用主题需要一些额外的颜色类型,我如何添加这些额外的颜色,以便它们可以通过MaterialTheme对象使用?

lev*_*evi 9

对于 Material3,我必须扩展该androidx.compose.material3.ColorScheme对象,因为MaterialTheme.colors它不存在。

val ColorScheme.successContainer: Color @Composable
    get() = if (!isSystemInDarkTheme()) Color(0xFFd6ffe0) else Color(0xFF269300)

Text(
    text = "Hello World",
    modifier = Modifier.background(color = MaterialTheme.colorScheme.successContainer)
)
Run Code Online (Sandbox Code Playgroud)


Val*_*kov 7

扩展Colors

您可以轻松地将扩展属性添加到类中,以便可以通过应用程序中的Colors任何对象使用它。Colors

@Composable
val Colors.myExtraColor: Color
    get() = if (isLight) Color.Red else Color.Green

@Composable
fun ExtraColorExample() {
    Text(
        text = "test",
        color = MaterialTheme.colors.myExtraColor // <-- the newly added color
    )
}
Run Code Online (Sandbox Code Playgroud)

撰写文档中也有一个示例,请参阅扩展材质颜色

指定内容 alpha

如果您缺少的颜色与现有颜色的不同之处仅在于 Alpha,并且该颜色的目的是更改内容优先级,则无需向主题添加其他颜色。您可以通过为LocalContentAlpha提供值来指定层次结构的内容 alpha 。

CompositionLocalProvider(
    LocalContentAlpha provides ContentAlpha.medium,
    LocalContentColor provides MaterialTheme.colors.onSurface
) {
    // this text is displayed using ContentAlpha.medium
    // and MaterialTheme.colors.onSurface color
    Text("Hello world!") 
}
Run Code Online (Sandbox Code Playgroud)

有关更多详细信息,请参阅Content Alpha文档。Jetpack Compose Theming Codelab 中也有Content Alpha部分。

  • 光从哪里来? (5认同)

Age*_*ntP 7

Valeriy Katkov 的答案只是一个小小的改变

在android studio的某些版本中,下面的代码不起作用

@Composable
val Colors.myExtraColor: Color
    get() = if (isLight) Color.Red else Color.Green

@Composable
fun ExtraColorExample() {
    Text(
        text = "test",
        color = MaterialTheme.colors.myExtraColor // <-- the newly added color
    )
}
Run Code Online (Sandbox Code Playgroud)

它会显示错误

此注释不适用于目标“没有支持字段或委托的顶级属性”

要解决这个问题,要么像这样写

@get:Composable
val Colors.myExtraColor: Color
    get() = if (isLight) Color.Red else Color.Green
Run Code Online (Sandbox Code Playgroud)

或者

val Colors.myExtraColor: Color
    @Composable
    get() = if (isLight) Color.Red else Color.Green
Run Code Online (Sandbox Code Playgroud)

我发现这个错误的版本

Android Studio Arctic Fox | 2020.3.1 Canary 12
Build #AI-203.7148.57.2031.7226969, built on March 23, 2021
Runtime version: 11.0.8+10-b944.6842174 amd64
VM: OpenJDK 64-Bit Server VM by N/A
Windows 10 10.0
Run Code Online (Sandbox Code Playgroud)

  • 不知道为什么 `isLight` 条件总是 true,因此我使用 `isSystemInDarkTheme()` 而不是 `isLight` 并且它有效。 (5认同)

Gus*_*son 5

基本上有两种方法:

天真的方法是只创建扩展属性来对颜色进行硬编码。如果您不想支持多个主题或明/暗模式,这很好用。

如果你想将你的颜色正确地融入主题,你可以阅读我关于它的文章,因为在这里内嵌有点长:https : //gustav-karlsson.medium.com/extending-the-jetpack-compose-material -theme-with-more-colors-e1b849390d50

但简而言之,步骤是:

  • 创建您自己的MyColors类,该类包含对Colors新颜色的引用。
  • 创建一个CompositionLocal包含MyColor实例的 。
  • 创建主题,并包裹MaterialThemeCompositionLocalProvider其中CompositionLocal提供MyColors。确保还指定Colors从实例MyColorsMaterialTheme
  • 创建一个扩展属性上MaterialTheme是指CompositionLocal持有MyColors。这就是您引用新颜色的方式。

这将允许您为主题引入新颜色,这些颜色将随着主题更改而动态更新。