Google published the official font resources handling since support library v26 released: https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html
However, looks like I cannot add country qualifier for the font resources folder.
I have an app which has 3 languages: English, Traditional Chinese and Simplified Chinese.
And I tried to name my font folder under res
this way:font
font-zh
font-zh_CN
(I have also tried font-zh-CN
)
(Note that zh
is the language, while CN
is the country. With some more context for your information - In China we all use "Chinese", but there are Simplified Chinese and Traditional Chinese; Moreover, Hong Kong and Taiwan both use Traditional Chinese but the way we use them are a bit different. Most importantly, typefaces have separate files for Traditional Chinese and Simplified Chinese, due to the fact that they are quite different in their shapes.)
But I cannot build the project. Android Studio keeps telling me that font-zh_CN
(or font-zh-CN
) is an invalid resource directory name.
This does not happen for my values-zh_CN
folder (nor values-zh-CN
).
Question:
How do you use different fonts for the same language but different country, using the new official method since API 26?
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.
来源:https://stackoverflow.com/questions/47066720/how-to-add-localewith-country-to-font-resources-support-library-v26