为什么Android 8以下设备的Activity语言切换功能不生效?
问题原因
你当前的实现存在两个核心问题导致低版本系统语言切换不生效:
- 版本适配逻辑错误:
createConfigurationContext是API 17就提供的系统方法,你当前仅在Android 7.0(API 24)及以上版本使用该方法返回更新后的Context对象,低于API 24的版本直接返回了原始Context,即使你修改了原始Context的Resources配置,Activity初始化时还是会读取默认配置加载资源,导致切换失效。 - 缺少全局资源同步:Android 7.1及更低版本中,部分通用资源会优先从Application级别的Resources中加载,仅修改Activity的Context配置没有同步更新全局资源配置,也会导致语言不生效。
修复后的实现代码
override fun attachBaseContext(newBase: Context) { val newContext = updateBaseContextLocale(newBase) super.attachBaseContext(newContext) } private fun updateBaseContextLocale(context: Context): Context { val locale = getMyLocale() // 获取需要使用的目标locale Locale.setDefault(locale) // 同步更新Application全局的资源配置,解决低版本全局资源加载问题 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { val appConfig = context.applicationContext.resources.configuration appConfig.setLocale(locale) context.applicationContext.createConfigurationContext(appConfig) } else { val appResources = context.applicationContext.resources val appConfig = appResources.configuration appConfig.locale = locale appResources.updateConfiguration(appConfig, appResources.displayMetrics) } // 所有API 17及以上版本都使用createConfigurationContext返回新Context return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { val config = context.resources.configuration config.setLocale(locale) context.createConfigurationContext(config) } else { // 仅minSdk低于17时需要保留该分支逻辑 val resources = context.resources val configuration = resources.configuration configuration.locale = locale resources.updateConfiguration(configuration, resources.displayMetrics) context } }
额外注意事项
- 如果你需要全局修改应用语言,只需要在自定义Application的
attachBaseContext方法中添加相同的逻辑即可,不需要每个Activity单独实现。 - 如果是运行时动态切换语言,切换完成后需要调用Activity的
recreate()方法重建页面,新的语言配置才会生效。 - 如果你需要仅修改单个Activity的语言,去掉代码中同步更新Application全局资源的逻辑即可,仅保留当前Context的配置更新。
内容的提问来源于stack exchange,提问作者AndroidKotlinNoob
相关产品推荐
相关产品推荐

