系统控件与动态字体的深度绑定
别名: 动态字体 · 内容尺寸类别 · 文本样式 · text styles
概念解释
苹果把字号做成用户级的内容尺寸类别(content size category),再把界面文字做成具名的文本样式(text styles:正文、标题、脚注、说明文字)。系统控件——标签、按钮、单元格、导航标题——默认订阅这套样式。用户在系统设置里放大文字,订阅了样式的控件会一起变大,布局按固有内容尺寸重新排。这种绑定叫 Dynamic Type binding:控件不是「碰巧用了某种字号」,而是接到了同一条会随用户偏好直播的通道上。
它回答的是「系统控件为什么能跟着辅助文字设置长高」,不是「该不该用系统控件来显得更像原生」。硬编码 17 点的自定义绘制、把文字画进位图、或用固定高度的单元格,都等于从这条通道上拔掉。
机制
绑定能起作用,是因为尺寸不是写死在控件里的像素,而是「样式角色 × 当前类别」查出来的。同一段「正文」在默认类别和超大类别下是不同的点值,行高、字距也会跟着样式表走。系统控件按固有内容尺寸报告自己需要的高度,Auto Layout 或栈式布局再把邻居推开——文字变大时,变的是控件自己报上来的需求,不是设计师预先画好的一档高度。
自定义字体只有在显式选择按类别缩放、并在类别变化时重新请求布局时,才重新接到通道上。一旦高度被写成常数、一旦文字被光栅化进图标、一旦用截断来「保持一行卡片高度不变」,通道就被掐断:设置里的滑块还在动,这块界面已经听不见。导航栏、标签栏、列表头这类系统容器内部的标题,同样走文本样式;把它们换成固定字号的自定义视图,等于在系统壳里开了一块不响应的飞地。
边界
插画、品牌标志、刻意保持固定视觉节奏的营销封面,本来就不该订阅正文样式,否则标志会跟着辅助文字被拉变形。游戏 HUD、相机取景叠加层如果必须把控件钉在取景构图上,放大文字会破坏瞄准;这类表面需要独立的可读性策略,而不是假装自己是列表。Watch 和部分空间界面的类别档位与手机不同,同一套样式名映射出的绝对尺寸不能跨设备抄。只验证默认类别通过、从未打开最大辅助文字的界面,绑定是否真正接通是看不见的——失败发生在尾部档位,不发生在设计稿常用的那一档。
怎么落地
- 界面文字使用系统文本样式,而不是写死点值;自定义字体也要按内容尺寸类别缩放,并在类别变化时让约束失效重算。
- 允许标签、按钮、单元格按固有内容尺寸长高、换行;把「必须单行」的位置收成少数例外,并单独用最大类别检查截断是否吃掉含义。
- 不要把说明文字画进位图或做成固定高度的装饰条;导航栏和列表标题尽量留在系统容器里,避免换成不订阅样式的自定义视图。
- 验证:在系统设置里从默认档拉到最大辅助文字,走完主要列表、表单、导航标题和按钮。任何裁切、重叠、单行被吃掉关键动词、或只有正文变大而按钮还停在原高度的地方,都说明那块控件没有接到通道上。再把类别打回默认,确认版面能缩回去,而不是留下放大后的空洞。