Android应用屏幕旋转后语言变更问题:onConfigurationChanged回调未触发
问题解决方法
首先解决
onConfigurationChanged不触发的问题
你需要在AndroidManifest.xml中为主Activity添加configChanges属性,声明你要自行处理的配置变更事件,系统才会回调该方法:<activity android:name=".你的主Activity类名" android:configChanges="orientation|screenSize|locale|layoutDirection" ... 其他配置 />其中
locale和layoutDirection是处理语言切换的必要配置,orientation和screenSize是处理屏幕旋转的必要配置。修正语言设置的逻辑问题
你现有代码存在两个核心错误:- 不应该从
newConfig.locales[1]取语言,系统Locale列表的顺序不固定,你应该提前把用户选择的语言(EN/AR)持久化存储到SharedPreferences中,每次都读取你自己存的用户偏好值 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
相关产品推荐
相关产品推荐

