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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 22:50:35