猿问

Android N以编程方式更改语言

我发现了只在Android N设备上才能复制的真正奇怪的错误。


在浏览我的应用程序时,可以更改语言。这是更改它的代码。


 public void update(Locale locale) {


    Locale.setDefault(locale);


    Configuration configuration = res.getConfiguration();


    if (BuildUtils.isAtLeast24Api()) {

        LocaleList localeList = new LocaleList(locale);


        LocaleList.setDefault(localeList);

        configuration.setLocales(localeList);

        configuration.setLocale(locale);


    } else if (BuildUtils.isAtLeast17Api()){

        configuration.setLocale(locale);


    } else {

        configuration.locale = locale;

    }


    res.updateConfiguration(configuration, res.getDisplayMetrics());

}

该代码在我的巡回活动(带recreate()电话)中效果很好,但是在接下来的所有活动中,所有String资源都是错误的。屏幕旋转将其修复。我该怎么办?我应该以其他方式更改Android N的语言环境还是仅仅是系统错误?


PS这是我发现的。第一次启动MainActivity时(在我的旅行之后)Locale.getDefault()是正确的,但是资源错误。但是在其他活动中,它会给我错误的语言环境和该语言环境的错误资源。旋转后屏幕(或其他一些配置更改)Locale.getDefault()是正确的。


翻过高山走不出你
浏览 562回答 3
3回答

凤凰求蛊

好。最后,我设法找到了解决方案。首先,您应该知道在25个API Resources.updateConfiguration(...)中已弃用。因此,您可以执行以下操作:1)您需要创建自己的ContextWrapper,它将覆盖baseContext中的所有配置参数。例如,这是我的ContextWrapper,可以正确更改Locale。注意context.createConfigurationContext(configuration)方法。public class ContextWrapper extends android.content.ContextWrapper {    public ContextWrapper(Context base) {        super(base);    }    public static ContextWrapper wrap(Context context, Locale newLocale) {        Resources res = context.getResources();        Configuration configuration = res.getConfiguration();        if (BuildUtils.isAtLeast24Api()) {            configuration.setLocale(newLocale);            LocaleList localeList = new LocaleList(newLocale);            LocaleList.setDefault(localeList);            configuration.setLocales(localeList);            context = context.createConfigurationContext(configuration);        } else if (BuildUtils.isAtLeast17Api()) {            configuration.setLocale(newLocale);            context = context.createConfigurationContext(configuration);        } else {            configuration.locale = newLocale;            res.updateConfiguration(configuration, res.getDisplayMetrics());        }        return new ContextWrapper(context);    }}2)这是您在BaseActivity中应该做的事情:@Overrideprotected void attachBaseContext(Context newBase) {    Locale newLocale;    // .. create or get your new Locale object here.    Context context = ContextWrapper.wrap(newBase, newLocale);    super.attachBaseContext(context);}注意:如果要在某个地方更改应用程序的区域设置,请记住要重新创建活动。您可以使用此解决方案覆盖所需的任何配置。

ABOUTYOU

受各种代码的启发(例如:我们的Stackoverflow团队(大声疾呼)),我制作了一个简单得多的版本。该ContextWrapper扩展名是不必要的。首先,假设您有2个按钮用于2种语言,即EN和KH。在按钮的onClick中,将语言代码保存到中SharedPreferences,然后调用activity recreate()方法。例:@Overridepublic void onClick(View v) {    switch(v.getId()) {        case R.id.btn_lang_en:            //save "en" to SharedPref here            break;        case R.id.btn_lang_kh:            //save "kh" to SharedPref here            break;        default:        break;    }    getActivity().recreate();}然后创建一个ContextWrapper可能在Utils类中返回的静态方法(这就是我所做的,lul)。public static ContextWrapper changeLang(Context context, String lang_code){    Locale sysLocale;    Resources rs = context.getResources();    Configuration config = rs.getConfiguration();    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {        sysLocale = config.getLocales().get(0);    } else {        sysLocale = config.locale;    }    if (!lang_code.equals("") && !sysLocale.getLanguage().equals(lang_code)) {        Locale locale = new Locale(lang_code);        Locale.setDefault(locale);        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {            config.setLocale(locale);        } else {            config.locale = locale;        }        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {            context = context.createConfigurationContext(config);        } else {            context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics());        }    }    return new ContextWrapper(context);}最后,从加载的语言代码SharedPreferences中的所有活动'S attachBaseContext(Context newBase)方法。@Overrideprotected void attachBaseContext(Context newBase) {    String lang_code = "en"; //load it from SharedPref    Context context = Utils.changeLang(newBase, lang_code);    super.attachBaseContext(context);}奖励:为了节省键盘上的汗水,我创建了一个LangSupportBaseActivity类,扩展了类Activity并在其中使用最后一块代码。并且我将所有其他活动扩展LangSupportBaseActivity。例:public class LangSupportBaseActivity extends Activity{    ...blab blab blab so on and so forth lines of neccessary code    @Override    protected void attachBaseContext(Context newBase) {        String lang_code = "en"; //load it from SharedPref        Context context = Utils.changeLang(newBase, lang_code);        super.attachBaseContext(context);    }}public class HomeActivity extends LangSupportBaseActivity{    ...blab blab blab}

哔哔one

从Android 7.0+开始,我的应用程序的某些部分不再更改其语言。即使使用上面提出的新方法。应用程序和活动上下文的更新对我有所帮助。这是Activity子类覆盖的Kotlin示例:private fun setApplicationLanguage(newLanguage: String) {    val activityRes = resources    val activityConf = activityRes.configuration    val newLocale = Locale(newLanguage)    activityConf.setLocale(newLocale)    activityRes.updateConfiguration(activityConf, activityRes.displayMetrics)    val applicationRes = applicationContext.resources    val applicationConf = applicationRes.configuration    applicationConf.setLocale(newLocale)    applicationRes.updateConfiguration(applicationConf,            applicationRes.displayMetrics)}override fun attachBaseContext(newBase: Context?) {    super.attachBaseContext(newBase)    setApplicationLanguage("fa");}注意:不建议使用updateConfiguration,但是无论如何,每个Activity的createConfigurationContext都保留一些字符串不变。
随时随地看视频慕课网APP

相关分类

Java
Android
我要回答