chapter[11] · part 2 / 程序员的界面美学
读完 HIG 再读 Material Design,最有趣的是气质差异:Apple 给你一套礼仪,Google 给你一套物理学。HIG 说"应当谦逊、应当清晰",像一位品味极好的主人在立家规;Material 则从一个第一性隐喻出发,把所有规则当定理推导出来。对程序员来说,Material 是更"对胃口"的读物——它是公理化的。本章看两样东西:这个公理系统怎么运转,以及它和 iOS 的方言差异如何处理。
Material 的全部规则源自一个隐喻:界面由一种虚构的材料构成——量子纸(quantum paper)。它像真纸一样:有厚度(1dp)、有海拔、会投影、不可相互穿透;又比真纸多几条魔法:可以瞬间伸缩、分裂、合并、响应触摸泛起涟漪。一旦接受这个公理,大量设计决定就不再需要死记:
Material 3(Material You)做了一件把本书前文全部串起来的事:动态取色(dynamic color)。用户换一张壁纸,整个系统和所有适配的 App 随之换装。它的管线值得程序员细看,因为每一步都是你学过的章节:
on-primary 与 primary 永远隔开足够的 tone 距离)。这就是为什么任何壁纸进去,出来的界面对比度都达标:美学判断(选色)交给用户,工程纪律(可读性)锁死在系统里。每个 on-X 配 X 的命名模式,是 8.2 语义层最工整的工业实现。
M3 还顺手解决了 9.4 节的暗色模式海拔问题:投影在深底上失效,于是海拔改用色调表面(tonal surface)表达——海拔越高,表面叠加越多主色调的"色调提升"。光的语法从"影子"换成了"染色",但层级语义一字未变。
双平台开发者最常踩的坑不是大原则(两家高度一致),而是方言细节。一张对照表:
| 维度 | iOS(HIG) | Android(Material) |
|---|---|---|
| 返回模型 | 局部:左上角 ‹ + 屏幕左缘右滑 | 全局:系统级返回手势/按钮,App 必须响应 |
| 系统字体 | San Francisco(光学尺寸) | Roboto / Google Sans |
| 主导航 | 底部 Tab Bar(3–5 个) | 底部 Navigation Bar(M3 同样收敛到底部) |
| 首要动作 | 导航栏右上角文字按钮 | FAB——悬浮在内容上的实体按钮 |
| 触摸反馈 | 高亮/透明度变化 | 涟漪(ripple)从触点扩散 |
| 模态风格 | 底部卡片上滑,压暗退后 | 对话框居中,或 bottom sheet |
| 尺寸单位 | pt | dp(与 pt 概念等价)· 触达最小 48dp |
| 气质 | 克制、内容优先、隐形 | 表达、色彩大胆、组件在场 |
其中 FAB 值得单独一句:它是第七章"克制"原则的实体化——整屏唯一一个高海拔、高饱和的圆钮,等于把"本屏最重要的动作"用海拔和颜色同时声明出来。也因此 FAB 的滥用方式只有一种:一屏放两个。
该做两套 UI 还是一套?把选项按成本排开:
两个团队、两套设计语言,各自纯正。体验上限最高,成本两倍。大厂核心 App 的选择。
品牌层(色彩、字阶、插画、语气)两端统一;结构层(返回模型、导航位置、模态风格、反馈动效)入乡随俗——正是上表那几行。Flutter/React Native/Compose Multiplatform 时代的务实解。
两端长得一模一样、且都不像系统。等于自建平台:10.6 的打破成本公式 × 2。除非品牌强到用户为它学习(大型游戏、超级 App),否则慎选。
策略 B 翻译成架构语言:品牌是抽象接口,平台礼仪是两个实现。把 design token(第八章)按这条线切开——brand.*(色、字、圆角、插画风格)共享一份;platform.*(导航结构、返回行为、反馈动效)各自绑定系统组件。在 Flutter 里这对应同一套主题 token 喂给 Material 与 Cupertino 两套组件;切错这条线(比如把 iOS 的返回箭头硬编码进共享组件),就是把实现细节泄漏进了接口。
Android 生态比 iOS 更早被一个问题逼到墙角:屏幕尺寸不是几种,是连续的——手机、折叠屏(合起来是手机、展开是平板)、平板、ChromeOS、桌面。第九章 Web 那套"为规则设计而非为版面设计"的弹性思维,在原生端有了官方框架:窗口尺寸类(window size class),把连续的宽度切成三档——Compact(手机竖屏)、Medium(折叠展开/小平板)、Expanded(平板/桌面/大折叠)。关键不在档位本身,而在每一档该重排成什么样:
这正是第九章弹性思维在原生端的复刻,工具也已就位:Compose 的 WindowSizeClass、SwiftUI 的 NavigationSplitView——一个组件根据当前尺寸类切换布局,而不是把"手机假设"(如单栏导航、列表必跳详情)硬编码进去。折叠屏还多一个维度叫姿态(posture):合起、半开(像笔记本支起)、完全摊平,以及跨折痕的内容连续性——但底层心法不变,仍是 9.1 的 content-out:不是"为 Pixel Fold 写一个分支",而是问"内容到了这个宽度,怎样重排才最省用户的力"。按设备型号分支,是追不完的;按尺寸类与内容重排,才收敛。
HIG 与 Material 在所有表层差异之下共享同一个深层结构——都是把第一部分的美学原理编译成平台规则:层级(7.1)、光影(5.2)、字阶(4.3)、克制(7.7)。所以双平台设计的正确心法不是记两套规则,而是认出同一条原理在两地的不同方言。会一门"普通话"(第一部分),方言只是口音。
找一个你同时在 iPhone 和 Android 手机上用过的 App(或借朋友手机对比):① 用 11.3 的表逐行检查,它在每个维度上是"入乡随俗"还是"一套到底"?② 判断它选了 11.4 的哪种策略,找出一处礼仪适配做得好的细节和一处穿帮(iOS 风格的返回箭头出现在 Android 上是最常见的穿帮);③ 如果是 Android 12+ 设备,换一张壁纸,看哪些 App 跟着变色——那些就是接入了动态取色管线的 App。④ 变形测试:找一个平板或把手机横过来(或用模拟器拉宽窗口),看你常用的 App 怎么应对大屏——它是优雅地重排成双栏/侧栏(11.5),还是把手机布局直接抻宽、中间留一大片尴尬的空白?后者就是"放大的手机"反模式,记一例进 swipe file。