问题
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?
回答1:
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
回答2:
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