如何通过RadioGroup内的RadioButton选择并用SharedPreferences保存深浅模式设置
具体实现方案
1. 预定义常量(避免硬编码)
直接复用系统主题常量,不需要额外做映射,减少出错概率:
// 可存放在常量类或对应Activity中 const val SP_NAME_THEME = "theme_sp" const val SP_KEY_THEME_MODE = "theme_mode" // 直接复用AppCompatDelegate的官方主题常量,取值对应如下: // 浅色模式:AppCompatDelegate.MODE_NIGHT_NO = 1 // 深色模式:AppCompatDelegate.MODE_NIGHT_YES = 2 // 跟随系统:AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM = -1
2. 监听RadioGroup选中事件,持久化配置并生效主题
在设置页的onCreate方法中给RadioGroup绑定监听,选中时同时执行存储和主题生效逻辑:
// 初始化SharedPreferences实例 val themeSp = getSharedPreferences(SP_NAME_THEME, Context.MODE_PRIVATE) themeRadioGroup.setOnCheckedChangeListener { _, checkedId -> val targetThemeMode = when(checkedId) { R.id.rb_light_mode -> AppCompatDelegate.MODE_NIGHT_NO R.id.rb_dark_mode -> AppCompatDelegate.MODE_NIGHT_YES // 如果需要跟随系统选项可以加下面这行,不需要就删掉 R.id.rb_follow_system -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM else -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM } // 写入SharedPreferences持久化存储,异步写入用apply不会阻塞主线程 themeSp.edit() .putInt(SP_KEY_THEME_MODE, targetThemeMode) .apply() // 立即切换当前应用的主题 AppCompatDelegate.setDefaultNightMode(targetThemeMode) }
3. 应用启动时读取已存配置,恢复主题和选中状态
注意主题设置逻辑必须放在setContentView之前执行,否则布局加载时主题不生效:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 第一步:读取已存储的主题配置,先设置主题再加载布局 val themeSp = getSharedPreferences(SP_NAME_THEME, Context.MODE_PRIVATE) val savedThemeMode = themeSp.getInt(SP_KEY_THEME_MODE, AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) AppCompatDelegate.setDefaultNightMode(savedThemeMode) // 第二步:加载布局 setContentView(R.layout.activity_setting) // 第三步:给RadioGroup设置对应选中状态,和存储的配置保持一致 val checkedRadioId = when(savedThemeMode) { AppCompatDelegate.MODE_NIGHT_NO -> R.id.rb_light_mode AppCompatDelegate.MODE_NIGHT_YES -> R.id.rb_dark_mode AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM -> R.id.rb_follow_system else -> R.id.rb_follow_system } themeRadioGroup.check(checkedRadioId) }
补充说明
- 如果是多Activity项目,建议把读取主题并设置的逻辑放到自定义
Application类的onCreate方法中执行,全局生效不需要每个页面重复编写 - Java实现逻辑完全一致,仅语法差异,SharedPreferences存int值、监听RadioGroup选中、设置主题的逻辑没有变化
- 不需要对主题模式做自定义的字符串映射,直接用系统提供的int常量效率更高也避免映射错误
内容的提问来源于stack exchange,提问作者JaloliddinPage
相关产品推荐
相关产品推荐

