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

Android API 23以下版本如何通过代码动态切换应用语言

修复方案

问题根因

  • 直接new Configuration()创建配置对象,未继承当前上下文已有的配置项,Android 5.x版本会忽略未显式设置的配置参数,导致语言修改不生效
  • 仅更新了baseContext的资源配置,未同步更新Application全局上下文的配置,部分资源加载时会复用全局默认配置
  • 首次启动时如果SharedPreferences未存储过语言配置,loadLocale()返回空字符串,构造Locale时参数无效,导致语言设置失败
  • 未重写Activity的attachBaseContext方法,Activity创建/重建时系统会恢复默认配置,覆盖你之前设置的语言

代码修改

1. 修改MainActivity代码

public class MainActivity extends AppCompatActivity {

    PreferenceRepository preferenceRepository;
    @SuppressLint({"NonConstantResourceId", "SourceLockedOrientationActivity"})
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        preferenceRepository = new PreferenceRepository(this);
        setContentView(R.layout.activity_main);

        // 初始化控件
        RadioButton GeLang = findViewById(R.id.GeorgianLang);
        RadioButton EnLang = findViewById(R.id.EnglishLang);
        RadioGroup LanguageApp = findViewById(R.id.Language);

        // 根据当前语言选中对应单选按钮
        if (Locale.getDefault().getDisplayLanguage().equals("ქართული")){
            GeLang.setChecked(true);
        } else {
            EnLang.setChecked(true);
        }

        // 选中后切换语言
        LanguageApp.setOnCheckedChangeListener((LanguageApp1, i) -> {
            switch (i) {
                case R.id.GeorgianLang:
                    setLocale("ka");
                    recreate();
                    break;
                case R.id.EnglishLang:
                    setLocale("en");
                    recreate();
                    break;
            }
        });
    }

    @Override
    protected void attachBaseContext(Context newBase) {
        PreferenceRepository tempRepo = new PreferenceRepository(newBase);
        String lang = tempRepo.loadLocale();
        if (TextUtils.isEmpty(lang)) {
            super.attachBaseContext(newBase);
            return;
        }
        Locale locale = new Locale(lang);
        Locale.setDefault(locale);
        Resources res = newBase.getResources();
        Configuration config = new Configuration(res.getConfiguration());
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            config.setLocale(locale);
        } else {
            config.locale = locale;
        }
        Context context = newBase.createConfigurationContext(config);
        super.attachBaseContext(context);
    }

    // 更新配置并加载选中的语言
    private void setLocale(String language) {
        // 处理空值,默认取系统当前语言
        if (TextUtils.isEmpty(language)) {
            language = Locale.getDefault().getLanguage();
        }
        Locale locale = new Locale(language);
        Locale.setDefault(locale);
        Resources resources = getResources();
        Configuration config = resources.getConfiguration();
        // 兼容低版本API
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            config.setLocale(locale);
        } else {
            config.locale = locale;
        }
        // 更新当前上下文配置
        resources.updateConfiguration(config, resources.getDisplayMetrics());
        // 同步更新全局Application配置
        getApplicationContext().getResources().updateConfiguration(config, getApplicationContext().getResources().getDisplayMetrics());
        preferenceRepository.setLocale(language);
    }
}

2. PreferenceRepository代码无需调整,如需指定默认语言可修改loadLocale方法:

public String loadLocale() {
    // 示例:默认设置为英文就传入"en",留空则默认取系统语言
    return mySharedPref.getString("My_Language", "");
}

额外注意事项

  • 确保格鲁吉亚语资源文件夹命名为res/values-ka,不要添加多余的地区后缀,Android 5.x对带地区的资源匹配逻辑存在兼容问题
  • 如果应用存在多个Activity,建议把attachBaseContext重写、setLocale逻辑封装到BaseActivity中,所有Activity继承BaseActivity即可统一适配
  • 切换语言调用recreate()会触发页面重绘,可根据需要添加过渡动画避免闪屏

内容的提问来源于stack exchange,提问作者Ksardas Freeman

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 00:24:00