构建可复用的 SwiftUI 组件库

发布: (2025年12月2日 GMT+8 08:37)
4 min read
原文: Dev.to

Source: Dev.to

SwiftUI 让 构建 UI 变得轻而易举——但要打造在整个应用中保持一致的 可复用组件 则是另一番挑战。

随着应用的增长,UI 重复出现会成为真正的问题:

  • 重复的按钮样式
  • 不一致的卡片形状
  • 重复的文本修饰符
  • 复制‑粘贴的阴影
  • 同一布局的多个版本

组件库 能解决这些问题。

今天你将学习如何构建一个现代、可扩展、符合 Apple 风格的 SwiftUI 组件库,内容包括:

  • 按钮
  • 卡片
  • 文本框
  • 浮动面板
  • 标签(Chip)
  • 设计令牌(颜色、圆角、阴影)
  • 可复用的修饰符
  • 一致的样式

这正是我在真实生产应用中使用的完整结构。让我们一起动手吧 🚀

1. 从 Design 文件夹开始

Design/
├── Colors.swift
├── Radii.swift
├── Shadows.swift
└── Typography.swift

Colors.swift

enum AppColor {
    static let primary = Color.blue
    static let background = Color(.systemBackground)
    static let glassStroke = Color.white.opacity(0.25)
}

Radii.swift

enum AppRadius {
    static let small: CGFloat = 10
    static let medium: CGFloat = 16
    static let large: CGFloat = 22
}

Shadows.swift

enum AppShadow {
    static let card = Color.black.opacity(0.18)
    static let glow = Color.blue.opacity(0.3)
}

Typography.swift

enum AppFont {
    static let title = Font.system(.title3, design: .rounded).bold()
    static let body = Font.system(.body, design: .rounded)
}

一处定义 → 全局一致。

2. 可复用的按钮样式

PrimaryButton

struct PrimaryButton: View {
    let title: String
    let action: () -> Void

    var body: some View {
        Button(action: action) {
            Text(title)
                .font(AppFont.body.bold())
                .padding(.horizontal, 28)
                .padding(.vertical, 14)
                .background(AppColor.primary)
                .foregroundColor(.white)
                .clipShape(RoundedRectangle(cornerRadius: AppRadius.medium, style: .continuous))
                .shadow(color: AppShadow.card, radius: 16, y: 8)
        }
    }
}

使用方式

PrimaryButton(title: "Continue") {
    print("Pressed")
}

3. 玻璃卡片组件(可复用)

struct GlassCard: View {
    @ViewBuilder let content: () -> Content

    var body: some View {
        content()
            .padding(20)
            .background(.ultraThinMaterial)
            .clipShape(RoundedRectangle(cornerRadius: AppRadius.large, style: .continuous))
            .overlay(
                RoundedRectangle(cornerRadius: AppRadius.large, style: .continuous)
                    .stroke(AppColor.glassStroke, lineWidth: 1)
            )
            .shadow(color: AppShadow.card, radius: 24, y: 12)
    }
}

使用方式

GlassCard {
    VStack(alignment: .leading) {
        Text("Glass Card")
            .font(AppFont.title)
        Text("Reusable glassmorphic component.")
            .foregroundColor(.secondary)
    }
}

4. 文本框组件(现代、简洁)

struct AppTextField: View {
    var title: String
    @Binding var text: String

    var body: some View {
        TextField(title, text: $text)
            .padding(.horizontal, 14)
            .padding(.vertical, 12)
            .background(.ultraThinMaterial)
            .clipShape(RoundedRectangle(cornerRadius: AppRadius.medium))
            .overlay(
                RoundedRectangle(cornerRadius: AppRadius.medium)
                    .stroke(AppColor.glassStroke)
            )
            .shadow(color: AppShadow.card.opacity(0.25), radius: 12, y: 6)
    }
}

使用方式

@State private var name = ""

AppTextField(title: "Name", text: $name)

5. Chip / Tag

struct Chip: View {
    let label: String
    let icon: String?

    var body: some View {
        HStack(spacing: 6) {
            if let icon { Image(systemName: icon) }
            Text(label)
        }
        .font(.caption)
        .padding(.horizontal, 12)
        .padding(.vertical, 8)
        .background(.ultraThinMaterial)
        .clipShape(Capsule())
        .overlay(Capsule().stroke(AppColor.glassStroke))
    }
}

示例

HStack {
    Chip(label: "SwiftUI", icon: "swift")
    Chip(label: "Design", icon: "paintbrush")
}

6. 浮动面板(可复用的底部弹出顶部区域)

struct FloatingPanel: View {
    @ViewBuilder let content: () -> Content

    var body: some View {
        VStack(spacing: 0) {
            Capsule()
                .fill(AppColor.glassStroke)
                .frame(width: 40, height: 6)
                .padding(.top, 10)

            content()
                .padding()
        }
        .background(.regularMaterial)
        .clipShape(RoundedRectangle(cornerRadius: AppRadius.large, style: .continuous))
        .shadow(color: .black.opacity(0.25), radius: 30, y: 14)
    }
}

7. 可复用的修饰符(强大工具!)

struct CardPadding: ViewModifier {
    func body(content: Content) -> some View {
        content
            .padding(20)
            .clipShape(RoundedRectangle(cornerRadius: AppRadius.large))
    }
}

extension View {
    func cardPadding() -> some View {
        modifier(CardPadding())
    }
}

修饰符让你的视图保持简洁且具声明式风格。

8. 推荐的文件夹结构

Design/
│  Colors.swift
│  Radii.swift
│  Shadows.swift
│  Typography.swift

Components/
│  Buttons/
│  Cards/
│  TextFields/
│  Panels/
│  Chips/
│  Modifiers/

一切清晰,一切可扩展。

结束语

SwiftUI 组件库能为你带来:

  • 一致的设计
  • 更快的迭代速度
  • 可复用的构建块
  • 可扩展的架构
  • 更容易的团队上手
  • 更精致的 UI

这就是从“构建界面” → “构建系统”的转变方式。

Back to Blog

相关文章

阅读更多 »