资讯详情

Flutter 上字体的另类玩法:FontFeature

在以前的 《Flutter 默认文本和字体知识点 和 带你深入理解 Flutter 字体冷知识 介绍了很多 Flutter 关于字体有趣的知识点,本文继续介绍 Flutter 上关于 Text 属性:FontFeature

什么是 FontFeature ,应该是前端的对应领域 font-feature-settings,它有别于 FontFamily ,是用于指定字体内字的形状的一个参数。

如下图所示 frac 分数和 tnum 对比渲染字体库的情况下,表格数字的对比渲染效果可以实现特殊渲染外, Feature 也有特征的意思,所以也可以理解为字体特征。

我们知道 Flutter 默认在 Android 上使用的是 Roboto 字体,而在 iOS 上使用的是 SF 但实际上,字体 Roboto 字体也分为很多类型,比如你查手机 system/fonts 你会发现很多目录都有 Roboto 字体库存。

所以 Roboto 这样的字体库是一个大的字体集,不同 font-weight 其实对应不同 ttf ,比如默认情况下

如下图所示,如果我们设置它 w400 - w700weight ,中间可以清楚地看到 500 和 600 其实厚度是一样的,所以在

回归到 FontFeature 上,那 Roboto 默认支持多少种? features 呢? 答案是 26 其编码如下图所示,运行后效果如下图所示,从日常使用来看, 26 种 Feature 基本满足大部分开发需求。

“c2sc”、 “ccmp”、 “dlig”、 “dnom”、 “frac”、 “liga”、 “lnum”、 “locl”、 “numr”、 “onum”、 “pnum”、 “salt”、 “smcp”、 “ss01”、 “ss02”、 “ss03”、 “ss04”、 “ss05”、 “ss06”、 “ss07”、 “tnum”、 “unic”、 “cpsp”、 “kern”、 “mark”、 “mkmk”

而 iOS 上的 SF pro 默认支持 39 种 Features , 它们的编码如下图所示,运行后效果如下图所示 SF pro 支持的 Features 更多。

“c2sc”、 “calt”、 “case”、 “ccmp”、 “cv01”、 “cv02”、 “cv03”、 “cv04”、 “cv05”、 “cv06”、 “cv07”、 “cv08”、 “cv09”、 “cv10”、 “dnom”、 “frac”、 “liga”、 “locl”、 “numr”、 “pnum”、 “smcp”、 “ss01”、 “ss02”、 “ss03”、 “ss05”、 “ss06”、 “ss07”、 “ss08”、 “ss09”、 “ss12”、 “ss13”、 “ss14”、 “ss15”、 “ss16”、 “ss17”、 “subs”、 “sups”、 “tnum”、 “kern”

因此,并非所有字体都支持它 Features 都一样,比如 iOS 上支持 sups 上标显示和 subs 但是 Android 上的 Roboto 甚至很多第三方字体也不支持 Features 。

同样在 Web 也有各种各样的限制,比如 swsh默认情况下基本不支持浏览器,fwidnlck 不支持 Safari 浏览器等。

有趣的是,在 Flutter Web 渲染文本时有一个模糊的问题#58159,目前还没有官方修复,但是你可以给它 Text 设置任意 FontFeatures 解决这个问题。

最后,如果是对的 FontFeature 感兴趣的朋友可以通过信息深入了解。如果您对字体有任何疑问,请留言讨论。

  • 假如你想了解更多 features 可通过类型 https://en.wikipedia.org/wiki/List_of_typographic_features 了解更多;

  • 如果你支持你使用的字体 features 感兴趣,可以通过 https://wakamaifondue.com 了解更多;

补充内容

事实上在 dart 对应可以在里面看到 FontWeight 通常被称为字体集中的字体:

名称
Thin w100
Extra w200
Light w300
Normal/regular/plain w400(默认)
Medium w500
Semi-bold w600
Bold w700
Extra-bold- w800
Black 900

因此,如果您对默认字体有疑问,可以在您的手机字体中找到是否有相应的字体,,甚至还有 600 斜体: https://fonts.google.com/specimen/Roboto Mono 。

这里可以用 Android Studio 的 Device File Explorer 查看/system/etc/fonts.xml 现在手机的字体编码,右键文件 save as 在电脑上,下图是华为上的 fonts.xml 截图:

您还可以通过以下原始代码获得相应的现状 Android 字体由系统支持 Typeface ,但是这个 Typeface 不是真正的字体名,而是对应的 fonts.xml

protected Map<String, Typeface> getSSystemFontMap() { 
        
    Map<String, Typeface> sSystemFontMap = null;
    try { 
        
        //Typeface typeface = Typeface.class.newInstance();
        Typeface typeface = Typeface.create(Typeface.DEFAULT, Typeface.NORMAL);
        Field f = Typeface.class.getDeclaredField("sSystemFontMap");
        f.setAccessible(true);
        sSystemFontMap = (Map<String, Typeface>) f.get(typeface);
        for (Map.Entry<String, Typeface> entry : sSystemFontMap.entrySet()) { 
        
            Log.e("FontMap", entry.getKey() + " ---> " + entry.getValue() + "\n");
        }
    } catch (Exception e) { 
        
        e.printStackTrace();
    }
    return sSystemFontMap;
}

private static List<String> getKeyWithValue(Map map, Typeface value) { 
        
    Set set = map.entrySet();
    List<String> arr = new ArrayList<>();
    for (Object obj : set) { 
        
        Map.Entry entry = (Map.Entry) obj;
        if (entry.getValue().equals(value)) { 
        
            String str = (String) entry.getKey();
            arr.add(str);
        }
    }
    return arr;
}

例如前面我们说过 Roboto 没有 w600 , 但是通过输出比对,华为上有 source-sans-pro 是支持 w600

另外注意这是 Flutter 而不是原生,具体实现调用是在 Engine 的 paragraph_skia.ccparagraph_builder_skia.cc 下对应的 setFontFamilies 相关逻辑,当然默认字体库指定在 typography.dart 下就看到,例如 'Roboto''.SF UI Display''.SF UI Text''.AppleSystemUIFont''Segoe UI'

名称
Android,Fuchsia,Linux Roboto
iOS .SF UI Display,.SF UI Text
MacOS .AppleSystemUIFont
Windows Segoe UI

例如:

另外如果你在 Mac 的 Web 上使用 Flutter Web,可以看到指定的是 .AppleSystemUIFont ,而对于 .AppleSystemUIFont 它其实不算是一种字体,而是苹果上字体的一种集合别称:

还有,如果你去看 Flutter 默认自带的 cupertino/context_menu_action.dart ,就可以看到一个有趣的情况:

,之前的文章也介绍过:

  • 默认在 iOS 上:

    • 中文字体:PingFang SC
    • 英文字体:.SF UI Text.SF UI Display
  • 默认在 Android 上:

    • 中文字体:Source Han Sans / Noto
    • 英文字体:Roboto

例如,在苹果上的简体中文其实会是 PingFang SC 字体,对应还有PingFang TCPingFang HK 的繁体集,而关于这个问题在 Flutter 上之前还出现过比较有意思的 bug :

用户在输入拼音时,iOS 会在中文拼音之间添加额外的 unicode \u2006 字符,比如输入 "nihao" ,iOS 系统会在 skia 中添加文字 “ni\u2006hao ”,从而导致字体无效的情况。

当然后续的 #16709 修复了这个问题 ,而在以前的文章我也讲过,当时我遇到了

解决方法也很简单,就是给 fontFamilyFallback 配置上 ["PingFang SC" , "Heiti SC"] 就可以了,这是因为韩文在苹果手机上使用的应该是 Apple SD Gothic Neo 这样的超集字体库,【广】这个字符在这个字体集上是不存在的,所以就变成了中文的【广】;

标签: 高压电阻器5w500m

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台