在以前的 《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
- w700
的 weight
,中间可以清楚地看到 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
默认情况下基本不支持浏览器,fwid
、nlck
不支持 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.cc 和 paragraph_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 TC
和 PingFang HK
的繁体集,而关于这个问题在 Flutter 上之前还出现过比较有意思的 bug :
用户在输入拼音时,iOS 会在中文拼音之间添加额外的
unicode \u2006
字符,比如输入"nihao"
,iOS 系统会在 skia 中添加文字“ni\u2006hao ”
,从而导致字体无效的情况。
当然后续的 #16709 修复了这个问题 ,而在以前的文章我也讲过,当时我遇到了 :
解决方法也很简单,就是给 fontFamilyFallback
配置上 ["PingFang SC" , "Heiti SC"]
就可以了,这是因为韩文在苹果手机上使用的应该是 Apple SD Gothic Neo
这样的超集字体库,【广】这个字符在这个字体集上是不存在的,所以就变成了中文的【广】;
。