Android N-在运行时更改语言环境 [英] Android N - Change Locale in runtime

查看:190
本文介绍了Android N-在运行时更改语言环境的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个android应用程序,我想向其添加一个简单的首选项屏幕,并使用一个选项在语言(英语和葡萄牙语)之间切换.我已经有适当的字符串资源文件了.

如果我在系统偏好设置中更改操作系统的主要语言并重新加载应用程序,它将使用该语言,但是我希望能够通过偏好设置屏幕来做到这一点.

我在这里的其他问题中看到,在以前的Android版本中这样做要容易得多,但是现在不赞成使用该代码,因此我采用了在每个活动中覆盖attachBaseContext方法的方法,以便通过包装程序,我在该包装程序中加载当前在首选项中选择的语言环境,如这篇文章所示:

Android N以编程方式更改语言

public class TCPreferenceActivity extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener {


@Override
public void onBuildHeaders(List<Header> target) {
    loadHeadersFromResource(R.xml.headers_preference, target);
}

@Override
protected boolean isValidFragment(String fragmentName) {
    return TCPreferenceFragment.class.getName().equals(fragmentName);
}


@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
    if (key.equals("lang")) {
        recreate();
    }
}



@Override
protected void attachBaseContext(Context newBase) {

    SharedPreferences pref =  PreferenceManager.getDefaultSharedPreferences(newBase);

    String lang = pref.getString("lang", null);

    Locale locale = new Locale(lang);

    Context context = TCContextWrapper.wrap(newBase, locale);
    super.attachBaseContext(context);
}

}

据我所知,在更改首选项时,将调用onSharedPreferenceChanged方法.我在那里重新创建了活动,以便可以在新的上下文中重新启动它.

这是我的上下文包装器:

public class TCContextWrapper extends ContextWrapper {

public TCContextWrapper(Context base) {
    super(base);
}

public static ContextWrapper wrap(Context context, Locale newLocale) {

    Resources res = context.getResources();
    Configuration configuration = res.getConfiguration();

    if (android.os.Build.VERSION.SDK_INT >= 24) {
        configuration.setLocale(newLocale);

        LocaleList localeList = new LocaleList(newLocale);
        LocaleList.setDefault(localeList);
        configuration.setLocales(localeList);

        context = context.createConfigurationContext(configuration);


    } else if (android.os.Build.VERSION.SDK_INT >= 17) {
        configuration.setLocale(newLocale);
        context = context.createConfigurationContext(configuration);

    } else {
        configuration.locale = newLocale;
        res.updateConfiguration(configuration, res.getDisplayMetrics());
    }

    return new ContextWrapper(context);
}

}

调试我可以看到调用了onChange方法,重新创建了preferences活动,调用了上下文包装器,在包装器中正确创建了新的语言环境值,但是当活动启动时,我一直看到相同的默认字符串. /p>

有什么主意吗?

解决方案

Language为您设置的Locale对象的@parameter应该是

An ISO 639 alpha-2 or alpha-3 language code, or a language subtag
     * up to 8 characters in length.

根据文档. 因此,如果您使用其他内容,则看不到更新的语言环境.

I have an android app to which I want to add a simple preferences screen with a single option to switch between to languages (english and portuguese). I have already the proper string resources files in place.

If I change the main language of the OS in the system preferences, and reload the app, it will use that language, however I would like to be able to do it via the preferences screen.

I saw in other questions here that in this was a lot easier to do in previous Android versions, but that code is now deprecated so I followed the approach of overriding the attachBaseContext method in every activity in order to recreate the context via a wrapper in which I load the locale currently selected in the preferences, as seen in this post:

Android N change language programatically

public class TCPreferenceActivity extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener {


@Override
public void onBuildHeaders(List<Header> target) {
    loadHeadersFromResource(R.xml.headers_preference, target);
}

@Override
protected boolean isValidFragment(String fragmentName) {
    return TCPreferenceFragment.class.getName().equals(fragmentName);
}


@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
    if (key.equals("lang")) {
        recreate();
    }
}



@Override
protected void attachBaseContext(Context newBase) {

    SharedPreferences pref =  PreferenceManager.getDefaultSharedPreferences(newBase);

    String lang = pref.getString("lang", null);

    Locale locale = new Locale(lang);

    Context context = TCContextWrapper.wrap(newBase, locale);
    super.attachBaseContext(context);
}

}

So to my understanding, when changing the preference, the method onSharedPreferenceChanged is called. I recreate the activity there so that it can be relaunched with the new context.

This is my context wrapper:

public class TCContextWrapper extends ContextWrapper {

public TCContextWrapper(Context base) {
    super(base);
}

public static ContextWrapper wrap(Context context, Locale newLocale) {

    Resources res = context.getResources();
    Configuration configuration = res.getConfiguration();

    if (android.os.Build.VERSION.SDK_INT >= 24) {
        configuration.setLocale(newLocale);

        LocaleList localeList = new LocaleList(newLocale);
        LocaleList.setDefault(localeList);
        configuration.setLocales(localeList);

        context = context.createConfigurationContext(configuration);


    } else if (android.os.Build.VERSION.SDK_INT >= 17) {
        configuration.setLocale(newLocale);
        context = context.createConfigurationContext(configuration);

    } else {
        configuration.locale = newLocale;
        res.updateConfiguration(configuration, res.getDisplayMetrics());
    }

    return new ContextWrapper(context);
}

}

Debugging I can see that the onChange method is called, the preferences activity is recreated, the context wrapper is called, the new locale value is correctly created in the wrapper but as the activity launches I keep seeing the same default strings.

Any idea?

解决方案

Language @parameter that you are setting for Locale object should be

An ISO 639 alpha-2 or alpha-3 language code, or a language subtag
     * up to 8 characters in length.

According to the documentation. Therefore if you're using something else, you'll not see the updating locales.

这篇关于Android N-在运行时更改语言环境的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆