关于 watchos-design-guidelines
面向 watchOS 应用设计者与开发者的设计指南,围绕 Apple Watch 的小屏幕和短时交互组织规则。内容涵盖数字表冠、复杂功能、常亮显示、健康与通知。
主要功能
- 01两秒内可理解的信息布局
- 02数字表冠滚动与精确输入
- 03浅层导航和复杂功能建议
- 04常亮显示的内容与隐私处理
- 05运动、健康和通知设计规则
适用场景
- 01精简抬腕即可查看的关键信息
- 02设计数字表冠驱动的选择器
- 03规划表盘复杂功能的显示与更新
- 04改善运动指标和手表通知
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ ehmo/ platform-design-skills --skill watchos-design-guidelines安装后在 Claude Code 中输入/watchos-design-guidelines确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
AGENTS.mdmetadata.jsonrules/_sections.md详细介绍
watchOS 设计指南
Apple Watch 是一款佩戴在手腕上的个人设备,便于快速查看。交互以秒计,而非分钟。每项设计决策都必须优先考虑信息理解的速度和交互的简洁性。
1. 便于快速查看的设计(关键)
这是 watchOS 的首要设计约束。如果用户抬起手腕后无法在 2 秒内获取关键信息,那么设计就失败了。
规则
- W-GL-01:主要信息必须无需滚动即可查看。首屏是唯一有保证会显示的屏幕。
- W-GL-02:交互时长应控制在 5 秒以内。围绕“抬腕—查看—放下”进行设计。
- W-GL-03:使用字号较大、对比度较高的文本。正文的有效最小字号为 16pt(系统字体)。标题应为 18pt 或更大。
- W-GL-04:文本仅保留必要内容。积极截断或缩写。含义明确时,使用 SF Symbols 代替文本标签。
- W-GL-05:考虑手腕放下后的状态。手腕放下时,应用会进入非活动状态。不要假设用户会持续关注。
- W-GL-06:每个屏幕优先呈现一项信息。如果要展示多个数据点,请通过大小、字重和颜色建立清晰的视觉层级。
屏幕尺寸参考
| 设备 | 屏幕宽度 | 屏幕高度 | 圆角半径 |
|---|---|---|---|
| 41mm(Series 9) | 176px | 215px | 36px |
| 45mm(Series 9) | 198px | 242px | 39px |
| 42mm(Series 10) | 180px | 220px | 37px |
| 46mm(Series 10) | 205px | 251px | 40px |
| 49mm(Ultra 2) | 205px | 251px | 40px |
反面模式
- 大段文字,需要滚动才能了解上下文
- 字号小、内容密集的数据表
- 必须多次轻点后才能看到有用信息
- 在 Watch 上照搬 iPhone 的屏幕布局
2. Digital Crown(高优先级)
Digital Crown 是滚动和精确选择数值的主要实体输入方式。它可提供触觉反馈,使用时应让人感到恰到好处。
规则
- W-DC-01:垂直内容应主要通过 Digital Crown 滚动。不要只依赖轻扫手势滚动。
- W-DC-02:对于数值选择器(时间、数量、滑块),应将 Crown 绑定到精确调整,并在每个离散数值处提供触觉定位反馈。
- W-DC-03:不要覆盖或干扰系统的 Crown 行为。系统会在媒体播放期间使用 Crown 控制音量,在系统 UI 中使用 Crown 滚动,并在复杂功能中使用 Time Travel。
- W-DC-04:提供与 Crown 旋转同步的视觉反馈。UI 必须逐帧响应 Crown 输入,不得出现可感知的延迟。
- W-DC-05:每次 Crown 增量都应更新。数值、选中项和高亮状态应随每次定位移动。不要等到手势结束后才处理 Crown 输入。
正确 — 通过 Crown 绑定并提供触觉定位反馈:
struct VolumePickerView: View {
@State private var volume: Double = 0.5
var body: some View {
VStack {
Text("\(Int(volume * 100))%")
.font(.title.bold())
Image(systemName: "speaker.wave.3")
}
.focusable()
.digitalCrownRotation(
$volume,
from: 0.0,
through: 1.0,
by: 0.05,
sensitivity: .medium,
isContinuous: false,
isHapticFeedbackEnabled: true
)
}
}
错误 — 忽略 Crown,强制用户只能通过触摸交互:
struct VolumePickerView: View {
@State private var volume: Double = 0.5
var body: some View {
Slider(value: $volume)
// No .digitalCrownRotation — Crown input is ignored
// Users must use touch-only, which is imprecise and frustrating on Watch
}
}
反面模式
- 忽略 Crown,强制所有交互都通过触摸完成
- 自定义 Crown 行为与系统预期相冲突
- 离散数值变化时缺少触觉反馈
- Crown 旋转时响应迟缓或批量更新
3. 导航(高优先级)
Watch 导航必须简洁且可预测。用户不应感到迷失,也不应无法返回已知状态。
规则
- W-NV-01:默认使用垂直页面滚动作为内容导航模式。页面从上到下滚动,使用 Digital Crown 操作。
- W-NV-02:使用
TabView展示顶层分区(最多 5 个标签页)。在标签页间水平滑动。每个标签页都是独立的功能区域。 - W-NV-03:使用
NavigationStack实现层级式深入导航。层级最多限制为 2-3 级。每个推入的视图都必须有返回按钮(由系统自动提供)。 - W-NV-04:避免在主要流程中使用模态表单。模态视图应仅用于专注的单一用途任务(例如确认、快速输入)。
- W-NV-05:应用最重要的操作应在启动后 1 次点击内可达。不要将主要功能藏在菜单或导航中。
导航模式参考
| 模式 | 使用场景 | 手势 |
|---|---|---|
| 垂直滚动 | 单个视图中的长篇内容 | Digital Crown / 上下滑动 |
| TabView(水平页面) | 应用顶层分区 | 左右滑动 |
| NavigationStack(推入/弹出) | 层级式深入导航 | 点击推入,向右滑动或点击返回按钮弹出 |
| 模态表单 | 确认、专注输入 | 以编程方式呈现,通过按钮或向下滑动关闭 |
反模式
- 过深的导航层级(4 级以上)
- 汉堡菜单或隐藏式导航抽屉
- 包含超过 5 项的标签栏
- 强迫用户滚动浏览长列表才能找到关键操作
4. Complications(高优先级)
Complications 是 Watch 应用中最醒目的展示区域。它们位于表盘上,无需启动应用即可提供一目了然的数据。
规则
- W-CP-01:支持多个 complication 系列,以最大限度提高表盘兼容性。至少支持
accessoryCircular、accessoryCorner和accessoryRectangular(WidgetKit、watchOS 9+)。 - W-CP-02:同时提供染色(单色)和全彩版本。染色 complication 在系统应用单一染色后仍必须清晰易读。
- W-CP-03:通过
TimelineProvider更新 complications。如果数据可预测(例如下一个日历事件、天气预报),请提供未来时间线条目。保持数据新鲜——过时的 complications 会削弱用户信任。 - W-CP-04:Complication 内容必须无需上下文即可理解。用户瞥一眼表盘就应立即理解数据(例如,“72F”而不是“72”)。
- W-CP-05:点击 complication 必须将应用打开到相关上下文,而不是仅打开应用的根视图。
正确 — 使用 WidgetKit TimelineProvider 为 accessoryCircular complication 提供支持:
struct StepCountProvider: TimelineProvider {
func placeholder(in context: Context) -> StepEntry {
StepEntry(date: Date(), steps: 5000)
}
func getSnapshot(in context: Context, completion: @escaping (StepEntry) -> Void) {
completion(StepEntry(date: Date(), steps: HealthStore.shared.todaySteps))
}
func getTimeline(in context: Context, completion: @escaping (Timeline<StepEntry>) -> Void) {
let entry = StepEntry(date: Date(), steps: HealthStore.shared.todaySteps)
// Refresh in 15 minutes
let nextUpdate = Calendar.current.date(byAdding: .minute, value: 15, to: Date())!
completion(Timeline(entries: [entry], policy: .after(nextUpdate)))
}
}
struct StepCountComplicationView: View {
let entry: StepEntry
var body: some View {
Gauge(value: Double(entry.steps), in: 0...10000) {
Image(systemName: "figure.walk")
} currentValueLabel: {
Text("\(entry.steps / 1000)k")
}
.gaugeStyle(.accessoryCircular)
}
}
Complication 系列参考
使用 WidgetFamily 值:
| 系列 | 形状 | 典型内容 |
|---|---|---|
accessoryCircular | 小圆形 | 单个数值、图标或仪表 |
accessoryCorner | 曲面,顶部为圆角 | 带标签的仪表,或带图标的文本 |
accessoryRectangular | 宽矩形 | 多行文本、图表或详细视图 |
accessoryInline | 文本行 | 简短标签或数值 |
反模式
- 只支持一种 complication 系列
- 数据过时,数小时都不更新
- 点击 complication 后进入通用应用主页,而非相关内容
- 染色模式下的 complication 难以辨认(对比度不足)
5. 常亮显示(中优先级)
当用户垂下手腕时,watchOS 会进入常亮状态,显示当前应用的暗化版本。必须有意识地处理这一状态。
规则
- W-AO-01:降低常亮状态下的视觉复杂度。移除动画、次要 UI 元素和非必要细节。仅显示最关键信息。
- W-AO-02:在暗显状态下隐藏敏感或私密数据(例如消息内容、健康详情、财务信息)。使用脱敏或占位内容。
- W-AO-03:降低常亮状态下的更新频率。每分钟最多更新显示一次。对于时间敏感的内容,使用带有
.everyMinute时间表的TimelineView。 - W-AO-04:使用系统提供的暗显行为。不要实现自定义暗显。系统会自动降低亮度并可应用色调。确保内容在亮度降低时仍清晰可读。
- W-AO-05:测试活跃状态和常亮状态。两种状态之间的切换应当流畅无缝——抬腕时布局不应偏移或跳动。
反模式
- 在活跃状态和常亮状态下显示完全相同的 UI(浪费电量,也可能暴露私密数据)
- 在常亮状态下播放动画或频繁更新
- 从活跃状态切换到暗显状态时布局发生偏移
- 忘记对敏感信息进行脱敏
6. 运动与健康(中等)
运动和健康应用有独特的要求:长时间运动、实时指标和身体感知功能。
规则
- W-WK-01:使用大号、高对比度文本显示实时运动指标。心率、时长、距离和卡路里应在运动过程中易于读取,无需停下来。
- W-WK-02:在达到里程碑时提供触觉反馈(完成一圈、达到目标、心率区间变化)。触觉反馈至关重要,因为用户运动时可能不会看屏幕。
- W-WK-03:为相关运动类型(跑步、步行)支持自动暂停检测。用户期望停止移动时运动自动暂停,重新开始移动时自动恢复。
- W-WK-04:游泳运动期间启用 WaterLock。此功能会禁用触摸屏,防止水触碰造成误操作。使用数码表冠排水并解锁。
- W-WK-05:运动结束时显示清晰的总结屏幕,列出关键指标。允许用户通过一次操作保存或丢弃运动记录。
反模式
- 指标文本过小,需要眯眼或停下来才能阅读
- 重要运动事件缺少触觉反馈
- 户外运动不支持自动暂停
- 结束或保存运动记录需要复杂操作
7. 通知(中等)
手表通知必须简短且可操作。用户抬腕的时间只有一瞬间。
规则
- W-NT-01:设计「简短显示」通知,仅包含标题、应用图标和应用名称。这是用户初次抬腕时看到的内容,必须立即传达通知的用途。
- W-NT-02:设计「完整显示」通知,包含完整内容和最多 4 个操作按钮。持续查看通知即可进入完整显示。将最有用的操作直接显示在通知中。
- W-NT-03:使用合适的触觉通知类型,根据紧急程度匹配:标准提醒使用
.notification,积极事件使用.directionUp,消极事件使用.directionDown,结果状态使用.success/.failure/.retry。 - W-NT-04:不要发送过多通知。通知过多会导致用户彻底关闭通知。将非紧急更新合并发送。仅将时间敏感或可操作的信息作为手表通知。
触觉类型参考
| 触觉反馈 | 使用场景 |
|---|---|
.notification | 一般提醒 |
.directionUp | 积极事件(达到目标、股票上涨) |
.directionDown | 消极事件(股票下跌、天气预警) |
.success | 操作成功完成 |
.failure | 操作失败 |
.retry | 重试提示 |
.start | 活动开始 |
.stop | 活动结束 |
.click | 离散选择(表冠刻度、选择器) |
反模式
- 将每条 iPhone 通知都发送到 Watch
- 通知没有可操作按钮(迫使用户启动应用)
- 无论内容如何,所有通知都使用相同的触觉反馈类型
- 通知文本过长,需要大量滚动才能阅读
8. 无障碍功能(关键)
Apple Watch 支持 VoiceOver 和其他辅助技术。复杂功能和应用 UI 必须具备无障碍性。
规则
- W-AC-01:每个交互元素都必须有含义明确的无障碍标签。SF Symbol 名称不足以作为标签。仅含图像的按钮应使用
.accessibilityLabel()。 - W-AC-02:VoiceOver 必须能够浏览应用中的所有内容。不要从无障碍层级中隐藏关键信息。
- W-AC-03:为自定义控件(例如仪表、进度指示器、自定义选择器)提供无障碍值和提示。使用
.accessibilityValue()和.accessibilityHint()。 - W-AC-04:遵循“减弱动态效果”设置。启用时,停用或替换装饰性动画。使用
@Environment(\.accessibilityReduceMotion)。 - W-AC-05:响应“粗体文本”设置。用户启用粗体文本后,自定义文本必须相应调整。SwiftUI 动态字体会自动处理此项;绘制的自定义文本必须检查
@Environment(\.legibilityWeight)。 - W-AC-06:响应“增强对比度”设置。用户启用增强对比度后,自定义颜色必须提供更高对比度的变体。使用
@Environment(\.colorSchemeContrast)检测用户的偏好。
正确:
Button(action: startWorkout) {
Image(systemName: "play.fill")
}
.accessibilityLabel("Start workout")
错误:
Button(action: startWorkout) {
Image(systemName: "play.fill")
}
// VoiceOver reads "play" — not clear what action this performs
反模式
- 仅含图像且没有无障碍标签的按钮
- 没有无障碍值或提示的自定义控件
- 不遵循“减弱动态效果”设置的动画
- 将视力正常的用户可见的内容从无障碍树中隐藏
评估清单
在审查 watchOS 设计或实现时,请使用此清单。
一目了然
- 用户能否在 2 秒内理解主要内容?
- 无需滚动即可看到最重要的信息吗?
- 正文是否至少为 16pt,且对比度足够?
- 交互能否在 5 秒内完成?
Digital Crown
- 表冠是否用于滚动垂直内容?
- 数值选择器是否提供触觉定位反馈?
- 是否避免了与系统表冠行为冲突?
导航
- 启动后是否只需轻点 1 次即可触达主要操作?
- 导航层级是否不超过 3 层?
- 每个推入的视图是否都有返回按钮?
- 顶层分区是否在适用时使用 TabView 组织?
复杂功能
- 是否支持多个复杂功能系列?
- 复杂功能是否同时兼容染色模式和全彩模式?
- 复杂功能数据是否通过 TimelineProvider 更新?
- 轻点复杂功能是否会打开相关内容?
始终显示
- 在变暗状态下是否隐藏敏感数据?
- 非活动时是否降低视觉复杂度?
- 更新频率是否限制为每分钟一次或更低?
- 活动状态与变暗状态之间的切换是否流畅(没有布局跳动)?
锻炼
- 实时指标是否以大号、高对比度文本显示?
- 是否在达成里程碑时使用触觉反馈?
- 适用的锻炼类型是否支持自动暂停?
- 是否只需一次操作即可查看锻炼摘要?
通知
- 简短视图是否包含有意义的内容(标题 + 图标)?
- 完整视图是否包含内联操作?
- 触觉反馈类型是否与通知的紧急程度相匹配?
- 通知频率是否合适(不过于频繁)?
无障碍
- 所有交互元素都有含义明确的无障碍标签(不使用原始 SF Symbol 名称)
- 自定义控件通过
.accessibilityValue()/.accessibilityHint()提供无障碍值和提示 - VoiceOver 可以浏览应用中的所有内容——无障碍树中不隐藏任何关键内容
- 动画遵循「减少动态效果」设置(
@Environment(\.accessibilityReduceMotion)) - 遵循「粗体文本」偏好设置(SwiftUI 会自动处理;自定义文本会检查
@Environment(\.legibilityWeight)) - 遵循「增强对比度」偏好设置(自定义颜色提供对比度更高的变体)