Android Studio中Kotlin应用主题切换初始化异常问题求助
主题切换问题解决方案
核心问题分析
你现在的问题根源有两个:
- 用了
getPreferences(Context.MODE_PRIVATE),这是单个Activity专属的SharedPreferences,MainActivity和SettingsActivity的配置文件是分开的,所以Settings里存的主题设置,MainActivity读不到。 - SettingsActivity的主题初始化放在了
super.onCreate()之后,导致页面先加载默认主题再切换,出现闪屏。
具体修复步骤
1. 统一全局SharedPreferences
把所有Activity里的getPreferences(Context.MODE_PRIVATE)替换成全局共享的SP:
sharedPreferences = getSharedPreferences("AppSettings", Context.MODE_PRIVATE)
这样所有组件读写的是同一个配置文件,主题设置能跨页面同步。
2. 修正主题初始化时机
所有Activity的主题初始化逻辑必须放在super.onCreate(savedInstanceState)之前执行,确保页面加载前就应用主题,避免闪屏。
3. 修改SettingsActivity代码
class SettingsActivity : AppCompatActivity() { private lateinit var binding: ActivitySettingsBinding private lateinit var sharedPreferences: SharedPreferences override fun onCreate(savedInstanceState: Bundle?) { // 先初始化主题,再调用super.onCreate initializeTheme() super.onCreate(savedInstanceState) binding = ActivitySettingsBinding.inflate(layoutInflater) setContentView(binding.root) sharedPreferences = getSharedPreferences("AppSettings", Context.MODE_PRIVATE) // 只初始化开关状态,不用重复设置主题(已经在initializeTheme里做了) binding.themeSwitch.isChecked = sharedPreferences.getBoolean("enable_dark_theme", false) binding.themeSwitch.setOnCheckedChangeListener { _, isChecked -> // 切换主题 AppCompatDelegate.setDefaultNightMode( if (isChecked) AppCompatDelegate.MODE_NIGHT_YES else AppCompatDelegate.MODE_NIGHT_NO ) // 保存设置 with(sharedPreferences.edit()) { putBoolean("enable_dark_theme", isChecked) apply() } } binding.backButtonSettings.setOnClickListener { finish() } } private fun initializeTheme() { sharedPreferences = getSharedPreferences("AppSettings", Context.MODE_PRIVATE) val isDarkThemeEnabled = sharedPreferences.getBoolean("enable_dark_theme", false) AppCompatDelegate.setDefaultNightMode( if (isDarkThemeEnabled) AppCompatDelegate.MODE_NIGHT_YES else AppCompatDelegate.MODE_NIGHT_NO ) } }
4. 修改MainActivity代码
class MainActivity : AppCompatActivity() { private lateinit var binding: ActivityMainBinding private lateinit var sharedPreferences: SharedPreferences private val startInputActivityLauncher: ActivityResultLauncher<Intent> = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> if (result.resultCode == RESULT_OK) { val data = result.data val productName = data?.getStringExtra("productName") val productPrice = data?.getDoubleExtra("productPrice", 0.0) if (!productName.isNullOrBlank() && productPrice != null) { val myApplication = application as MyApplication myApplication.addProductToWarehouse(productName, productPrice) showToast(getString(R.string.toast_product_added, productName, productPrice)) } else { println("输入的信息不正确") } } } override fun onCreate(savedInstanceState: Bundle?) { // 先初始化主题 initializeTheme() super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) val exitButton = binding.exitButton val inputButton = binding.inputButton val aboutButton = binding.aboutButton val settingsButton = binding.settings inputButton.setOnClickListener { val intent = Intent(this, InputActivity::class.java) startInputActivityLauncher.launch(intent) } aboutButton.setOnClickListener { val intent = Intent(this, AboutActivity::class.java) startActivity(intent) } exitButton.setOnClickListener { finish() } settingsButton.setOnClickListener { val intent = Intent(this, SettingsActivity::class.java) startActivity(intent) } } private fun initializeTheme() { sharedPreferences = getSharedPreferences("AppSettings", Context.MODE_PRIVATE) val isDarkThemeEnabled = sharedPreferences.getBoolean("enable_dark_theme", false) AppCompatDelegate.setDefaultNightMode( if (isDarkThemeEnabled) AppCompatDelegate.MODE_NIGHT_YES else AppCompatDelegate.MODE_NIGHT_NO ) } private fun showToast(message: String) { Toast.makeText(this, message, Toast.LENGTH_SHORT).show() } }
额外建议
- 其他Activity(比如InputActivity、AboutActivity)也要加上同样的
initializeTheme()逻辑,放在super.onCreate()之前,确保所有页面主题统一。 - 如果想在Application类里初始化主题,要注意:Application的onCreate里初始化时,要确保SP能正确读取,而且设置主题后,后续启动的Activity都会生效,但切换主题后需要重启所有Activity才能立即生效(可以在切换主题后发送广播,让所有Activity重启)。不过对于你的作业场景,上面的方案足够简单有效。
内容的提问来源于stack exchange,提问作者PrzgiBaklo
相关产品推荐
相关产品推荐

