主题
明暗主题、语义化颜色令牌与排版。
应用支持系统 / 浅色 / 深色外观,带有应用内实时切换,还有一套随色彩方案自适应的 语义化颜色令牌,以及一份带类型的排版比例。三者合力,让换肤变成"查找并微调", 而非在内联十六进制值里翻找。本页覆盖这三部分,外加一份换肤清单。
外观切换
ThemeController(Core/Theme/)持有该选择,与 LocaleController 如出一辙:一个
@Observable,持久化到 AppPreferences,并暴露根部要应用的 SwiftUI 值。
@Observable @MainActor
final class ThemeController {
var selectedTheme: AppTheme { // .system | .light | .dark
didSet { preferences.themeTag = selectedTheme.rawValue }
}
var effectiveColorScheme: ColorScheme? { selectedTheme.effectiveColorScheme }
}AppTheme.system 映射为 nil(交给 iOS);.light/.dark 强制方案。RootView
在顶层应用一次:
.preferredColorScheme(theme.effectiveColorScheme)由于 ThemeController 是 @Observable,更改主题会立即重新渲染整棵树。ThemeToggle
组件(一个分段 Picker)就是现成的控件——放到任何地方即可;Me 标签页已在用它。
语义化颜色令牌
颜色以 .appXxx 静态访问器的形式定义在 Color+Tokens.swift 中,分为两类。
在视图里使用令牌——永远不要内联重算十六进制,这样换肤只需改动一个文件。
品牌与语义单例——浅色深色相同:
static let appTint = Color(hex: 0x007AFF)
static let appDestructive = Color(hex: 0xFF3B30)
static let appGreen = Color(hex: 0x10B981)自适应令牌——通过 Color(light:dark:) 按色彩方案解析,其内部封装了一个
UIColor { trait in … }:
static let appGroupedBg = Color(light: 0xF2F2F7, dark: 0x000000)
static let appGroupedSurface = Color(light: 0xFFFFFF, dark: 0x1C1C1E)
static let appSeparator = Color(light: 0xC6C6C8, dark: 0x38383A)两个便捷初始化器支撑着它们(init(hex:) 与 init(light:dark:)),因此新增一个令牌
只是一行代码。整套配色遵循 iOS 系统颜色约定(分组背景、分隔线、标签层级),移植自
Expo 原版的 lib/theme.ts。
AccentColor 是例外——它位于 Assets.xcassets/AccentColor.colorset,而非代码
中,因此设计师无需重新编译就能给应用的强调色换色。其余一切都定义在
Color+Tokens.swift 里。
排版
Typography.swift 用一套命名比例扩展了 Font,封装系统字体。优先用这些,而非
.font(.system(size:)),以保持动态字体与深色模式对比度的一致:
| 令牌 | 尺寸 / 字重 | 用途 |
|---|---|---|
.appLargeTitle | 34 bold | Home 精选标题 |
.appTitle | 28 bold | 内容内的屏幕标题 |
.appTitle2 | 22 semibold | 卡片 / 分区标题 |
.appHeadline | 17 semibold | 行主文本 |
.appBody | 15 regular | 卡片 / 列表正文 |
.appCallout | 14 regular | 副标题、辅助文本 |
.appCaption | 12 regular | 元数据 |
.appOverline | 12 semibold | 大写分区眉标(SectionHeader) |
Text("Today").font(.appTitle2)换肤清单
把模板变成你自己的:
强调色 → 给 Assets.xcassets/AccentColor.colorset 换色(浅色 + 深色两种外观)。
品牌令牌 → 编辑 Color+Tokens.swift 中的单例(appTint、appGreen 等)。若你的
配色不是 iOS 灰调,再调整自适应表面令牌。
字体 → 在 Typography.swift 中把系统字体换成自定义字族(一个文件,所有调用点随之
生效)。
应用图标 → 替换 Assets.xcassets/AppIcon.appiconset,以及启动资源
LaunchLogo / LaunchBackground。
显示名与 bundle id → 在 target 的构建设置中设置 PRODUCT_NAME(驱动
CFBundleName)和 bundle 标识符(目前为 com.soarstarter.SoarStarterSwift)。见
App Store 发布。
边做边预览两种方案——Xcode 的 #Preview 与画布的色彩方案切换,或在模拟器中运行并
切换 设置 → 开发者 → 深色外观。每个自适应令牌都有深色取值;硬编码的十六进制会在
某一种方案下露馅。
