mcpField
A
apple-hig-designer

apple-hig-designer

github.com/jamesrochabrun设计与 UI2211.1k 次安装41 周前更新
代码仓库

关于 apple-hig-designer

apple-hig-designer 是面向 iOS 设计与开发的技能,协助创建并检查符合 Apple Human Interface Guidelines 的界面,涵盖原生组件、无障碍和视觉规范。

主要功能

  1. 01生成 SwiftUI 与 UIKit 组件
  2. 02检查 Apple HIG 合规性
  3. 03支持 VoiceOver 与 Dynamic Type
  4. 04应用语义颜色和深色模式
  5. 05提供排版、间距与安全区指引

适用场景

  1. 01构建原生风格的 iOS 界面
  2. 02检查界面的无障碍支持
  3. 03为浅色和深色外观设计配色

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/jamesrochabrun/skills --skill apple-hig-designer

安装后在 Claude Code 中输入/apple-hig-designer确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
accessibility.md
colors.md
components.md
layout_spacing.md
typography.md
scripts/
audit_accessibility.sh
generate_ios_component.sh
validate_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)

按钮层级:

  1. 醒目 - 主要操作(每个屏幕一个)
  2. 描边 - 次要操作
  3. 纯文本 - 次级操作、链接

指南:

  • 最小点击目标: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

评论

支持 Markdown