深色模式适配实战
场景
产品需要全面支持系统深色模式,覆盖所有页面和自定义组件。
方案
1. 基础适配
// 1. 继承 DayNight 主题
// res/values/themes.xml
// <style name="AppTheme" parent="Theme.Material3.DayNight">
// 2. 使用主题属性而非硬编码颜色
// ❌ android:textColor="#000000"
// ✅ android:textColor="?attr/colorOnSurface"
// 3. 在代码中处理
class App : Application() {
override fun onCreate() {
super.onCreate()
// 跟随系统设置
AppCompatDelegate.setDefaultNightMode(
AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
)
}
}
2. 资源分组
| 资源目录 | 用途 |
|---|---|
res/values/colors.xml | 浅色模式颜色 |
res/values-night/colors.xml | 深色模式颜色 |
res/drawable/ | 通用图片 |
res/drawable-night/ | 深色模式专用图片 |
<!-- res/values/colors.xml -->
<color name="surface">#FFFFFF</color>
<color name="onSurface">#1C1B1F</color>
<!-- res/values-night/colors.xml -->
<color name="surface">#1C1B1F</color>
<color name="onSurface">#E6E1E5</color>
3. 常见坑点
| 问题 | 解决 |
|---|---|
| 第三方 WebView 不跟随深色 | WebSettings.setForceDark() (deprecated) → CSS prefers-color-scheme |
| 硬编码颜色散落各处 | Lint 检查 HardcodedColor + 全局替换 |
| Splash 画面颜色不对 | SplashScreen API 的 windowSplashScreenBackground |
| 状态栏/导航栏颜色 | WindowInsetsControllerCompat.setAppearanceLightStatusBars() |
| 图片在深色背景下看不清 | 提供 -night 变体或添加 tint |
4. Compose 适配
@Composable
fun AppTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit
) {
val colorScheme = if (darkTheme) darkColorScheme() else lightColorScheme()
MaterialTheme(colorScheme = colorScheme, content = content)
}
面试答题要点
- 使用
DayNight主题 +?attr/引用是基础 - 颜色通过
values/values-night成对管理 - WebView、第三方 SDK、状态栏是常见踩坑点
- Compose 用
isSystemInDarkTheme()+MaterialTheme即可