深色模式已成为现代应用的标配功能,不仅能减少眼睛疲劳、节省电量,还能提供更好的视觉体验。本文将深入讲解如何在 Compose 中实现完善的深色模式支持。
一、检测系统深色模式
@Composable
fun App() {
val isDarkTheme = isSystemInDarkTheme()
MyAppTheme(darkTheme = isDarkTheme) {
MainContent()
}
}
二、用户可控的主题切换
enum class ThemeMode { LIGHT, DARK, SYSTEM }
@Composable
fun App(viewModel: ThemeViewModel) {
val themeMode by viewModel.themeMode.collectAsState()
val systemDarkTheme = isSystemInDarkTheme()
val isDarkTheme = when (themeMode) {
ThemeMode.LIGHT -> false
ThemeMode.DARK -> true
ThemeMode.SYSTEM -> systemDarkTheme
}
MyAppTheme(darkTheme = isDarkTheme) {
MainContent()
}
}
三、Material You 动态颜色
@Composable
fun MyAppTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
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
}
MaterialTheme(colorScheme = colorScheme, content = content)
}
四、DataStore 持久化
class ThemePreferences(private val dataStore: DataStore<Preferences>) {
val themeMode: Flow<ThemeMode> = dataStore.data
.map { preferences ->
val modeString = preferences[THEME_MODE_KEY] ?: ThemeMode.SYSTEM.name
ThemeMode.valueOf(modeString)
}
suspend fun setThemeMode(mode: ThemeMode) {
dataStore.edit { it[THEME_MODE_KEY] = mode.name }
}
}
五、语义化颜色
// ✅ 好:使用 MaterialTheme 颜色
Card(
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surface,
contentColor = MaterialTheme.colorScheme.onSurface
)
)
// ❌ 避免:硬编码颜色
Card(
colors = CardDefaults.cardColors(
containerColor = Color.White // 深色模式下会很刺眼
)
)
💡 最佳实践
始终使用 MaterialTheme.colorScheme 中的颜色,避免硬编码。这样可以确保应用在深色和浅色模式下都能正确显示。
六、Preview 预览两种主题
@Preview(name = "Light Mode")
@Preview(name = "Dark Mode", uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
fun ScreenPreview() {
MyAppTheme {
MyScreen()
}
}
七、最佳实践
- ✅ 使用
MaterialTheme.colorScheme而非硬编码颜色 - ✅ 提供浅色/深色/跟随系统三种选项
- ✅ 使用 DataStore 持久化用户偏好
- ✅ Android 12+ 支持 Material You 动态颜色
- ✅ 为深色模式适配图片和图标
- ✅ 在 Preview 中同时预览两种主题
总结
- isSystemInDarkTheme():检测系统深色模式
- ColorScheme:Material3 的颜色方案
- dynamicColorScheme:Android 12+ 动态颜色
- DataStore:持久化主题偏好
- 语义化颜色:避免硬编码