How to add locale(with country) to font resources (Support Library v26)?

蓝咒 提交于 2019-12-05 03:13:09

The pattern for resource folder names is defined in Table 2 here: https://developer.android.com/guide/topics/resources/providing-resources.html#Alternative%20Resources

Specifically, try:

font-zh-rCN

As @SeanBarbeau pointed out, the correct pattern should be {language}-r{country}.

I definitely have tried this 4 months ago before I asked this question, but at that time, I believe there are other factors which make it fail.

And therefore I would like to add some more info here, in the hope of helping more people who are in trouble.

How do I change language (and corresponding font) in-app

Short answer is by wrapping the context in onAttachBaseContext of a BaseActivity.
Specifically I followed the guide here.

But in order for everything to work, you need to make sure 2 things:

(1) Your font resources are located in a correctly qualified folder;

Which is answered already in this thread, and;

(2) You wrapped the context in a correct locale

I believe this was what I missed 4 months ago.

At that time I didn't know much about the format of a locale.
I think I kept using something like new Locale("zh-CN") or new Locale("zh_CN") or new Locale("zh-rCN"). All of these are wrong!

The best way to specify a locale is to use the built-in constants, e.g. Locale.SIMPLIFIED_CHINESE.

If you look into this constant, it is calling the method createConstant("zh", "CN").
While createConstant() is a private method, I think it should be the same as new Locale("zh", "CN"); yet I still suggest using the constants.

So, at the end, your ContextWrapper should look like this:

public static Context wrap(Context context, Locale locale) {
    Configuration config = context.getResources().getConfiguration();
    if (locale == null) locale = Locale.ENGLISH; //Your default locale
    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) {
        return context.createConfigurationContext(config);
    } else {
        context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics());
        return context;
    }
}

The point here is to directly pass a Locale object to the wrapper, which is different from most examples out there which used a String.
While the conversion of preference (probably just a String) to Locale object is up to your implementation.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!