主题

明暗主题、语义化颜色令牌与排版。

应用支持系统 / 浅色 / 深色外观,带有应用内实时切换,还有一套随色彩方案自适应的 语义化颜色令牌,以及一份带类型的排版比例。三者合力,让换肤变成"查找并微调", 而非在内联十六进制值里翻找。本页覆盖这三部分,外加一份换肤清单。

外观切换

ThemeControllerCore/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:)),以保持动态字体与深色模式对比度的一致:

令牌尺寸 / 字重用途
.appLargeTitle34 boldHome 精选标题
.appTitle28 bold内容内的屏幕标题
.appTitle222 semibold卡片 / 分区标题
.appHeadline17 semibold行主文本
.appBody15 regular卡片 / 列表正文
.appCallout14 regular副标题、辅助文本
.appCaption12 regular元数据
.appOverline12 semibold大写分区眉标(SectionHeader
Text("Today").font(.appTitle2)

换肤清单

把模板变成你自己的:

强调色 → 给 Assets.xcassets/AccentColor.colorset 换色(浅色 + 深色两种外观)。

品牌令牌 → 编辑 Color+Tokens.swift 中的单例(appTintappGreen 等)。若你的 配色不是 iOS 灰调,再调整自适应表面令牌。

字体 → 在 Typography.swift 中把系统字体换成自定义字族(一个文件,所有调用点随之 生效)。

应用图标 → 替换 Assets.xcassets/AppIcon.appiconset,以及启动资源 LaunchLogo / LaunchBackground

显示名与 bundle id → 在 target 的构建设置中设置 PRODUCT_NAME(驱动 CFBundleName)和 bundle 标识符(目前为 com.soarstarter.SoarStarterSwift)。见 App Store 发布

边做边预览两种方案——Xcode 的 #Preview 与画布的色彩方案切换,或在模拟器中运行并 切换 设置 → 开发者 → 深色外观。每个自适应令牌都有深色取值;硬编码的十六进制会在 某一种方案下露馅。

相关页面

On this page