Jetpack Compose文本颜色异常:自定义背景方法导致颜色未切换
我是Jetpack Compose新手,尝试根据主题将窗口背景设置为黑白色。创建自定义主题并设置背景色后,文本颜色始终为黑色。
代码实现
theme.kt
package com.vivek.sportsresult.ui.theme import android.os.Build import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.material3.* import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import com.google.accompanist.systemuicontroller.rememberSystemUiController private val DarkColorScheme = darkColorScheme( primary = Purple80, secondary = PurpleGrey80, tertiary = Pink80, background = Color.Black ) private val LightColorScheme = lightColorScheme( primary = Purple40, secondary = PurpleGrey40, tertiary = Pink40, background = Color.White ) @Composable fun SportsResultTheme( darkTheme: Boolean = isDarkTheme(), // Dynamic color is available on Android 12+ dynamicColor: Boolean = true, content: @Composable () -> Unit ) { val systemUiController = rememberSystemUiController() 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 } } if (darkTheme) { systemUiController.setSystemBarsColor( color = Color.Black ) } else { systemUiController.setSystemBarsColor( color = Color.White ) } MaterialTheme( colorScheme = colorScheme, typography = Typography, content = content ) } @Composable fun isDarkTheme() = isSystemInDarkTheme() @Composable fun getBackgroundColor() = if (isDarkTheme()) { DarkColorScheme.background } else { LightColorScheme.background }
MainActivity.kt
package com.vivek.sportsresult import android.os.Bundle import android.util.Log import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.tooling.preview.Preview import com.vivek.sportsresult.ui.theme.SportsResultTheme import com.vivek.sportsresult.ui.theme.getBackgroundColor class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { SportsResultTheme { // A surface container using the 'background' color from the theme Surface( modifier = Modifier.fillMaxSize(), color = getBackgroundColor() ) { Log.e("TAG", "onCreate: ") Greeting("Android") } } } } } @Composable fun Greeting(name: String) { Text(text = "Hello $name!") } @Preview(showBackground = true) @Composable fun DefaultPreview() { SportsResultTheme { Greeting("Android") } }
问题详情
当我使用color = getBackgroundColor()设置背景时,文本颜色不会随主题切换;但使用color = MaterialTheme.colorScheme.background时,深色/浅色主题下文本颜色均能正常显示。请问这是什么原因?能否提供相关指导?
实际效果

预期效果

原因分析
自定义方法脱离主题上下文:
你写的getBackgroundColor()直接通过系统主题判断返回静态的DarkColorScheme/LightColorScheme背景色,完全忽略了主题中动态颜色的分支(Android 12+开启动态色时,实际生效的是dynamicDarkColorScheme/dynamicLightColorScheme)。更关键的是,用这种方式设置Surface颜色时,Compose无法将当前主题的配色上下文传递给内部组件,导致Text无法自动适配对应主题的文本颜色(即MaterialTheme.colorScheme.onBackground)。MaterialTheme.colorScheme是统一入口:
不管是静态配色还是动态配色,MaterialTheme.colorScheme始终指向当前主题生效的完整配色方案。Surface使用这个值时,会自动让内部组件继承主题上下文,Text会自动匹配对应的onBackground颜色(深色主题下为白色,浅色为黑色)。
解决方案
方案1:直接使用主题提供的配色(推荐)
删除自定义的getBackgroundColor(),修改MainActivity中的Surface颜色设置:
Surface( modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background ) { Greeting("Android") }
方案2:修复自定义方法的实现
如果需要保留工具方法,应该从当前主题上下文获取配色,而非直接用静态配色:
@Composable fun getBackgroundColor() = MaterialTheme.colorScheme.background
额外优化:动态颜色下保留纯黑/纯白背景
如果希望开启动态颜色时,背景仍保持纯黑或纯白,可以修改主题的配色逻辑,覆盖动态配色的背景色:
val colorScheme = when { dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { val context = LocalContext.current if (darkTheme) { dynamicDarkColorScheme(context).copy(background = Color.Black) } else { dynamicLightColorScheme(context).copy(background = Color.White) } } darkTheme -> DarkColorScheme else -> LightColorScheme }
内容的提问来源于stack exchange,提问作者Compose Learner

