跳到主要内容

深色模式适配实战

场景

产品需要全面支持系统深色模式,覆盖所有页面和自定义组件。

方案

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)
}

面试答题要点

  1. 使用 DayNight 主题 + ?attr/ 引用是基础
  2. 颜色通过 values / values-night 成对管理
  3. WebView、第三方 SDK、状态栏是常见踩坑点
  4. Compose 用 isSystemInDarkTheme() + MaterialTheme 即可

相关链接