在以前的 [《Flutter 上默认的文本和字体知识点》](https://juejin.cn/post/6844904164082843655) 和 [《带你深入理解 Flutter 中的字体“冷”知识》](https://juejin.cn/post/6844904174023344136) 中,已经介绍了很多 Flutter 上关于字体有趣的知识点,而本篇讲继续介绍 Flutter 上关于 `Text` 的一个属性:`FontFeature` , **事实上相较于 Flutter ,本篇内容可能和前端或者设计关系更密切**。 > **相信本篇绝对是你能看到关于 Flutter `FontFeature` 相关的少数资料之一。** 什么是 `FontFeature`? **简单来说就是影响字体形状的一个属性** ,在前端的对应领域里应该是 `font-feature-settings`,它有别于 `FontFamily` ,是用于指定字体内字的形状的一个参数。 > 如下图所示是 `frac` 分数和 `tnum` 表格数字的对比渲染效果,这种效果可以在不增加字体库时实现特殊的渲染,另外 `Feature` 也有特征的意思,所以也可以理解为字体特征。 ![](http://img.cdn.guoshuyu.cn/20220328_Flutter-FontFeature/image1) 我们知道 Flutter 默认在 Android 上使用的是 `Roboto` 字体,而在 iOS 上使用的是 `SF` 字体,但是其实 `Roboto` 字体也是分很多类型的,比如你去查阅手机的 `system/fonts` 目录,就会发现很多带有 `Roboto` 字样的字体库存在。 ![](http://img.cdn.guoshuyu.cn/20220328_Flutter-FontFeature/image2) 所以 `Roboto` 之类的字体库是一个很大的字体集,不同的 `font-weight` 其实对应着不同的 `ttf` ,例如默认情况下的 **`Roboto` 是不支持 `font-weight` 为 600 的配置**: ![](http://img.cdn.guoshuyu.cn/20220328_Flutter-FontFeature/image3) 所以如下图所示,如果我们设置了 `w400` - `w700` 的 `weight` ,可以很明显看到中间的 500 和 600 其实是一样的粗细,所以在**设置 `weight` 或者设计 UI 时,就需要考虑不同平台上的 `weight` 是否支持想要的效果**。 ![](http://img.cdn.guoshuyu.cn/20220328_Flutter-FontFeature/image4) 回归到 `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" ![](http://img.cdn.guoshuyu.cn/20220328_Flutter-FontFeature/image5) 而 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" ![](http://img.cdn.guoshuyu.cn/20220328_Flutter-FontFeature/image6) 所以可以看到,并不是所有字体支持的 Features 都是一样的,比如 iOS 上支持 `sups` 上标显示和 `subs` 下标显示,但是 Android 上的 Roboto 并不支持,甚至很多第三方字体其实并不支持 Features 。 > 同样在 Web 上也存在各种限制,比如 `swsh`(花体)默认下基本不支持浏览器,`fwid` 、 `nlck` 不支持 Safari 浏览器等。 有趣的是,在 Flutter Web 有一个渲染文本时会变模糊的问题[#58159](https://github.com/flutter/flutter/issues/58159),这个问题目前官方还没有修复,但是你可以通过给 `Text` 设置任意 `FontFeatures` 来解决这个问题。 > **因为出现模糊的情况一般都是因为使用了 `canvas` 标签绘制文本,而如果 `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 |
所以如果对于默认字体有疑问,可以在你的手机字体找找是否有对应的字体,**比如虽然我们说 roboto 没有 600 ,但是如果是 roboto mono 字体集是有 600 的 fontweight**,甚至还有 600 斜体: https://fonts.google.com/specimen/Roboto+Mono 。
这里可以用 Android Studio 的 `Device File Explorer` 查看`/system/etc/fonts.xml` 下当前手机的字体编码情况,右键该文件 `save as` 到电脑上,下图是华为上的 `fonts.xml` 截图:
![](http://img.cdn.guoshuyu.cn/20220328_Flutter-FontFeature/image7)
你也可以通过如下原生代码,获取到对应现在 Android 系统支持的字体 `Typeface` ,但是这个 `Typeface` 并不是真正的字体名,还是要对应在 `fonts.xml` 下查看。
```java
protected Map