在以前的 《Flutter 上默认的文本和字体知识点》 和 《带你深入理解 Flutter 中的字体“冷”知识》 中,已经介绍了很多 Flutter 上关于字体有趣的知识点,而本篇讲继续介绍 Flutter 上关于 Text 的一个属性:FontFeature事实上相较于 Flutter ,本篇内容可能和前端或者设计关系更密切

相信本篇绝对是你能看到关于 Flutter FontFeature 相关的少数资料之一。

什么是 FontFeature简单来说就是影响字体形状的一个属性 ,在前端的对应领域里应该是 font-feature-settings,它有别于 FontFamily ,是用于指定字体内字的形状的一个参数。

如下图所示是 frac 分数和 tnum 表格数字的对比渲染效果,这种效果可以在不增加字体库时实现特殊的渲染,另外 Feature 也有特征的意思,所以也可以理解为字体特征。

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

所以 Roboto 之类的字体库是一个很大的字体集,不同的 font-weight 其实对应着不同的 ttf ,例如默认情况下的 Roboto 是不支持 font-weight 为 600 的配置

所以如下图所示,如果我们设置了 w400 - w700weight ,可以很明显看到中间的 500 和 600 其实是一样的粗细,所以在设置 weight 或者设计 UI 时,就需要考虑不同平台上的 weight 是否支持想要的效果

回归到 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 来解决这个问题。

因为出现模糊的情况一般都是因为使用了 canvas 标签绘制文本,而如果 Text 控件具有 fontFeatures 时,就会被设置为 <p> + <span> 进行渲染,从而避免问题

最后,如果对 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 截图:

你也可以通过如下原生代码,获取到对应现在 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

例如:.SF Text 适用于更小的字体;.SF Display 则适用于偏大的字体,我记得分水岭好像是 20pt 左右,不过 SF(San Francisco) 属于动态字体,系统会动态匹配

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

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

为了强调和 iOS 上的样式尽量一直,当开发者配置 isDefaultAction == true 时,会强行指定 '.SF UI Text' 并指定为 FontWeight.w600

当然,前面我们说了那么多,主要是针对英文的情况下,而在中文下还是有差异的,之前的文章也介绍过:

  • 默认在 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 修复了这个问题 ,而在以前的文章我也讲过,当时我遇到了 “Flutter 在 iOS 系统上,系统语言是韩文时,在和中文一起出现会导致字体显示异常" 的问题

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

所以可以看到,字体相关是一个平时很少会深入接触的东西,但是一旦涉及多语言和绘制,就很容易碰到问题的领域

Flutter 上字体的另类玩法:FontFeature相关推荐

  1. 软件也兼职 Word2003的另类玩法(转)

    软件也兼职 Word2003的另类玩法(转)[@more@] 大家都知道Word是文字处理软件中佼佼者,不过你知道吗?它还可以播放网络电影.Flash,还具有英汉双向翻译,给词语加注解等有趣功能,本文 ...

  2. 固态和机械硬盘组raid_另类玩法 固态盘和机械盘竟能组RAID

    另类玩法 固态盘和机械盘竟能组RAID RAID有很多种,其中RAID 0最为人所熟知,因为它可以成倍地提升存储设备性能.虽然现在组建RAID的过程已经不那么麻烦甚至非常简单,但是很多人依然认为RAI ...

  3. BIOS INT 10-13功能调用的“另类”玩法

    http://www.cnblogs.com/ljf9201314/archive/2008/07/21/1247653.html BIOS INT 10-13功能调用的"另类"玩 ...

  4. 59深度解密五十九:利用“抖音”进行吸粉的简单、另类玩法

    网络营销推广技术.技巧深度解密(五十九)指南: 1.本文档适合零基础和互联网营销推广工作者,主要讲解抖音吸粉的问题. 2.原创版权文档,任何抄袭或者全部.部分模仿都是侵权行为. 3.敬畏法律,尊重原创 ...

  5. 表情包项目的另类玩法,月赚好几W,情感萌宠精准拿捏用户

    文章目录 调研 分析 操作 图片 文案 bgm 链接 调研   这几天我有看到一位博主,他搞了个表情包项目,一个月赚了五六万.我们看下他的视频点赞量,真的不差.   而且我看了下,他玩这个表情包项目的 ...

  6. 【XSS技巧拓展】————14、XSS攻击另类玩法

    今天就来讲一下大家都熟悉的 xss漏洞的攻击利用.相信大家对xss已经很熟悉了,但是很多安全人员的意识里 xss漏洞危害只有弹窗或者窃取cookie.但是xss还有更多的花式玩法,今天将介绍几种. 1 ...

  7. 用导电颜料画乐器来“纸上弹琴”,Arduino新玩法

    我们之前见过几个创客自制的蔬菜钢琴(如上图),Instructable上也有很多创客在乐器上面玩花样.现在,意大利的一家创业公司MusicInk又研制出了一个更嗨的玩法:用导电材料在纸上画出真正可以发 ...

  8. 咪咕圈圈首创线上应援空间新玩法 为动感地带明星合伙人张艺兴花式庆生太圈粉

    10月7日,时值中国移动动感地带5G合伙人&AI宣推官张艺兴生日之际,张艺兴版10086定制客服语音包正式上线.这是自中国移动10086客户服务热线推出以来,首次推出明星客服语音定制合作. 同 ...

  9. 另类玩法,使用 REST API 操作 RabbitMQ

    文章目录 1. REST API 2. 开启 Web 管理页面 3. 实践 3.1 查看队列统计数据 3.2 创建队列 3.3 查看当前连接信息 3.4 查看当前用户信息 3.5 创建一个用户 3.6 ...

最新文章

  1. Python 中的locals()
  2. Ibatisnet示例:npetshop学习一
  3. The Wide and Deep Learning Model(译文+Tensorlfow源码解析) 原创 2017年11月03日 22:14:47 标签: 深度学习 / 谷歌 / tensorf
  4. iOS自定义转场动画实战讲解
  5. 【ruoyi若依】layer 重置大小/resize
  6. spring mvc后端校验validator
  7. android studio 手动安装gradle,Android Studio 如何安装Gradle?
  8. 上机不会做?在讲台上做做试试!
  9. 申请Let's Encrypt永久免费SSL证书
  10. ASP.NET MVC 中@Html.Partial,@Html.Action,@Html.RenderPartial,@Html.RenderAction
  11. SqlBulkCopy做大数据插入
  12. 汽车之家字体反爬破解实践
  13. 论文笔记(2):Cartoon Avatar Generation with Configurable Attributes based on GAN
  14. 屏幕刷新频率怎么更改?
  15. iCoud-MaciCoud上传文件时卡住-卡死-iCoud文件无法上传解决办法
  16. 华为p10自带计算机,华为P10评测:EMUI 5.1越用越快、总结
  17. android 导航安全密码,您导航的v5.3.8 Android版本
  18. 从“棱镜门”事件看“洋”产品
  19. HTMLParser 使用
  20. Python Z3约束求解器解决数独问题

热门文章

  1. 医院在线预约挂号管理系统(Java+SSH+MySQL)
  2. 一元多项式的除法C++实现
  3. 【视频】海康威视摄像头RTSP协议格式
  4. ArcMap出图小技巧:主图设计、图例、比例尺、指北针、标题
  5. 服务器通过笔记本电脑联网
  6. 华为OJ平台题目:(练习用)挑7
  7. 信号与系统2-连续离散系统时域分析
  8. Postgresql总结几种HA的部署方式
  9. 移动端Click300毫秒点击延迟 解决办法
  10. speedoffice中Word如何拆分单元格