You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Android中通过Switch Button切换App为dark theme深色主题

Android 实现Switch切换深色主题方案

1. 基础主题适配配置

首先确认项目使用DayNight系列兼容主题,分别定义日夜间两套主题配置:

  • 在res/values/styles.xml中定义日间主题:
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
    <item name="colorPrimary">@color/purple_500</item>
    <item name="colorPrimaryVariant">@color/purple_700</item>
    <item name="colorOnPrimary">@color/white</item>
    <item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
    <!-- 其他自定义属性 -->
</style>
  • 新建res/values-night/styles.xml定义深色主题:
<style name="AppTheme" parent="Theme.MaterialComponents.Dark.NoActionBar">
    <item name="colorPrimary">@color/purple_200</item>
    <item name="colorPrimaryVariant">@color/purple_400</item>
    <item name="colorOnPrimary">@color/black</item>
    <item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
    <!-- 其他深色模式下的自定义属性 -->
</style>

所有需要适配主题的颜色,都需要分别在res/values/colors.xml和res/values-night/colors.xml中定义对应色值,不要在布局、代码中硬编码色值。

2. 持久化存储主题状态

通过SharedPreferences存储用户的主题选择,避免应用重启后设置丢失,可封装为工具类调用:

object ThemeHelper {
    private const val PREF_NAME = "theme_config"
    private const val KEY_DARK_MODE = "is_dark_mode"

    // 应用当前保存的主题
    fun applySavedTheme(context: Context) {
        val darkModeEnabled = getDarkModeState(context)
        AppCompatDelegate.setDefaultNightMode(
            if (darkModeEnabled) AppCompatDelegate.MODE_NIGHT_YES 
            else AppCompatDelegate.MODE_NIGHT_NO
        )
    }

    // 保存用户选择的主题状态
    fun saveDarkModeState(context: Context, isDark: Boolean) {
        context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
            .edit()
            .putBoolean(KEY_DARK_MODE, isDark)
            .apply()
    }

    // 读取已保存的主题状态,默认返回false(日间模式)
    fun getDarkModeState(context: Context): Boolean {
        return context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
            .getBoolean(KEY_DARK_MODE, false)
    }
}

3. 绑定Switch控件交互逻辑

在放置Switch的Activity/Fragment中添加切换监听,注意主题应用方法要放在super.onCreate和setContentView之前调用:

override fun onCreate(savedInstanceState: Bundle?) {
    // 必须在super.onCreate之前调用,否则主题不生效
    ThemeHelper.applySavedTheme(this)
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_settings)

    val themeSwitch = findViewById<Switch>(R.id.switch_dark_theme)
    // 初始化Switch状态为已保存的主题状态
    themeSwitch.isChecked = ThemeHelper.getDarkModeState(this)
    
    themeSwitch.setOnCheckedChangeListener { _, isChecked ->
        ThemeHelper.saveDarkModeState(this, isChecked)
        // 重建当前Activity让主题立刻生效
        recreate()
        // 若需要全局所有已打开页面立刻生效,可发送广播通知栈内其他Activity也执行recreate
    }
}

额外优化说明

  • 所有Activity的onCreate方法都要在最开头调用ThemeHelper.applySavedTheme(this),否则新打开页面的主题会不生效
  • 如果不需要切换时的Activity重启闪烁效果,可在recreate()后调用overridePendingTransition(0, 0)取消默认切换动画
  • 若使用Jetpack Compose开发,只需要在主题Composable中根据存储的状态判断调用darkColorScheme或lightColorScheme即可,不需要重建Activity

内容的提问来源于stack exchange,提问作者Sina Moradi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 19:39:04