Android Jetpack Compose Colors 类包含一组可以用于实现材质主题应用程序的颜色类型。如果我的应用程序主题需要一些额外的颜色类型,我如何添加这些额外的颜色,以便可以通过 MaterialTheme 对象使用它们?
对 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
)
}
会显示错误
此注解不适用于目标'顶级属性 没有支持场或代表'
要解决这个问题,可以这样写
@get:Composable
val Colors.myExtraColor: Color
get() = if (isLight) Color.Red else Color.Green
或者
val Colors.myExtraColor: Color
@Composable
get() = if (isLight) Color.Red else Color.Green
我发现这个错误的版本
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
基本上有两种方法:
最简单的方法是仅创建扩展属性来对颜色进行硬编码。如果您不想支持多个主题或亮/暗模式,这也可以。
如果您想将颜色正确地融入主题,您可以阅读我的文章,因为这里内联有点长:https://gustav-karlsson.medium.com/extending-the-jetpack-compose -材质主题与更多颜色-e1b849390d50
但简而言之,步骤是:
MyColors
类,其中包含对 Colors
以及新颜色的引用。CompositionLocal
来保存 MyColor
实例。MaterialTheme
包装在 CompositionLocalProvider
中,其中 CompositionLocal
提供 MyColors
。确保还将 Colors
中的 MyColors
实例分配给 MaterialTheme
。MaterialTheme
上创建一个扩展属性,引用持有 CompositionLocal
的 MyColors
。这就是您引用新颜色的方式。这将允许您向主题引入新的颜色,这些颜色将随着主题的变化而动态更新。
对于 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)
)
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
)
}
撰写文档中也有一个示例,请参阅扩展材质颜色。
如果您缺少的颜色与现有颜色的不同之处仅在于 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!")
}
请参阅Content Alpha文档了解更多详细信息。
Jetpack Compose Themingcodelab 中还有
Content Alpha
部分。
在我的例子中,主题组件从保存的设置中获取其参数,即应用程序主题独立于设备主题。因此,当前的答案对我不起作用。
我的实现与
Material 3
相关,并且直接取决于传递的参数。
Color.kt
package com.my.app.theme
import androidx.compose.ui.graphics.Color
val SuccessLightColor = Color(0xFF436915)
val SuccessLightContainerColor = Color(0xFFC2F18D)
val SuccessDarkColor = Color(0xFFA7D474)
val SuccessDarkContainerColor = Color(0xFF2D5000)
Theme.kt
package com.my.app.theme
import android.os.Build
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
private val DarkColorScheme = darkColorScheme()
private val LightColorScheme = lightColorScheme()
var successColorSchemeColor by mutableStateOf(SuccessLightColor)
var successContainerColorSchemeColor by mutableStateOf(SuccessLightColor)
@Suppress("unused")
var ColorScheme.success: Color
get() = successColorSchemeColor
set(value) {
successColorSchemeColor = value
}
@Suppress("unused")
var ColorScheme.successContainer: Color
get() = successContainerColorSchemeColor
set(value) {
successContainerColorSchemeColor = value
}
@Composable
fun Theme(
darkTheme: Boolean = isSystemInDarkTheme(),
// Dynamic color is available on Android 12+
dynamicColor: Boolean = true,
content: @Composable () -> Unit
) {
val colorScheme = when {
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
val context = LocalContext.current
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
}
darkTheme -> DarkColorScheme
else -> LightColorScheme
}
colorScheme.success = if (darkTheme) {
SuccessDarkColor
} else {
SuccessLightColor
}
colorScheme.successContainer = if (darkTheme) {
SuccessDarkContainerColor
} else {
SuccessLightContainerColor
}
MaterialTheme(
colorScheme = colorScheme,
typography = Typography,
content = content
)
}
使用案例:
Box(
modifier = Modifier
.size(128.dp)
.background(
color = MaterialTheme.colorScheme.successContainer
)
)
“CompositionLocal”答案是正确的,但可能不太容易理解。
youtube 上的 Android 开发者发送了一个视频:“Compose by example”。 https://www.youtube.com/watch?v=DDd6IOlH3io on 6:28/22:07 介绍了这个用法。
这是我学习这部分的示例代码,供大家复制:
定义主题:
val Purple200 = Color(0xFFBB86FC)
val Purple500 = Color(0xFF6200EE)
val Purple700 = Color(0xFF3700B3)
val Teal200 = Color(0xFF03DAC5)
val yellow200 = Color(0xffffeb46)
val yellow400 = Color(0xffffc000)
val yellow500 = Color(0xffffde03)
val yellowDarkPrimary = Color(0xff242316)
val yellowLightPrimary = Color(0xffd4d3f6)
class RabbitColorPalette(
val raFirstColor: Color,
val raSecColor: Color,
val raOnFirstColor: Color,
val raOnSecColor: Color
)
val rabbitPurple = RabbitColorPalette(Purple200,Purple500,Purple700,Teal200)
val rabbitYellow = RabbitColorPalette(yellow200,yellow400,yellow500,yellowDarkPrimary)
val rabbitColors = compositionLocalOf<RabbitColorPalette>{
rabbitPurple
}
@Composable
fun RabbitThemePink(
content: @Composable() () -> Unit
) {
val colors = rabbitPurple
CompositionLocalProvider(rabbitColors provides colors){
MaterialTheme(
typography = Typography,
shapes = Shapes,
content = content
)
}
}
object RabbitTheme{
val colors: RabbitColorPalette
@Composable get() = rabbitColors.current
}
@Composable
fun RabbitThemeYellow(
content: @Composable() () -> Unit
) {
val colors = rabbitYellow
CompositionLocalProvider(rabbitColors provides colors){
MaterialTheme(
typography = Typography,
shapes = Shapes,
content = content
)
}
}
用法
class RabbitThemeActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
RabbitThemePink {
SampleLayout()
}
}
}
@Composable
fun SampleLayout() {
Column {
Text(text = "sample", modifier = Modifier.background(color = RabbitTheme.colors.raFirstColor))
Text(text = "des", modifier = Modifier.background(color = RabbitTheme.colors.raSecColor))
}
}
@Preview
@Composable
fun ConstraintLayoutContentPinkPreview() {
RabbitThemePink {
SampleLayout()
}
}
@Preview
@Composable
fun ConstraintLayoutContentYellowPreview() {
RabbitThemeYellow {
SampleLayout()
}
}
}
这里的所有答案似乎要么有点过时,要么过于复杂。我发现简短而有用的是这个答案。
所有学分归原作者@Thales Isidoro
像下面的代码一样创建自定义颜色并使用 Materialtheme 设置颜色
val ColorScheme.myCustomColor: Color
@Composable
get() = if (isSystemInDarkTheme()) Color.Green else Color.Red
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
Text(
text = "Hello $name!",
modifier = modifier,
color = MaterialTheme.colorScheme.myCustomColor //Custom color
)
}