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

Android应用屏幕旋转后语言变更问题:onConfigurationChanged回调未触发

问题解决方法
  • 首先解决onConfigurationChanged不触发的问题
    你需要在AndroidManifest.xml中为主Activity添加configChanges属性,声明你要自行处理的配置变更事件,系统才会回调该方法:

    <activity
        android:name=".你的主Activity类名"
        android:configChanges="orientation|screenSize|locale|layoutDirection"
        ... 其他配置 />
    

    其中locale和layoutDirection是处理语言切换的必要配置,orientation和screenSize是处理屏幕旋转的必要配置。

  • 修正语言设置的逻辑问题
    你现有代码存在两个核心错误:

    1. 不应该从newConfig.locales[1]取语言,系统Locale列表的顺序不固定,你应该提前把用户选择的语言(EN/AR)持久化存储到SharedPreferences中,每次都读取你自己存的用户偏好值
    2. resources.updateConfiguration在Android 7.0及以上版本已经废弃,生效不稳定,推荐通过重写attachBaseContext的方式应用语言配置,这种方式在Activity重建、配置变更时都会自动生效,比onConfigurationChanged更可靠
  • 正确实现示例
    首先是持久化存储用户选择的语言,比如用户切换到阿拉伯语时执行:

    // 存用户选择的语言
    getSharedPreferences("app_config", Context.MODE_PRIVATE)
      .edit()
      .putString("selected_locale", "ar")
      .apply()
    

    然后在主Activity中重写attachBaseContext:

    override fun attachBaseContext(newBase: Context) {
        val selectedLocale = getSharedPreferences("app_config", Context.MODE_PRIVATE)
            .getString("selected_locale", "en") ?: "en"
        val locale = Locale(selectedLocale)
        Locale.setDefault(locale)
        
        val config = Configuration(newBase.resources.configuration)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            config.setLocale(locale)
            val localeList = LocaleList(locale)
            LocaleList.setDefault(localeList)
            config.setLocales(localeList)
        } else {
            config.locale = locale
        }
        
        val updatedContext = newBase.createConfigurationContext(config)
        super.attachBaseContext(updatedContext)
    }
    

    如果你还是需要使用onConfigurationChanged,修正后的写法为:

    override fun onConfigurationChanged(newConfig: Configuration) {
        super.onConfigurationChanged(newConfig)
        // 读取自己存的用户选择的语言,不要从newConfig里取
        val selectedLocale = getSharedPreferences("app_config", Context.MODE_PRIVATE)
            .getString("selected_locale", "en") ?: "en"
        setLocale(selectedLocale)
        // 配置变化后刷新当前显示的Fragment内容
        supportFragmentManager.fragments.forEach { fragment ->
            fragment.onConfigurationChanged(newConfig)
            // 必要时可以让Fragment重新加载视图内容
        }
    }
    
    private fun setLocale(localeLan: String) {
        val locale = Locale(localeLan)
        Locale.setDefault(locale)
        val config = resources.configuration
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            config.setLocale(locale)
            config.setLocales(LocaleList(locale))
        } else {
            config.locale = locale
        }
        resources.updateConfiguration(config, resources.displayMetrics)
    }
    
  • 额外注意
    不需要在Fragment中实现onConfigurationChanged,只要Activity的上下文配置正确,Fragment会自动继承Activity的资源配置,如果你发现Fragment还是显示错误语言,可以在配置变更后手动调用Fragment重新加载文本内容。


内容的提问来源于stack exchange,提问作者Owies AL omari

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 14:45:02