Communitygithub.com

Apple HIG 设计师

遵循苹果人机界面指南设计 iOS 应用。生成原生组件,验证设计,并确保 iPhone、iPad 和 Apple Watch 的无障碍合规性。

Apple HIG 设计师 是什么?

该技能旨在帮助开发者设计和构建遵循苹果人机界面指南(HIG)的原生 iOS 应用。它能够生成符合 HIG 规范的 SwiftUI 和 UIKit 组件,自动验证设计合规性,并确保无障碍性(如 VoiceOver、动态类型和色彩对比度)。该技能支持 iPhone、iPad 和 Apple Watch 平台,并提供有关清晰度、遵从性和深度等设计原则的指导。通过提供示例代码和最佳实践,它帮助开发者创建直观、一致且对用户友好的界面,同时遵守苹果的间距、排版和色彩系统。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Bershmern/my-skills/tree/HEAD/skills/apple-hig-designer

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

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)

按钮层级:

  1. 突出 - 主要操作(每屏一个)
  2. 边框 - 次要操作
  3. 普通 - 三级操作、链接

指南:

  • 最小触摸目标: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) {
        // 执行动画
    }
}

增强对比度

支持高对比度模式。

[因篇幅限制截断]

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

相关技能