大多数浏览器和
Developer App 均支持流媒体播放。
-
用户界面字体排印详情
学习如何为你的 app 制作出排版精美的用户界面,提升可读性、易用性,以及在各 Apple 平台的一致性。了解 San Francisco 字体系列的最新发展,包括如何将多种字体调整为适合阅读的大小与粗细等。我们还会为你介绍一些关于如何最大程度利用系统字体、支持多种自定义字体的内容。 若要复习 San Francisco 字体系列及其基础原则的有关内容,请查看 WWDC15 的 “全新系统字体介绍”一节。
资源
相关视频
WWDC22
WWDC20
WWDC19
-
下载
(你好 WWDC 2020) 你好 欢迎来到 WWDC
(用户界面字体排印详情) 你好 我叫 Loïc Sander 我是 Apple 设计团队的一名字体设计师 在这次讲座中 我将和我的同事 Jiang 一起 向大家介绍优秀的用户界面 字体排印的细节 以及实现 app 排版的工具 总的来说 我们即将介绍的所有主题 实际上都是关于在我们的平台上 理解文本的动态行为 首先 我讲一下字型 和它们与用户界面设计相关的方面 然后 Jiang 将向你展示 设计排版样式和布局时 有用的 API 和最佳做法 对于大多数人来说 设计字体就像选择一种字型 和磅值一样简单 其实也应该如此
但我们的第一个话题 我想告诉你 改变文本的大小其实有很多微妙的影响 了解视觉字号是更好理解易读性的关键 这是你应该一直关注的重点
在视觉字号之后 我再讲一下可变字型 这种格式 可以让我们改进平台上文本的行为 也可以改善 app 的字体排印
然后我将介绍 直接影响用户界面设计感的话题: 字间距和行距 它们是文本布局的重要组成部分 所以绝对值得我们花时间去增加了解
最后但同样重要的是 Jiang 将深入探讨文本风格和动态字体 这是我们的两个核心排版工具 可帮助实现很棒的用户界面设计感 这也将是一次回顾 因为其中一些 API 不是新出现的 但我们也有一些新的内容 所以 我们开始吧 (视觉字号) 为了描述什么是视觉字号 我想回到几年前 我们的主系统字型旧金山首次问世的时候 我们的团队付出了很多努力 以确保 SF 在任何磅值下看起来都很棒 我们通过引入两个你们可能很熟悉的变体 实现了这一点 我们为小于 20 磅的字号设计了 SF Text 为大于 20 磅的设计了 SF Display 这些变体就是我们所说的视觉字号
它们能让我们 更好地控制影响易读性的细节 例如 SF Text 和 Display 字母之间的空间大小是为了适应 两种实际情况:一个设计适用于小字号 另一个适用于大字号
这两个设计之间的垂直比例也略有不同 因此在相同的磅值下 SF Text 可能会显得稍大一些 因此在使用小字号时更容易辨认
当我们推出这个设计时 感觉像是一场小革命 但我发现“革命”这个词很有趣 我们通常认为它的意思是前进或进步 但实际上它的意思是“回到起点” 因为 你看 自从字体排印被发明以来 视觉字号一直是一个问题 并且几个世纪以来 一直是一个涉及实体物体的印刷过程 几乎没有改变 的确 数字技术 在处理文本方面给了我们更多的灵活性 但在某种程度上 它使字体排印比以前更加粗糙 为了说明我的观点 我想给大家展示一下 自然环境下的视觉字号 作为一个字体和历史爱好者 我家里正好有这本 18 世纪的旧书 这就是我们所称作的字体标本 它包含了各种大小的字体排印示例 我想向你展示其中的两个示例 在这些页面中 有着不同字号的同一设计 也就是说 两种不同的字型 有点像 SF Text 和 Display 在今天的印刷单位中大约是 8 和 42 磅
现在我想让你们想象一下 对于你们在这里看到的每一个字母 都曾有一个完全相同大小的金属印章 是手工制作的
这些所谓的印章是通过一个流程来设计的 需要在钢制冲孔机上切割字形 在成型过程中 这些钢制的冲孔机被用于开始环节 最终制造出一套铅字 这正是金属印章的名字
看看这些字形的细节 你就会知道这个手工过程 受到了物理尺度的多大影响 8 磅字母看着很粗糙 因为它的尺寸较小 这说明了视觉字号 会受制于分辨率
对于切割铅字的人来说 这意味着设计要面对 用金属和墨水在纸纤维上印刷的挑战 而对于我们来说 这意味着要处理 矢量图形在像素网格上栅格化的挑战 但不管你设计的是哪种输出 视觉字号的改变 都是为了平衡易读性和细节 我这么说好像它们是独立的 但可读性是由细节决定的 与 SF Text 和 Display 一样 这里的关键细节是字母之间的空间
当字体变小时 字母之间往往需要更多的空间 这样眼睛可以更容易地将它们区分开
当然 字母本身也有更多有意义的细节 比如字母较细的部分 随着字母的变小 有时需要变得更挺拔
然后 一些细节可能会让你感到意外 比如字母“i”上的点的位置 但这样做是有意的 要确保 在小字号时“i”不会和“l”混淆 因为间隙越小 就越容易被墨水 或像素填充
因此 由于我们在这里需要考虑相对大小 我们观察一下最初的 按预期比例呈现的两个词 这两个设计之间的差异 现在感觉不那么明显了 这就是视觉字号的目的 它们平衡了易读性和美学特质 使设计在各个比例上令人感觉舒适一致 对于几个世纪前制作字型的人来说 调整设计以适应其比例 是一个相当直接的过程 因为他们总是按照实际尺寸工作 但另一方面 数字字体设计也面临着一个不幸的挑战
因为你可以无限地缩放矢量图形 实际上 所有数字字型只包含每个字形的单个绘图 所以字体设计师 必须选择一个理想的尺寸来设计 这就意味着你使用的大多数字型 都是在一定字号范围内 得以最好的发挥
当然 字体设计师总是可以决定 创建适合多种字号的多种字型 但这不是我们可以轻易做出的决定 因为这仍需要花大量的功夫 更重要的是 它成为了一个不太方便使用的字型家族 所以在最初设计 SF 的时候 我们非常仔细地考虑了这一点 最终我们决定使用视觉字号 但只设计两种
对我们来说 这个决定比较容易做出 因为 OS 可以自动在设计之间切换 然后 我们向所有人 讲授 SF Text 和 SF Display 的存在 让大家都有所了解 多年来 这已经成为了我们平台上最先进的技术 但我们一直希望能进一步改进这个行为 毕竟 如果一个字型 可以自动适应你选择的每个字号 不需要你在 Text 和 Display 之间切换 那不是很棒吗? 其实 这在几年前已经成为了可能 可变字型是在 2016 年引入的 是 OpenType 规范的演变 当时规范的更新 是为了应对网络字型的日益流行 以及这项技术实际上是在测试 现有字型格式的局限性 这种格式从根本上改变了 字形在字型中的存储方式 字形不再局限于单个静态绘图 它还可以描述每个点移动的方式 以产生相关但不同的字形 每一个运动或差量都与设计轴相连 让软件来控制它们的行为
在这些轴中 有一个是我们特别感兴趣的 因为它专门用于执行视觉字号 这使得我们可以 更新 SF Pro 并改进现有的视觉字号 但是这种新的动态行为确实在我们的 New York 衬线字体系统上显示了其潜力 该系统对字号的不同适应情况更加明显
多亏了可变的视觉字号 我们现在能够设计出完美适应比例的字体 绕了一圈 我们又要回顾物理字体的优点 (采用可变字型) 这也是为什么 今年 我们开始不再 将视觉字号作为单独的字型 现在合并的不仅是视觉字号 还有字重
这意味着从现在开始 我们的大多数系统字型 将下载为单一可变字型 尽管如此 今年我们仍然会发布 Text 和 Display 字型以方便过渡 (在设计工具中处理视觉字号) 在设计工具中 你应该能够找到用于可变字型的新控件 主要以滑动条的形式显示字型的公共轴
但请注意 它们是可选控件 你仍然可以通过 其预定义实例按常规方式使用该字型 事实上 当你使用我们的系统字型时 通常最好保留这些预定义的实例
如果你使用的可变字型支持视觉字号 你可以找到一个专用的滑动条 它将覆盖特定范围的磅值 原则上 设计 apps 应该注意保持滑块的值 与你使用的磅值同步
但情况并非总是如此 根据 app 的不同 改变磅值可能不会自动更新控件
如果你注意到 你使用的磅值与滑动条上的值不匹配 那么你需要自己设置滑动条
如果 你使用的磅值超出了滑动条的范围 也完全没问题 只需将滑动条设置为最接近的值即可 如果你在以前的 OS 上使用设计工具 可变字型可能无法正常工作 在这种情况下 重新使用我们 仍在提供的单独视觉字号更安全 比如 SF Text 和 Display (用代码处理视觉字号) 在代码中 这是完全自动化的行为 我们会处理 保持视觉字号和磅值同步的工作 当然 这适用于我们的系统字型 但也适用于 你可能使用的任何自定义可变字型 只要它有一个视觉字号轴 (以下的 API 自动处理视觉字号) 因此 在了解了特定尺寸的 字体排印的最新发展之后 我想谈谈用户界面 文本布局的两个基本原理 字间距和行距
字间距是我们如何有效实现 特定尺寸字体排印的重要组成部分 我已经详细地讨论了视觉字号 但是有一件事我没有提到 那就是当你把视觉字号和字间距相结合时 视觉字号会更加行之有效 但首先 字间距是什么意思?
好吧 让我们先看看一种字型的字形 它们已经包含了一定的空间
这个空间就是我们所说的“边位” 这是字形被绘制时所作出的设计 并将其定义为文本的默认间距
但是 正如我前面指出的 文本需要不同的字母间距 才能在任何磅值下都看起来美观
这种补偿初始空间的做法 就是我们所说的“字间距” 它在某种程度上 相当于 CSS 中的字母间距 但是字间距具体是指 在文本布局的字形之间 添加空间的操作
我刚提到的内容或许有人会觉得困惑 并想 “等等 我以为这是字偶距”
这种混淆很常见 但是字间距和字偶距是不同的事情
字距调整是一种只应用于 某一对字母间距的微小修正 字距调整也是由字体设计师创建的 大多数情况下 你根本不需要修改它
但说回字间距 让我告诉你如何 以及为什么在 SF 字型上使用它
即使你在设计字型时使用特定大小的间距 就像我们为 SF Text 和 Display 所做的那样 如果你想获得精美的结果 使用字间距仍然是正确的
如果没有字间距 在 SF Text 和 Display 的 字号为 20 磅时 从一种字型切换到另一种 原生间距的差异将成为一个问题
请注意 最后一条蓝线和第一条橙线的长度 几乎相同 尽管它们的磅值不同
这是因为它们默认的间距不同 而这种急剧的变化正是我们使用视觉字号 作为字间距的原因
这确实是系统字型行为的一个重要部分 也是我们发布字间距表 作为 Apple Design Resources 一部分的原因 因为如果你想准确地再现系统字型的行为 你需要知道对每个磅值应用多少字间距 今年 随着 SF Pro 成为可变字型 在 20 磅左右时不再有急剧的变化 设计现在在 17 和 28 磅之间 从 Text 过渡到 Display
由于行为中潜在的变化 我们不得不更新字间距表 所以请注意 当你在设计比较中使用新的 SF Pro 时 你需要应用 17 磅 28 磅之间的 一套新的字间距值 (紧凑字间距) 但当我们观察字间距曲线时 我想指出最后一个问题 一个字型实际上可以包含多个字间距表 我们可以使用它来添加字间距值 为紧凑的字符串提供帮助 假设 你遇到了字符串被截断的情况
你可能会使用字偶距 API 这个非常常见的解决方案 但正如我前面指出的 在这里使用字偶距并不理想
使用字间距 API 会更好 因为它在语义上是正确的 但更重要的是 它允许OS 禁用 可能与字间距冲突的排版特性 比如连字特性 (字距调整 API - 字间距 API) 因为如果你用一个字偶距 API 来调整一个包含连字的单词 那么这个连字会保留下来 并破坏这个单词的节奏 另一方面 使用字间距 API 我们会为你拆除连字 这使字间距更均匀
不过 要想让一个字串合适 最佳首选的解决方案是让它自动收紧 那就是我们使用紧凑字间距表的时候 使用这个 API 系统会尝试使字符串 在合理的易读性范围内得以匹配 因为字间距也不能太大 对于这类情况 最好采取截断的方法
使用此 API 的最后一个原因 是它应用特定大小的字间距 如果你自己应用字间距 则必须通过手动来实现 (文档字型的字间距) 好了 让我用一个小公告 来总结字间距的话题 (我们的系统用户界面字型 有内置的字间距表) 今年 我们将启用对第三方字型的字间距 (今年 我们的平台 将对任何字型启用字间距) (同时包含 TRAK 和 STAT 表) 这意味着 字型供应商可以开始在他们自己的字型中 添加字间距表 嵌入的字间距将应用于我们的平台 前提是字型也包含一个 STAT 表
如果你应用 CTFont 视觉字号属性 此类字型 也可以在旧的 OS 上使用其字间距数据
好了 我们已经讨论了字形之间的空间 现在我们来看看另一种字体间距:行距
我想在这里再普及一下词汇问题 以消除两个术语的歧义 我们先来说一下行高 (行高) 默认情况下 行高是字型的垂直高度限制 你还可以将其视为两条基线之间的距离 但是无论采用何种方法 距离都是相同的
当两条线之间的距离增加时 它们之间的距离被称为“行距线”
说点冷知识来帮助你记忆 这个名字来自金属字体的时代 当时在两行文字之间的间隔上 有一块铅条 (行高包含行距) 这里需要注意的重要一点是 当两行文字之间有行距时 行高也包含行距 所以这两个概念是相互依赖的 如果你改变了一个 就改变了另一个
大多数时候 你不需要关心 行距或行高 因为我们 已经在大多数用户界面组件中定义了它们 但是让我给你们看两个例子 在这两个例子中我们确实修改了行距
阿拉伯语是一种 文字不断起伏的书写系统 在一条给定的直线上 它们会侵占上下行的视觉空间 所以在这种情况下 增加一些行距通常是有益的
出于这个原因 我们在平台上 为了阿拉伯语等受益于 较高行高的语言环境 应用了更高的行距
另一方面 有时收紧行距是有帮助的 让元素更加垂直紧凑 例如 在 watchOS 上 我们在很多地方应用了窄行距 在屏幕上最大限度地显示更多的信息
此类修改是通过使用文字样式来完成的 Jiang 稍后会给大家介绍
这两个例子很好地展示了 我们如何努力设计 API 和排版特性 通过使用已有的系统 API 大家将从我们每年进行的 设计改进中获益 至于新版本 我们尽量让适配工作变得简洁 这样可以让你的 app 随着时间的推移变得更好 现在是我把话题交给 Jiang 的好时机 他将向你展示更多关于我们为你提供的 强大的字型和文本 API 多谢 Loïc 好 在深入了解字体排印的细节之后 让我们来谈谈文本样式和动态字体 这两个重要的系统工具 可以帮助你 在 app 中创建美观且一致的字体排印
文本样式是 Apple 构建优秀用户界面的核心 它们提供了一个框架 支持灵活和一致的字体排印 具有清晰的层次结构 和足够的风格范围 来满足大多数用户界面的需求 (文本样式) 文本样式是一组预定义的 系统字型字重、磅值和行距值的组合 它们被构建在 一个提供排版层次结构的系统中 使你更容易 在 app 中实现清晰易读的布局
首先 虽然定义的文本样式 提供了广泛的字型大小 来表示信息层次结构 但有时 仅靠字体大小还不足以突出更细微的差异
比如这里 日历中年份和月份的标题 可以看到 它们使用了标准文本样式中的 字重较粗的字体 像这样的加重文本样式 允许你使用相同的 文本样式大小和不同的字重 这被我们的系统 app 广泛使用 当然 你也见过这个 邮件中的大标题导航栏 这是使用加重的大标题文本样式 现在我将展示 如何在你自己的 app 中使用它
假设我们有一个使用标题 1 字型的标签 我发现标题需要更显眼一点 所以为什么不使用粗体字重呢? 那么 加重的标题 1 就是这样
这里 我们不使用 UIFont preferredFont(withTextStyle:) API 我们使用 UIFontDescriptor API 来获得具有标题 1 文本风格的描述符 然后我们将一个粗体符号特征应用于它 使用粗体特征 你将得到加重标题 1 文本样式 它映射到 SF Pro 粗体
你可以将粗体符号特征应用到任何 NSFont、UIFont 或 SwiftUI 字型 来创建该字型的加重变量
虽然该符号特征的名称是“粗体” 但该变体的实际字重取决于文本样式 可以是中号、半粗体、粗体或是重体 如前所述 文本样式具有行高 我们发现它适用于 大多数情况 但是 有时你使用的空间比较有限 因此节省行之间的空间会增加信息密度 这个健身 app 就是一个例子 或者在呈现大量文本时 你可能想要给内容更多的喘息空间 来改善阅读体验 就像这里的地图一样 在这些情况下 你可以使用 窄和宽的文本样式的行距变量 (窄和宽行距的文本样式) 在 iOS 和 macOS 中 窄行距使线高降低 2 磅 (标准行距-窄行距-宽行距) 宽行距使线间距增加 2 磅 在 watchOS 中 调整幅度减少到了 1 磅
现在 在这个例子中 我们有一个像这样的很长的文本段落 它使用的是正文文本样式 现在它有 22 磅的线高 假设我们想实验一下 看看在更窄的线高下它会是什么样子 我想你现在已经掌握窍门了 一旦我们应用窄行距的符号特性 文本看起来是这样的 好了 现在它有 20 磅的线高 但对于这么长的一段文字来说 这似乎太紧凑了 那么 宽行距呢?那会是什么样子呢? 现在让我们尝试 宽行距特征得到 24 磅的线高 好了 现在看起来舒服多了 所以它实际上和我们刚才讲过的 加重变量非常相似 只是这一次 我们运用了窄行距 和宽行距的象征特征 在今年新推出的功能中 你也可以在 SwiftUI 中 对文字样式字型进行行距调整
在整个系统中 我们在 app 中 使用了 New York 和 SF Pro 圆体 就像这里的图书和提醒事项 app 一样 但值得注意的是 它们不仅仅作为独立的字体工作 它们也非常适合我们的文本样式 现在 假设我们想要创建一个标签 就像提醒事项一样 让我们结合 我们刚刚学过的加重文本样式 我们从“今天”这样的文本开始 并使用加重的大标题文本样式
目前它使用的是 SF Pro 粗体
我们来把圆角应用到文本上 fontDescriptorwithDesign API 你可以看到 现在的字型已经切换到 SF Pro 圆体
因此 我们引入了一个非常灵活的 API 允许你将这些设计 应用到任何系统用户界面字型 对于 AppKit 和 UIKit 来说 fontDescriptorwithDesign API 可以应用于任何用户界面字型
对于 SwiftUI 来说 API 有点不同 在开始构造字型时 应该传递设计 而不是使用修饰符转换现有字型
当选择一个带有设计的文本样式时 除了设计之外的一切都保持不变 包括字型大小、字重和行高 我知道你们中的许多人 使用网络页面或在 app 中嵌入网络视图 几年前 WebKit 引入了-apple-system 字型系列 这样你就可以 用它来使用 CSS 中的旧金山字型 这已被广泛采用 (通过 CSS 访问系统字型设计) 现在带前缀的-apple 版本 有一个标准名称:system-ui 今年早些时候 我们将为 Apple 平台 带来一套新的 CSS 字型家族名称 比如 ui-round、ui-serif 和 ui-monospace 我很高兴地宣布 今年文本风格 是 macOS 中完全支持的 API (macOS 文本特征 API) 我们将为所有 Cocoa app 引入一套新的 API 到 AppKit 这个 AppKit API 将支持所有的文本样式 就像在 iOS 上一样 字型大小被优化 以匹配 macOS 的控件大小 虽然没有动态字体支持 但你可以获得 我们刚刚介绍的文本样式的所有其他好处 去年 我们分享了这张 Catalyst-app 文本样式大小的图表 实际上是 iOS 尺寸的 77% 今年 Catalyst app 的界面 针对 Mac 进行了优化 你会得到一套像这样的文本样式的新尺寸
你可以看到它们排列得很整齐 所以你的 app 只需要最小的变化就可适配
如果你选择“缩放界面以匹配 iPad” 它将继续遵循 iOS 的 77%大小 但如果你想要新的行为 在 Xcode 中选择 “为 Mac 优化界面”选项就可得到
你可能已经知道 在 iOS 中 文本样式还有另一个维度:动态字体 你选择的字型将根据偏好 自动缩放
动态字体让人们可以控制文本样式的大小 (文本样式和动态字体) 它使文本对很多人来说更容易阅读 所以你真的应该考虑 在你的 app 中支持动态字体
通过同时使用系统字型 API 和文本样式 你可以在 iOS 上自动选择这种行为 但是在使用自定义字形时 你也可以支持动态字体 我将在本部分介绍如何做到这一点 (动态字体缩放行为) 好的 我们刚刚展示的图表 有很多需要注意的地方 我希望你注意的一件事是不同的文本样式 可能有不同的缩放行为 在这里 我们可以看到正文、标题和脚注文本样式 如何随动态字体缩放 当你使用自定义字型处理动态字体支持时 也应该注意这一点 正如我们所知 字体排印对于品牌识别是至关重要的 而你们中的许多人在创建 app 时 都使用了为自己的 app 和品牌 设计的自定义字型 但是你仍然希望支持动态字体 因为这对辅助功能至关重要
你希望你的 app 在文本大小偏好改变时做出相应的反应 就像 iOS 系统的 app 那样 要怎么做呢?
我们在过去的会谈中已经讨论过 这个问题 但仍然值得再次讨论 因为这是多年来常见的问题
自从 iOS 11 以来 我们引入了 一个新的 UIFontMetrics 类 它捕获了文本样式的动态字体功能 并允许你将其应用到任意字型上
为了使用它 让我们看一下这个例子 首先 像往常一样 使用标准 UIFont API 从定制字型开始 然后可以根据 正文文本样式创建 UIFontMetrics 有了这个正文指标对象 由 scaledFont API 生成的字型将进行缩放 就像当文本大小首选项发生变化时 正文文本进行缩放一样
值得注意的是 你还可以使用它 来缩放自定义布局的常量值 比如这里的两个标签之间的间距 自去年发布以来 我们收到了来自 SwiftUI 开发者的大量反馈 今年 在 SwiftUI 中 我们会 让你做和 UIKit 中一样的字型缩放 为了理解这一点 让我们先在 SwiftUI ContentView 中加入一段文本 到目前为止一切顺利 当文本大小偏好发生变化时 所有内容都会相应地缩放
现在我想使用 Avenir 字型 中等字重 34 磅的文本 我知道怎么做 正如你所看到的 它使用了我们想要的字型 然而 在 iOS 13 中 问题是 一旦你开始使用自定义字型 它就会停止支持动态字体
在 iOS14 中 它会自动缩放 但为了确保标题有正确的缩放行为 我将设置 relativeTo 参数 以便它会相对于标题文本样式缩放
可以看到 标题文本现在自动缩放了
让我们继续添加正文文本 与添加标题文本的方式类似 我们声明一段文本 并将其分配给 VStack 中的文本
我甚至不需要使用 relativeTo 参数 因为自定义字型 在 iOS 14 中默认会相对于 正文样式缩放
标题和正文现在都自动缩放了 但是看起来 我们可以利用好正文周围的内边距 因为文本太接近边框和标题了
让我们添加一些内边距 我们先从 20 磅的固定内边距开始
好多了 现在 如果内边距也能 根据文本大小的变化进行缩放 那不是很好吗?
我们可以利用新的 ScaledMetric 属性包装器 来定义值为“20”的内边距
但它也可以相对于正文文本样式缩放
让我们看看这是否奏效 可以看到 文本周围的内边距与文本大小成比例缩放 而不是固定大小
好 下面是我们刚刚展示内容的重述 font(.custom API 有一个新的可选参数 relativeTo 用于指定 你希望它相对于哪个文本样式进行缩放 如果你跳过这个 它会相对于正文缩放 这是 iOS 14 中的一个行为改变 你仍然可以 使用 fixedSize 参数创建一个固定尺寸 且完全不缩放的自定义字型
除此之外 你还可以缩放常量 就像 UIFontMetrics 对 ScaledMetric 属性包装器所做的那样 好吧 今天我们讲了很多基础知识 这里有一些我想提醒大家的基本原则
我们提供了各种风格的 精心设计的系统字型 如SF Pro、SF Pro Rounded、 SF Mono 和 New York 我们鼓励你试一试 (尝试使用系统字型如 SF PRO、 SF PRO round、SF MONO 和 NEW YORK) 对于好的字体排印 层次结构是很重要的 而文本样式是构建这种层次结构的好工具 (使用文本样式 有助于创建排版层次结构) 即使在使用自定义字型时 你也应该有足够的选项来支持动态字体 这对辅助功能很有帮助 (考虑使用自定义字型支持动态字体) 我们已经讨论了字体排印的许多重要细节 比如字间距和行距 你应该只在特殊情况下 覆盖默认的系统行为 并让系统为其余的行为 替你把事情做好 (只有在特殊情况下才覆盖系统行为) 如果你必须在你的 用户界面中使用自定义字间距 记住它应该是特定尺寸的 否则你为小尺寸提供的字间距 在大尺寸上可能不太美观 (自定义字间距应该是特定的大小) 我希望你现在已经 更好地理解了文本在我们平台上的行为 以及你所使用的文本和字型 API 以便在你的 app 中实现出色的字体排印 谢谢
-
-
12:19 - Setting custom tracking
// UIKit label.attributedText = NSAttributedString(string: "hamburgefonstiv", attributes: [kCTTrackingAttributeName as NSAttributedString.Key: -0.5]) // SwiftUI Text("hamburgefonstiv").tracking(-0.5)
-
12:45 - Allow tightening to use tight tracking from system fonts
// UIKit: UILabel label.allowsDefaultTighteningForTruncation = true // AppKit: NSTextField textField.allowsDefaultTighteningForTruncation = true // SwiftUI Text("hamburgefonstiv").allowsTightening(true)
-
17:45 - Getting emphasized text styles
// Getting emphasized text styles let label = UILabel() label.text = "Ready. Set. Code." if let descriptor = UIFontDescriptor .preferredFontDescriptor(withTextStyle: .title1) .withSymbolicTraits(.traitBold) { // 28 pt Bold on iOS label.font = .init(descriptor: descriptor, size: 0) }
-
18:05 - Getting emphasized text styles APIs
// Getting emphasized text styles // AppKit let descriptor = NSFontDescriptor .preferredFontDescriptor(forTextStyle: .body) .withSymbolicTraits(.bold) // 13 pt Semibold on macOS let emphasizedBodyFont = NSFont(descriptor: descriptor, size: 0) // UIKit/Catalyst if let descriptor = UIFontDescriptor .preferredFontDescriptor(withTextStyle: .body) .withSymbolicTraits(.traitBold) { // 17 pt Semibold on iOS let emphasizedBodyFont = UIFont(descriptor: descriptor, size: 0) } // SwiftUI let emphasizedFootnoteFont = Font.footnote.bold() // 13 pt Semibold on iOS
-
19:34 - Getting tight leading variant
// Getting tight leading variant import UIKit let label = UILabel() label.text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat." if let descriptor = UIFontDescriptor .preferredFontDescriptor(withTextStyle: .body) .withSymbolicTraits(.traitTightLeading) // 20 pt line height label.font = UIFont(descriptor: descriptor, size: 0) }
-
19:49 - Getting loose leading variant
// Getting tight leading variant import UIKit let label = UILabel() label.text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat." if let descriptor = UIFontDescriptor .preferredFontDescriptor(withTextStyle: .body) .withSymbolicTraits(.traitLooseLeading) // 24 pt line height label.font = UIFont(descriptor: descriptor, size: 0) }
-
20:03 - Getting tight/loose leading variant APIs
// Getting tight/loose leading variant // AppKit let descriptor = NSFontDescriptor.preferredFontDescriptor(forTextStyle: .headline) .withSymbolicTraits(.tightLeading) // Use .looseLeading for loose leading font let tightLeadingFont = NSFont(descriptor: descriptor, size: 0) // 14 pt line height // UIKit/Catalyst if let descriptor = UIFontDescriptor.preferredFontDescriptor(withTextStyle: .title1) .withSymbolicTraits(.traitTightLeading) { // Use .traitLooseLeading for loose leading let tightLeadingFont = UIFont(descriptor: descriptor, size: 0) // 36 pt line height } // SwiftUI // Use .loose for loose leading font let tightLeadingFootnoteFont = Font.footnote.leading(.tight) // 16 pt line height on iOS
-
20:56 - Access rounded system font design
// Access rounded system font design import UIKit let label = UILabel() label.text = "Today" if let descriptor = UIFontDescriptor .preferredFontDescriptor(withTextStyle: .largeTitle) .withSymbolicTraits(.traitBold)? .withDesign(.rounded) { // SF Pro Rounded Bold label.font = UIFont(descriptor: descriptor, size: 0) }
-
21:08 - Access system font designs
// Access system font designs // Use .serif for New York, .monospaced for SF Mono // AppKit let descriptor = NSFontDescriptor.preferredFontDescriptor(forTextStyle: .body) .withDesign(.rounded) let roundedBodyFont = NSFont(descriptor: descriptor, size: 0) // SF Pro Rounded // UIKit/Catalyst if let descriptor = UIFontDescriptor.preferredFontDescriptor(withTextStyle: .body) .withDesign(.rounded) { let roundedBodyFont = UIFont(descriptor: descriptor, size: 0) // SF Pro Rounded } // SwiftUI let roundedBodyFont = Font.system(.body, design: .rounded) // SF Pro Rounded
-
25:05 - Support Dynamic Type with custom font in UIKit
// Support Dynamic Type with custom font in UIKit if let customFont = UIFont(name: "Charter-Roman", size: 17) { let bodyMetrics = UIFontMetrics(forTextStyle: .body) // Charter-Roman scaled relative to body text style // in different content size categories. let customFontScaledLikeBody = bodyMetrics.scaledFont(for: customFont) label.font = customFontScaledLikeBody label.adjustsFontForContentSizeCategory = true // Scaling constant 10 relative to body text style. let scaledValue = bodyMetrics.scaledValue(for: 10) }
-
26:25 - Support Dynamic Type with custom fonts in SwiftUI example
struct ContentView: View { let prose = "Apple provides two type families you can use in your iOS apps. San Francisco (SF). San Francisco is a sans serif type family that includes SF Pro, SF Pro Rounded, SF Mono, SF Compact, and SF Compact Rounded." @ScaledMetric(relativeTo: .body) var padding: CGFloat = 20 var body: some View { VStack { Text("Typography") .font(.custom("Avenir-Medium", size: 34, relativeTo: .title)) Text(prose) .font(.custom("Charter-Roman", size: 17)) .padding(padding) } } }
-
28:29 - Support Dynamic Type with custom fonts in SwiftUI
// Support Dynamic Type with custom fonts in SwiftUI // Text with font Avenir-Roman, scaling relative to title text style. Text("Typography").font(.custom("Avenir-Roman", size: 34, relativeTo: .title)) // Text with font Helvetica, scaling relative to body text style. Text("Title").font(.custom("Helvetica", size: 17)) // Text with font Courier, always use fixed size, do not scale according to user setting. Text("Fixed").font(.custom("Courier", fixedSize: 17)) // Constant 10, scaled relative to title text style. @ScaledMetric(relativeTo: .title) private var spacing: CGFloat = 10.0
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。