如何将区域设置(带国家/地区)添加到字体资源(支持库 v26)?

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

Google发布了自支持库v26发布以来的官方字体资源处理: https://developer.android.com/guide/topics/ui/look-and-feel/fonts-in-xml.html

但是,我似乎无法为字体资源文件夹添加国家/地区限定符。

我有一个应用程序有 3 种语言:英语、繁体中文和简体中文。

并且我尝试这样命名 res 下的字体文件夹:
font
font-zh
font-zh_CN
(我也试过了font-zh-CN

(请注意 zh 是语言,而 CN 是国家/地区。为您提供更多信息 - 在中国我们都使用 "Chinese" , 但有简体中文和繁体中文之分;而且香港和台湾都使用繁体中文,但我们使用它们的方式有点不同。最重要的是,字体有繁体中文和简体中文的单独文件,因为它们的形状完全不同。)

但是我无法构建项目。 Android Studio 一直告诉我 font-zh_CN(或 font-zh-CN)是无效的资源目录名称。

我的 values-zh_CN 文件夹(也 values-zh-CN)不会发生这种情况。

问题:

同种语言不同国家如何使用不同的字体,使用API26以来的官方新方法?

资源文件夹名称的模式在 Table 2 中定义: https://developer.android.com/guide/topics/resources/providing-resources.html#Alternative%20Resources

具体来说,试试:

font-zh-rCN

正如@SeanBarbeau 指出的那样,正确的模式应该是 {language}-r{country}.

在我问这个问题之前,我确实在 4 个月前尝试过这个,但当时,我相信还有其他因素导致它失败。

所以我想在这里补充一些信息,希望能帮助到更多有困难的人。

如何更改语言(和相应的字体)in-app

简短的回答是将上下文包装在 BaseActivityonAttachBaseContext 中。
具体来说,我遵循了指南 here.

但是为了让一切正常运行,您需要确保两件事:

(1) 您的字体资源位于正确限定的文件夹中;

已在此线程中回答,并且;

(2) 您将上下文包装在正确的语言环境中

我相信这是我 4 个月前错过的。

那时我对语言环境的格式了解不多。
我想我一直在使用 new Locale("zh-CN")new Locale("zh_CN")new Locale("zh-rCN") 之类的东西。这些都是错误的!

指定语言环境的最佳方法是使用 built-in 常量,例如Locale.SIMPLIFIED_CHINESE.

如果您查看此常量,它正在调用方法 createConstant("zh", "CN")
虽然 createConstant() 是一个私有方法,但我认为它应该与 new Locale("zh", "CN") 相同;但我仍然建议使用常量。

所以,最后,您的 ContextWrapper 应该如下所示:

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;
    }
}

这里的重点是 直接将 Locale 对象传递给包装器这与大多数使用 String.
虽然偏好(可能只是一个字符串)到 Locale 对象的转换取决于您的实现。