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

Android 8.0应用语言切换异常问题求助

Android 8.0应用语言切换问题解决方案

我一看你这情况就知道是Android 7.0+系统里语言切换的典型坑——旧的配置更新API已经失效,再加上Context初始化时机和Activity重启方式不对,才导致切换时Toolbar没同步、杀进程后又变回英文。我给你梳理下问题根源,再直接上可运行的修复代码:

问题拆解

  1. 废弃API拖后腿:Android N(7.0)之后,resources.updateConfiguration()被标记为废弃,直接调用根本没法保证配置在所有组件里生效。
  2. Application初始化时机错了:在onCreate()里设置语言太晚,Application的Context已经初始化完了,后续启动的组件还是会用默认配置,杀进程重启自然就还原了。
  3. Activity重启方式不合理:用finish() + startActivity(intent)重启Activity,容易因为栈的问题导致配置没重新加载,比如Toolbar这类系统控件就没同步更新。

修复步骤

1. 重构Application类,在正确时机初始化语言

我们得在attachBaseContext()里设置语言,这是Application Context创建的最早阶段,能确保所有后续组件都继承正确的语言配置:

class MyApplication : Application() {
    companion object {
        // 封装语言更新方法,返回更新后的Context
        fun updateLanguage(context: Context, lang: String): Context {
            val targetLocale = Locale(lang)
            Locale.setDefault(targetLocale)

            val resources = context.resources
            val config = resources.configuration.apply {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    // Android N及以上用setLocales替代旧的setLocale
                    setLocale(targetLocale)
                    setLocales(LocaleList(targetLocale))
                } else {
                    @Suppress("DEPRECATION")
                    setLocale(targetLocale)
                }
            }

            return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                // Android N+用createConfigurationContext生成新的配置Context
                context.createConfigurationContext(config)
            } else {
                // 低版本仍使用updateConfiguration
                @Suppress("DEPRECATION")
                resources.updateConfiguration(config, resources.displayMetrics)
                context
            }
        }
    }

    override fun attachBaseContext(base: Context?) {
        // 先读取保存的语言设置,再初始化Context
        val sharedPref = PreferenceManager.getDefaultSharedPreferences(base)
        val savedLang = sharedPref.getString("lang", "en") ?: "en"
        // 更新Context后再传给父类,确保后续组件用的都是新配置
        super.attachBaseContext(base?.let { updateLanguage(it, savedLang) })
    }

    override fun onCreate() {
        super.onCreate()
        // 这里不再需要设置语言,attachBaseContext已经处理完毕
    }
}

2. 修改MainActivity的语言切换逻辑

用recreate()替代旧的重启方式,确保Activity完全重建并加载新配置;同时在切换时立即更新当前Activity的配置:

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val sharedPref = PreferenceManager.getDefaultSharedPreferences(this)
        val currentLang = sharedPref.getString("lang", "en") ?: "en"

        // 每次onCreate都同步按钮和Toolbar文字,确保语言生效
        switchLanguage.setText(if (currentLang == "en") R.string.english else R.string.viet)
        switchLanguage.isChecked = currentLang != "en"

        switchLanguage.setOnCheckedChangeListener { _, isChecked ->
            val targetLang = if (!isChecked) "en" else "vi"
            // 保存语言设置到SharedPreferences
            sharedPref.edit().putString("lang", targetLang).apply()
            // 更新当前Activity配置并重建,确保所有控件同步语言
            val updatedContext = MyApplication.updateLanguage(this, targetLang)
            applyOverrideConfiguration(updatedContext.resources.configuration)
            recreate()
        }
    }
}

关键修改说明

  • attachBaseContext初始化:保证Application的Context从一开始就用指定语言,杀进程重启后不会还原为系统默认语言。
  • 适配Android N+API:用createConfigurationContext和setLocales替代废弃API,确保配置在所有组件中生效。
  • Activity重建方式:recreate()会触发Activity完整生命周期重建,包括Toolbar在内的所有控件都会重新加载当前语言的资源。

这样修改后,你应该就能解决切换时Toolbar不同步、杀进程后还原的问题了。

内容的提问来源于stack exchange,提问作者Hoang Duc Tuan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:23:00