关于 apple-hig-designer
apple-hig-designer 是面向 iOS 设计与开发的技能,协助创建并检查符合 Apple Human Interface Guidelines 的界面,涵盖原生组件、无障碍和视觉规范。
主要功能
- 01生成 SwiftUI 与 UIKit 组件
- 02检查 Apple HIG 合规性
- 03支持 VoiceOver 与 Dynamic Type
- 04应用语义颜色和深色模式
- 05提供排版、间距与安全区指引
适用场景
- 01构建原生风格的 iOS 界面
- 02检查界面的无障碍支持
- 03为浅色和深色外观设计配色
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ jamesrochabrun/ skills --skill apple-hig-designer安装后在 Claude Code 中输入/apple-hig-designer确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/accessibility.mdcolors.mdcomponents.mdlayout_spacing.mdtypography.mdscripts/audit_accessibility.shgenerate_ios_component.shvalidate_design.sh详细介绍
Apple HIG 设计师
遵循 Apple 人机界面指南(HIG),设计精美、原生的 iOS 应用。使用原生组件、恰当的排版、语义颜色和 Apple 的设计原则,打造易于访问、直观的界面。
此技能的作用
帮助你设计和构建具有原生体验并遵循 Apple 指南的 iOS 应用:
- 生成 iOS 组件 - 创建 SwiftUI 和 UIKit 组件
- 验证设计 - 检查是否符合 Apple HIG
- 确保无障碍功能 - VoiceOver、动态字体、颜色对比度
- 应用设计原则 - 清晰、从属、层次
- 使用语义颜色 - 自动支持深色模式
- 实现排版 - San Francisco 字体系统
- 遵循间距规范 - 8pt 网格系统和安全区域
Apple 的设计原则
1. 清晰
让内容清晰、聚焦。
任何字号的文本都清晰易读,图标精准明了,装饰元素低调得体,设计以功能为核心。
// ✅ Clear, focused content
Text("Welcome back, Sarah")
.font(.title)
.foregroundColor(.primary)
// ❌ Unclear, cluttered
Text("Welcome back, Sarah!!!")
.font(.title)
.foregroundColor(.red)
.background(.yellow)
.overlay(Image(systemName: "star.fill"))
2. 从属
UI 帮助人们理解和交互内容,但绝不与内容争抢注意力。
界面从属于内容,采用轻盈的视觉处理方式,让焦点留在内容上,并为内容留出呼吸空间。
// ✅ Content-focused
VStack(alignment: .leading, spacing: 8) {
Text("Article Title")
.font(.headline)
Text("Article content goes here...")
.font(.body)
.foregroundColor(.secondary)
}
.padding()
// ❌ Distracting UI
VStack(spacing: 8) {
Text("Article Title")
.font(.headline)
.foregroundColor(.white)
.background(.blue)
.border(.red, width: 3)
}
3. 层次
视觉层次和逼真的动态效果能够传达层级关系,并帮助人们理解彼此之间的联系。
鲜明的视觉层次和逼真的动态效果赋予界面活力,帮助人们理解内容。触控交互和易发现性增强愉悦感,让人们无需脱离当前情境即可使用各项功能。
// ✅ Clear depth hierarchy
ZStack {
Color(.systemBackground)
VStack {
// Card with elevation
CardView()
.shadow(radius: 8)
}
}
// Using blur for depth
Text("Content")
.background(.ultraThinMaterial)
iOS UI 组件
导航模式
1. 导航栏
用于导航和操作的顶部栏。
NavigationStack {
List {
Text("Item 1")
Text("Item 2")
}
.navigationTitle("Title")
.navigationBarTitleDisplayMode(.large)
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button("Add") {
// Action
}
}
}
}
指南:
- 在顶层视图中使用大标题
- 在详情视图中使用内嵌标题
- 操作应与当前情境相关
- 工具栏项目最多 2-3 个
2. 标签栏
用于顶层目标位置的底部导航。
TabView {
HomeView()
.tabItem {
Label("Home", systemImage: "house")
}
SearchView()
.tabItem {
Label("Search", systemImage: "magnifyingglass")
}
ProfileView()
.tabItem {
Label("Profile", systemImage: "person")
}
}
指南:
- 最多使用 3-5 个标签
- 使用 SF Symbols 作为图标
- 标签应简洁(一词)
- 切勿隐藏或停用标签
- 不要在同一视图中同时使用标签栏和工具栏
3. 列表
可滚动的项目列表。
List {
Section("Today") {
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. Sheet(模态视图)
以模态方式呈现内容。
struct ContentView: View {
@State private var showSheet = false
var body: some View {
Button("Show Details") {
showSheet = true
}
.sheet(isPresented: $showSheet) {
DetailView()
.presentationDetents([.medium, .large])
}
}
}
Sheet 停靠位置:
.medium- 半屏.large- 全屏- 也可自定义高度
表单控件
1. Button
主要操作控件。
// Filled button (primary action)
Button("Continue") {
// Action
}
.buttonStyle(.borderedProminent)
// Bordered button (secondary action)
Button("Cancel") {
// Action
}
.buttonStyle(.bordered)
// Plain button (tertiary action)
Button("Learn More") {
// Action
}
.buttonStyle(.plain)
按钮层级:
- 醒目 - 主要操作(每个屏幕一个)
- 描边 - 次要操作
- 纯文本 - 次级操作、链接
指南:
- 最小点击目标:44x44 点
- 按钮标签使用动词
- 执行破坏性操作前应要求确认
2. TextField
文本输入控件。
@State private var username = ""
@State private var password = ""
VStack(alignment: .leading, spacing: 16) {
// Standard text field
TextField("Username", text: $username)
.textFieldStyle(.roundedBorder)
.textContentType(.username)
.textInputAutocapitalization(.never)
.autocorrectionDisabled()
// Secure field
SecureField("Password", text: $password)
.textFieldStyle(.roundedBorder)
.textContentType(.password)
}
文本内容类型:
.username- 用户名字段.password- 密码字段.emailAddress- 电子邮件字段.telephoneNumber- 电话号码.creditCardNumber- 信用卡号
3. Toggle
布尔控件(开关)。
@State private var isEnabled = false
Toggle("Enable notifications", isOn: $isEnabled)
.toggleStyle(.switch)
指南:
- 标签应说明开关控制的内容
- 效果应立即生效
- 仅用于二元选择
4. Picker
选择控件。
@State private var selectedSize = "Medium"
let sizes = ["Small", "Medium", "Large"]
// Menu style
Picker("Size", selection: $selectedSize) {
ForEach(sizes, id: \.self) { size in
Text(size).tag(size)
}
}
.pickerStyle(.menu)
// Segmented style (for 2-5 options)
Picker("Size", selection: $selectedSize) {
ForEach(sizes, id: \.self) { size in
Text(size).tag(size)
}
}
.pickerStyle(.segmented)
Picker 样式:
.menu- 下拉菜单(默认).segmented- 分段控件(2-5 个选项).wheel- 可滚动转盘.inline- 内嵌列表(用于表单)
卡片和容器
卡片视图
struct CardView: View {
var body: some View {
VStack(alignment: .leading, spacing: 12) {
Text("Title")
.font(.headline)
Text("Description goes here with some details about the content.")
.font(.subheadline)
.foregroundColor(.secondary)
.lineLimit(2)
Spacer()
Button("Action") {
// Action
}
.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 字体系统
Apple 设计的系统字体,确保最佳易读性。
// Dynamic Type text styles
Text("Large Title").font(.largeTitle) // 34pt
Text("Title").font(.title) // 28pt
Text("Title 2").font(.title2) // 22pt
Text("Title 3").font(.title3) // 20pt
Text("Headline").font(.headline) // 17pt semibold
Text("Body").font(.body) // 17pt regular
Text("Callout").font(.callout) // 16pt
Text("Subheadline").font(.subheadline) // 15pt
Text("Footnote").font(.footnote) // 13pt
Text("Caption").font(.caption) // 12pt
Text("Caption 2").font(.caption2) // 11pt
使用动态字体的自定义字体
// Custom font that scales with Dynamic Type
Text("Custom Text")
.font(.custom("YourFont-Regular", size: 17, relativeTo: .body))
字重
Text("Light").fontWeight(.light)
Text("Regular").fontWeight(.regular)
Text("Medium").fontWeight(.medium)
Text("Semibold").fontWeight(.semibold)
Text("Bold").fontWeight(.bold)
Text("Heavy").fontWeight(.heavy)
字体排版指南
建议:
- ✅ 使用系统字体(San Francisco),确保一致性
- ✅ 支持动态字体,提升无障碍体验
- ✅ 使用语义化文本样式(.headline、.body 等)
- ✅ 正文最小字号:17pt
- ✅ 行间距:字号的 120%–145%
避免:
- ❌ 使用过多字号(遵循系统样式)
- ❌ 文本小于 11pt
- ❌ 长文本使用全大写
- ❌ 禁用动态字体
颜色
语义化颜色
可自动适配浅色/深色模式的颜色。
// UI Element Colors
Color(.label) // Primary text
Color(.secondaryLabel) // Secondary text
Color(.tertiaryLabel) // Tertiary text
Color(.quaternaryLabel) // Watermark text
Color(.systemBackground) // Primary background
Color(.secondarySystemBackground) // Secondary background
Color(.tertiarySystemBackground) // Tertiary background
Color(.systemFill) // Fill colors
Color(.secondarySystemFill)
Color(.tertiarySystemFill)
Color(.quaternarySystemFill)
Color(.separator) // Separator lines
Color(.opaqueSeparator) // Non-transparent separator
系统颜色
// Standard system colors (adapt to dark mode)
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)
支持深色模式的自定义颜色
// Define adaptive color
extension Color {
static let customBackground = Color("CustomBackground")
}
// In Assets.xcassets, create color set with:
// - Any Appearance: #FFFFFF
// - Dark Appearance: #000000
颜色对比度指南
符合 WCAG AA 标准:
- 普通文本:对比度至少为 4.5:1
- 大号文本(24pt 及以上):对比度至少为 3:1
- UI 组件:对比度为 3:1
自定义颜色:
- 开启“增强对比度”进行测试
- 关键文本的对比度应达到 7:1
- 确保两种模式下都有足够的对比度
间距与布局
8 点网格系统
所有间距都应为 8 的倍数。
// Spacing values
.padding(8) // 8pt
.padding(16) // 16pt (standard)
.padding(24) // 24pt
.padding(32) // 32pt
.padding(40) // 40pt
.padding(48) // 48pt
// Edge-specific padding
.padding(.horizontal, 16)
.padding(.vertical, 24)
.padding(.top, 16)
.padding(.bottom, 16)
安全区域
遵循设备的安全区域。
// Content within safe area (default)
VStack {
Text("Content")
}
// Extend beyond safe area
VStack {
Color.blue
}
.ignoresSafeArea()
// Extend top only
VStack {
Color.blue
}
.ignoresSafeArea(edges: .top)
触控目标
交互区域的最小尺寸为 44x44 点。
Button("Tap") {
// Action
}
.frame(minWidth: 44, minHeight: 44)
间距指南
// Component spacing
VStack(spacing: 8) { // Tight spacing
Text("Line 1")
Text("Line 2")
}
VStack(spacing: 16) { // Standard spacing
Text("Section 1")
Text("Section 2")
}
VStack(spacing: 24) { // Loose spacing
SectionView()
SectionView()
}
无障碍
VoiceOver 支持
为盲人和低视力用户提供的屏幕阅读器。
// Accessible label
Image(systemName: "heart.fill")
.accessibilityLabel("Favorite")
// Accessible value
Slider(value: $volume)
.accessibilityLabel("Volume")
.accessibilityValue("\(Int(volume * 100))%")
// Accessible hint
Button("Share") {
share()
}
.accessibilityHint("Shares this item with others")
// Group elements
HStack {
Image(systemName: "person")
Text("John Doe")
}
.accessibilityElement(children: .combine)
// Hidden from VoiceOver
Image("decorative")
.accessibilityHidden(true)
动态字体
支持用户偏好的文本大小。
// Automatically supported with system fonts
Text("This text scales")
.font(.body)
// Limit scaling (if necessary)
Text("This text has limits")
.font(.body)
.dynamicTypeSize(...DynamicTypeSize.xxxLarge)
// Custom font with Dynamic Type
Text("Custom font")
.font(.custom("YourFont", size: 17, relativeTo: .body))
色盲
为色盲用户设计。
// Don't rely on color alone
HStack {
Image(systemName: "checkmark.circle.fill")
.foregroundColor(.green)
Text("Success")
}
// Not just color
Circle()
.fill(.green)
// ❌ Color only
// Better with shape/icon
HStack {
Image(systemName: "checkmark.circle.fill")
Circle().fill(.green)
}
// ✅ Color + shape
减少动态效果
尊重用户对动态效果的偏好。
@Environment(\.accessibilityReduceMotion) var reduceMotion
var animation: Animation {
reduceMotion ? .none : .spring()
}
Button("Animate") {
withAnimation(animation) {
// Animate
}
}
增强对比度
支持高对比度模式。
@Environment(\.colorSchemeContrast) var contrast
var textColor: Color {
contrast == .increased ? .primary : .secondary
}
Text("Content")
.foregroundColor(textColor)
深色模式
同时支持浅色和深色外观。
自动支持
// Use semantic colors (automatic)
Color(.label) // Adapts automatically
Color(.systemBackground) // Adapts automatically
测试深色模式
// Preview both modes
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
.preferredColorScheme(.light)
ContentView()
.preferredColorScheme(.dark)
}
}
深色模式指南
建议:
- ✅ 使用语义化颜色
- ✅ 开启“增强对比度”进行测试
- ✅ 开启“降低透明度”进行测试
- ✅ 确保两种模式下都有足够的对比度
避免:
- ❌ 使用纯黑色(#000000)——请使用 systemBackground
- ❌ 自动反转颜色
- ❌ 假设用户偏好
SF Symbols
Apple 的图标系统(包含 3000 多个符号)。
// Basic symbol
Image(systemName: "heart")
// Colored symbol
Image(systemName: "heart.fill")
.foregroundColor(.red)
// Sized symbol
Image(systemName: "heart")
.imageScale(.large)
// Font-based sizing
Image(systemName: "heart")
.font(.title)
// Multicolor symbols
Image(systemName: "person.crop.circle.fill.badge.checkmark")
.symbolRenderingMode(.multicolor)
// Hierarchical rendering
Image(systemName: "heart.fill")
.symbolRenderingMode(.hierarchical)
.foregroundColor(.red)
SF Symbols 指南
- 有系统符号时优先使用
- 保持视觉粗细一致
- 使用多色符号表达语义
- 根据使用场景选择合适的尺寸
App 图标
图标尺寸
iOS:
- 1024x1024 (App Store)
- 180x180 (iPhone @3x)
- 120x120 (iPhone @2x)
- 167x167 (iPad Pro)
- 152x152 (iPad @2x)
watchOS:
- 1024x1024 (App Store)
- 196x196 (49mm)
- 216x216 (45mm)
图标设计指南
建议:
- ✅ 使用简单、易识别的形状
- ✅ 填满整个图标区域
- ✅ 在设备上测试(不要只看样机)
- ✅ 保持视觉风格一致
避免:
- ❌ 包含文本(尺寸很小)
- ❌ 使用照片
- ❌ 仿制 Apple 硬件
- ❌ 使用半透明效果
动画与动态效果
标准动画
// Spring animation (natural, bouncy)
withAnimation(.spring()) {
offset = 100
}
// Linear animation
withAnimation(.linear(duration: 0.3)) {
opacity = 0
}
// Ease in/out
withAnimation(.easeInOut(duration: 0.3)) {
scale = 1.2
}
手势驱动
@State private var offset = CGSize.zero
var body: some View {
Circle()
.offset(offset)
.gesture(
DragGesture()
.onChanged { value in
offset = value.translation
}
.onEnded { _ in
withAnimation(.spring()) {
offset = .zero
}
}
)
}
动态效果指南
- 动画时长控制在 0.3 秒以内
- 对交互元素使用弹簧动画
- 尊重“减少动态效果”设置
- 为所有交互提供视觉反馈
最佳实践
导航
- 分层式 - 使用 NavigationStack 进行逐级导航
- 平铺式 - 使用 TabView 展示同级目的地
- 内容驱动式 - 用于媒体应用
反馈
- 视觉 - 点击时高亮显示
- 触觉 - 使用 UIImpactFeedbackGenerator
- 音频 - 谨慎使用系统声音
加载状态
struct LoadingView: View {
var body: some View {
VStack {
ProgressView()
.scaleEffect(1.5)
Text("Loading...")
.font(.caption)
.foregroundColor(.secondary)
.padding(.top)
}
}
}
错误状态
struct ErrorView: View {
let message: String
let retry: () -> Void
var body: some View {
VStack(spacing: 16) {
Image(systemName: "exclamationmark.triangle")
.font(.system(size: 48))
.foregroundColor(.orange)
Text("Something went wrong")
.font(.headline)
Text(message)
.font(.subheadline)
.foregroundColor(.secondary)
.multilineTextAlignment(.center)
Button("Try Again") {
retry()
}
.buttonStyle(.borderedProminent)
}
.padding()
}
}
空状态
struct EmptyStateView: View {
var body: some View {
VStack(spacing: 16) {
Image(systemName: "tray")
.font(.system(size: 64))
.foregroundColor(.secondary)
Text("No Items")
.font(.title2)
Text("Your items will appear here")
.font(.subheadline)
.foregroundColor(.secondary)
Button("Add Item") {
// Action
}
.buttonStyle(.borderedProminent)
}
}
}
平台注意事项
iPhone
- 针对不同尺寸设计(SE、Pro、Pro Max)
- 支持竖屏和横屏
- 针对刘海屏/动态岛使用安全区域
- 考虑单手操作
iPad
- 支持多任务处理(分屏浏览、侧拉)
- 使用侧边栏导航
- 适配更大的屏幕(不要仅仅放大)
- 考虑支持键盘快捷键
- 支持外接显示器
Apple Watch
- 信息应便于快速浏览
- 触控目标应较大(>44pt)
- 尽量减少所需交互
- 使用 Digital Crown 滚动
- 支持全天候显示
资源
“设计不只是外观和感受。设计关乎它如何运作。” - Steve Jobs