SwiftUI 设计令牌与主题系统(生产规模)
Source: Dev.to
随着 SwiftUI 应用的规模扩大,UI 的一致性变得脆弱。你会开始看到:
- 略有差异的间距值
- 不统一的圆角半径
- 随处硬编码的随机颜色
- 暗黑模式的 bug
- 可访问性问题
- 痛苦的品牌重塑工作
解决方案是 设计令牌(design tokens)——所有视觉决策的唯一真相来源。本文展示了如何在 SwiftUI 中构建一个 可用于生产的设计令牌与主题系统,并实现干净的可扩展性。
🧠 设计令牌是什么?
设计令牌是 具名的、语义化的值,而不是原始数字。
错误示例
.padding(12)
.cornerRadius(16)
.foregroundColor(.blue)
正确示例
.padding(.md)
.cornerRadius(.card)
.foregroundStyle(.accent)
令牌表达意图,而非实现细节。
📦 1. 核心令牌类别
一个完整的系统通常包括:
- 间距(Spacing)
- 圆角(Radius)
- 排版(Typography)
- 颜色(Colors)
- 阴影/层次(Elevation)
- 动画(Animation)
- 不透明度(Opacity)
我们将逐一清晰定义。
📏 2. 间距令牌
enum Spacing {
static let xs: CGFloat = 4
static let sm: CGFloat = 8
static let md: CGFloat = 16
static let lg: CGFloat = 24
static let xl: CGFloat = 32
}
使用方式
.padding(Spacing.md)
🔲 3. 圆角令牌
enum Radius {
static let sm: CGFloat = 6
static let md: CGFloat = 12
static let lg: CGFloat = 20
static let card: CGFloat = 16
}
🎨 4. 颜色令牌(语义化,而非视觉)
绝不要这样写:
Color.blue
而应该这样:
enum AppColor {
static let background = Color("Background")
static let surface = Color("Surface")
static let accent = Color("Accent")
static let textPrimary = Color("TextPrimary")
static let textSecondary = Color("TextSecondary")
}
Assets 负责处理亮/暗模式、可访问性对比度以及品牌变更。
🔤 5. 排版令牌
enum AppFont {
static let title = Font.system(size: 28, weight: .bold)
static let headline = Font.system(size: 20, weight: .semibold)
static let body = Font.system(size: 16)
static let caption = Font.system(size: 13)
}
使用方式
Text("Title")
.font(AppFont.title)
🧊 6. 阴影与材质令牌
enum Elevation {
static let card = CGFloat(4)
static let modal = CGFloat(12)
}
.background(.ultraThinMaterial)
.shadow(radius: Elevation.card)
🕺 7. 动画令牌
enum Motion {
static let fast = Animation.easeOut(duration: 0.15)
static let standard = Animation.easeInOut(duration: 0.25)
static let slow = Animation.spring(response: 0.45)
}
🌗 8. 主题容器
创建一个主题模型:
struct AppTheme {
let colors: AppColor.Type
let spacing: Spacing.Type
let radius: Radius.Type
}
通过环境注入:
.environment(\.theme, currentTheme)
🔁 9. 支持多主题
enum ThemeKind {
case light
case dark
case highContrast
}
根据以下条件动态切换:
- 系统外观
- 可访问性设置
- 用户偏好
- A/B 测试
🧪 10. 预览变得强大
#Preview("Dark") {
ContentView()
.environment(\.theme, .dark)
}
设计验证瞬间完成。
🚀 最后思考
设计令牌系统为你带来:
- 一致性
- 可访问性
- 更快的迭代
- 更安全的重构
- 轻松的品牌重塑
- 更简洁的代码
- 更开心的设计师
一旦采用令牌,你将不再回头。