Apple HIG 设计师 是做什么的?
遵循苹果人机界面指南(HIG)设计美观、原生的 iOS 应用。创建无障碍、直观的界面,使用原生组件、恰当的排版、语义化颜色和苹果的设计原则。
该技能的功能
帮助您设计和构建感觉原生并遵循苹果指南的 iOS 应用:
- 生成 iOS 组件 - 创建 SwiftUI 和 UIKit 组件
- 验证设计 - 检查是否符合 Apple HIG
- 确保无障碍性 - VoiceOver、动态类型、颜色对比度
- 应用设计原则 - 清晰度、遵从性、深度
- 使用语义化颜色 - 自动暗黑模式支持
- 实现排版 - San Francisco 字体系统
- 遵循间距 - 8pt 网格系统和安全区域
苹果的设计原则
1. 清晰度
使内容清晰且聚焦。
文本在各种尺寸下都清晰易读,图标精确明了,装饰物微妙恰当,设计以功能为驱动。
// ✅ 清晰、聚焦的内容
Text("欢迎回来,Sarah")
.font(.title)
.foregroundColor(.primary)
// ❌ 不清晰、杂乱
Text("欢迎回来,Sarah!!!")
.font(.title)
.foregroundColor(.red)
.background(.yellow)
.overlay(Image(systemName: "star.fill"))
2. 遵从性
UI 帮助用户理解和交互内容,但从不与之竞争。
界面遵从内容,使用轻盈的视觉处理,使焦点保持在内容上,并给内容留出喘息空间。
// ✅ 内容聚焦
VStack(alignment: .leading, spacing: 8) {
Text("文章标题")
.font(.headline)
Text("文章内容...")
.font(.body)
.foregroundColor(.secondary)
}
.padding()
// ❌ 分散注意力的 UI
VStack(spacing: 8) {
Text("文章标题")
.font(.headline)
.foregroundColor(.white)
.background(.blue)
.border(.red, width: 3)
}
3. 深度
视觉层次和逼真的动效传达层级关系,帮助用户理解关联。
独特的视觉层次和逼真的动效赋予活力并促进理解。触摸和可发现性增强了愉悦感,并在不丢失上下文的情况下实现对功能的访问。
// ✅ 清晰的深度层次
ZStack {
Color(.systemBackground)
VStack {
// 带阴影的卡片
CardView()
.shadow(radius: 8)
}
}
// 使用模糊效果增加深度
Text("内容")
.background(.ultraThinMaterial)
iOS UI 组件
导航模式
1. 导航栏
用于导航和操作的顶部栏。
NavigationStack {
List {
Text("项目 1")
Text("项目 2")
}
.navigationTitle("标题")
.navigationBarTitleDisplayMode(.large)
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button("添加") {
// 操作
}
}
}
}
指南:
- 顶层视图使用大标题
- 详细视图使用内联标题
- 保持操作与当前上下文相关
- 最多 2-3 个工具栏项目
2. 标签栏
用于顶层目的地的底部导航。
TabView {
HomeView()
.tabItem {
Label("首页", systemImage: "house")
}
SearchView()
.tabItem {
Label("搜索", systemImage: "magnifyingglass")
}
ProfileView()
.tabItem {
Label("个人", systemImage: "person")
}
}
指南:
- 最多 3-5 个标签
- 使用 SF Symbols 作为图标
- 标签应简洁(一个词)
- 切勿隐藏或禁用标签
- 不要在同一视图中同时使用标签栏和工具栏
3. 列表
可滚动的项目列表。
List {
Section("今天") {
ForEach(items) { item in
NavigationLink {
DetailView(item: item)
} label: {
HStack {
Image(systemName: item.icon)
.foregroundColor(.accentColor)
Text(item.title)
}
}
}
}
}
.listStyle(.insetGrouped)
列表样式:
.plain- 边缘到边缘的行.insetGrouped- 圆角、缩进的分组(iOS 默认).sidebar- 用于导航侧边栏
4. 表单(模态)
以模态方式呈现内容。
struct ContentView: View {
@State private var showSheet = false
var body: some View {
Button("显示详情") {
showSheet = true
}
.sheet(isPresented: $showSheet) {
DetailView()
.presentationDetents([.medium, .large])
}
}
}
表单吸附高度:
.medium- 半屏.large- 全屏- 支持自定义高度
表单控件
1. 按钮
主要操作控件。
// 填充按钮(主要操作)
Button("继续") {
// 操作
}
.buttonStyle(.borderedProminent)
// 边框按钮(次要操作)
Button("取消") {
// 操作
}
.buttonStyle(.bordered)
// 普通按钮(三级操作)
Button("了解更多") {
// 操作
}
.buttonStyle(.plain)
按钮层级:
- 突出 - 主要操作(每屏一个)
- 边框 - 次要操作
- 普通 - 三级操作、链接
指南:
- 最小触摸目标:44x44 点
- 按钮标签使用动词
- 破坏性操作需要确认
2. 文本输入框
文本输入控件。
@State private var username = ""
@State private var password = ""
VStack(alignment: .leading, spacing: 16) {
// 标准文本输入框
TextField("用户名", text: $username)
.textFieldStyle(.roundedBorder)
.textContentType(.username)
.textInputAutocapitalization(.never)
.autocorrectionDisabled()
// 安全文本输入框
SecureField("密码", text: $password)
.textFieldStyle(.roundedBorder)
.textContentType(.password)
}
文本内容类型:
.username- 用户名字段.password- 密码字段.emailAddress- 邮箱地址字段.telephoneNumber- 电话号码.creditCardNumber- 信用卡号
3. 开关
布尔控制(开关)。
@State private var isEnabled = false
Toggle("启用通知", isOn: $isEnabled)
.toggleStyle(.switch)
指南:
- 标签描述开关控制的内容
- 效果应即时生效
- 仅用于二元选择
4. 选择器
选择控件。
@State private var selectedSize = "中"
let sizes = ["小", "中", "大"]
// 菜单样式
Picker("尺寸", selection: $selectedSize) {
ForEach(sizes, id: \.self) { size in
Text(size).tag(size)
}
}
.pickerStyle(.menu)
// 分段样式(适用于 2-5 个选项)
Picker("尺寸", selection: $selectedSize) {
ForEach(sizes, id: \.self) { size in
Text(size).tag(size)
}
}
.pickerStyle(.segmented)
选择器样式:
.menu- 下拉菜单(默认).segmented- 分段控件(2-5 个选项).wheel- 可滚动的轮盘.inline- 内联列表(在表单中)
卡片和容器
卡片视图
struct CardView: View {
var body: some View {
VStack(alignment: .leading, spacing: 12) {
Text("标题")
.font(.headline)
Text("这里有一段描述,包含一些关于内容的详细信息。")
.font(.subheadline)
.foregroundColor(.secondary)
.lineLimit(2)
Spacer()
Button("操作") {
// 操作
}
.buttonStyle(.borderedProminent)
}
.padding()
.frame(width: 300, height: 200)
.background(Color(.systemBackground))
.cornerRadius(12)
.shadow(color: .black.opacity(0.1), radius: 8, x: 0, y: 4)
}
}
排版
San Francisco 字体系统
苹果为优化可读性而设计的系统字体。
// 动态类型文本样式
Text("大标题").font(.largeTitle) // 34pt
Text("标题").font(.title) // 28pt
Text("标题 2").font(.title2) // 22pt
Text("标题 3").font(.title3) // 20pt
Text("头条").font(.headline) // 17pt 半粗体
Text("正文").font(.body) // 17pt 常规
Text("提示").font(.callout) // 16pt
Text("副标题").font(.subheadline) // 15pt
Text("脚注").font(.footnote) // 13pt
Text("说明").font(.caption) // 12pt
Text("说明 2").font(.caption2) // 11pt
使用动态类型的自定义字体
// 随动态类型缩放的自定义字体
Text("自定义文本")
.font(.custom("YourFont-Regular", size: 17, relativeTo: .body))
字重
Text("细体").fontWeight(.light)
Text("常规").fontWeight(.regular)
Text("中粗").fontWeight(.medium)
Text("半粗").fontWeight(.semibold)
Text("粗体").fontWeight(.bold)
Text("特粗").fontWeight(.heavy)
排版指南
应该做:
- ✅ 使用系统字体 (San Francisco) 以保证一致性
- ✅ 支持动态类型以实现无障碍
- ✅ 使用语义化文本样式 (.headline、.body 等)
- ✅ 正文最小字号:17pt
- ✅ 行间距:字体大小的 120-145%
不应该做:
- ❌ 使用过多字体大小(坚持使用系统样式)
- ❌ 使文本小于 11pt
- ❌ 长文本全部大写
- ❌ 禁用动态类型
颜色
语义化颜色
自动适应浅色/深色模式的颜色。
// UI 元素颜色
Color(.label) // 主要文本
Color(.secondaryLabel) // 次要文本
Color(.tertiaryLabel) // 三级文本
Color(.quaternaryLabel) // 水印文本
Color(.systemBackground) // 主要背景
Color(.secondarySystemBackground) // 次要背景
Color(.tertiarySystemBackground) // 三级背景
Color(.systemFill) // 填充颜色
Color(.secondarySystemFill)
Color(.tertiarySystemFill)
Color(.quaternarySystemFill)
Color(.separator) // 分隔线
Color(.opaqueSeparator) // 不透明分隔线
系统颜色
// 标准系统颜色(适应深色模式)
Color(.systemRed)
Color(.systemOrange)
Color(.systemYellow)
Color(.systemGreen)
Color(.systemMint)
Color(.systemTeal)
Color(.systemCyan)
Color(.systemBlue)
Color(.systemIndigo)
Color(.systemPurple)
Color(.systemPink)
Color(.systemBrown)
Color(.systemGray)
带深色模式的自定义颜色
// 定义自适应颜色
extension Color {
static let customBackground = Color("CustomBackground")
}
// 在 Assets.xcassets 中,创建颜色集:
// - 任意外观: #FFFFFF
// - 深色外观: #000000
颜色对比度指南
WCAG AA 合规性:
- 普通文本:最小 4.5:1 的对比度
- 大文本(24pt+):最小 3:1 的对比度
- UI 组件:最小 3:1 的对比度
自定义颜色:
- 在“增强对比度”启用时进行测试
- 关键文本的目标对比度设为 7:1
- 确保在两种模式下都有足够的对比度
间距和布局
8 点网格系统
所有间距应为 8 的倍数。
// 间距值
.padding(8) // 8pt
.padding(16) // 16pt (标准)
.padding(24) // 24pt
.padding(32) // 32pt
.padding(40) // 40pt
.padding(48) // 48pt
// 特定边距
.padding(.horizontal, 16)
.padding(.vertical, 24)
.padding(.top, 16)
.padding(.bottom, 16)
安全区域
尊重设备的安全区域。
// 内容在安全区域内(默认)
VStack {
Text("内容")
}
// 扩展到安全区域外
VStack {
Color.blue
}
.ignoresSafeArea()
// 仅扩展顶部
VStack {
Color.blue
}
.ignoresSafeArea(edges: .top)
触摸目标
最小交互尺寸:44x44 点。
Button("点击") {
// 操作
}
.frame(minWidth: 44, minHeight: 44)
间距指南
// 组件间距
VStack(spacing: 8) { // 紧密间距
Text("第 1 行")
Text("第 2 行")
}
VStack(spacing: 16) { // 标准间距
Text("部分 1")
Text("部分 2")
}
VStack(spacing: 24) { // 宽松间距
SectionView()
SectionView()
}
无障碍性
VoiceOver 支持
为盲人和低视力用户提供的屏幕阅读器。
// 无障碍标签
Image(systemName: "heart.fill")
.accessibilityLabel("收藏")
// 无障碍值
Slider(value: $volume)
.accessibilityLabel("音量")
.accessibilityValue("\(Int(volume * 100))%")
// 无障碍提示
Button("分享") {
share()
}
.accessibilityHint("将此项目分享给他人")
// 组合元素
HStack {
Image(systemName: "person")
Text("张三")
}
.accessibilityElement(children: .combine)
// 对 VoiceOver 隐藏
Image("decorative")
.accessibilityHidden(true)
动态类型
支持用户偏好的文本大小。
// 使用系统字体自动支持
Text("此文本会缩放")
.font(.body)
// 限制缩放(如有必要)
Text("此文本有大小限制")
.font(.body)
.dynamicTypeSize(...DynamicTypeSize.xxxLarge)
// 带动态类型的自定义字体
Text("自定义字体")
.font(.custom("YourFont", size: 17, relativeTo: .body))
色盲
为色盲用户设计。
// 不要仅依赖颜色
HStack {
Image(systemName: "checkmark.circle.fill")
.foregroundColor(.green)
Text("成功")
}
// 不仅仅是颜色
Circle()
.fill(.green)
// ❌ 仅颜色
// 更佳做法:颜色 + 形状/图标
HStack {
Image(systemName: "checkmark.circle.fill")
Circle().fill(.green)
}
// ✅ 颜色 + 形状
减少动效
尊重用户的动效偏好。
@Environment(\.accessibilityReduceMotion) var reduceMotion
var animation: Animation {
reduceMotion ? .none : .spring()
}
Button("动画") {
withAnimation(animation) {
// 执行动画
}
}
增强对比度
支持高对比度模式。
[因篇幅限制截断]