XPThemeSize 是 XPFontSizeManage 的 2.0 演进:在「普通 / 大号」字号维度之上,增加浅色 / 深色外观维度,由 XPThemeSizeManager 统一解析为 XPThemeSnapshot,一次通知驱动 UI 刷新。
适用于关怀模式、无障碍、App 内「字体大小 + 深浅色」设置等场景。
1.x 用户: 继续使用
pod 'XPFontSizeManage'(已标记弃用)或迁移至XPThemeSize+Legacy子模块,见 从 1.0 迁移。
设计规格: docs/superpowers/specs/2026-05-26-xpthemesize-design.md
- 双维度:
appearance(light / dark / 跟随系统)×contentSize(normal / large) - 单一数据源:
XPThemeSizeManager.shared.currentSnapshot聚合颜色、字体、圆角等指标 - 模块化 Subspec:
Core/Theme/FontSize/UIKit/Legacy,按需集成 - 声明式资源:
MixFont、MixColor、MixedResource按当前 Snapshot 自动unfold() - 低侵入: UIKit Extension + 关联对象,无需子类化控件
- 1.0 兼容:
Legacy子模块保留XPFontSizeManager等 API
| 项目 | 版本 |
|---|---|
| iOS | 9.0+ |
| Swift | 5.0+ |
| Xcode | 建议 12+ |
# 新项目:UIKit = Theme + FontSize + 控件扩展
pod 'XPThemeSize/UIKit'
# 从 1.x 过渡:在 UIKit 基础上增加兼容层
pod 'XPThemeSize/Legacy'
# 按需精简
pod 'XPThemeSize/Core' # 仅 Manager + Snapshot
pod 'XPThemeSize/Theme' # 深浅色 + trait 监听(依赖 Core)
pod 'XPThemeSize/FontSize' # MixFont / XPFont(依赖 Core)多子模块合并安装(Example 用法):
pod 'XPThemeSize', :subspecs => ['Core', 'FontSize', 'Theme', 'UIKit', 'Legacy']git clone https://github.com/jamalping/XPFontSizeManage.git
cd XPFontSizeManage/Example
pod install
open XPFontSizeManage.xcworkspaceGitee:git clone https://gitee.com/jamalping/XPFontSizeManage.git
安装 Theme 或 UIKit 后,在启动时安装 trait 监听:
import XPThemeSize
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// ...
window?.makeKeyAndVisible()
if let window = window {
XPThemeSizeAppearanceObserver.install(on: window)
}
return true
}import XPThemeSize
let manager = XPThemeSizeManager.shared
// 字号(持久化)
manager.contentSize = .large
manager.switchContentSize()
// 外观偏好(持久化)
manager.appearancePreference = .dark // .system / .light / .dark
// 当前快照
let snap = manager.currentSnapshot
view.backgroundColor = snap.colors.background
label.font = snap.typography.font(for: .body)NotificationCenter.default.addObserver(
forName: XPThemeSizeManager.themeSizeDidChangeNotification,
object: nil,
queue: .main
) { _ in
let snap = XPThemeSizeManager.shared.currentSnapshot
// 刷新自定义 UI
}label.fontSize = MixFont(
normal: .systemFont(ofSize: 15),
other: .systemFont(ofSize: 22)
)
label.fontSize = XPFont(normal: .systemFont(ofSize: 15), 3)
button.xpControlNormalFont = MixFont(normal: .systemFont(ofSize: 15), other: .systemFont(ofSize: 22))
view.layer.xpCornerRadius = MixedResource(normal: 8, other: 20)
view.themeChangeCallback = { contentSize in
// contentSize: .normal | .large
}在 didFinishLaunching 最早注册;传 nil 恢复内置默认。
// 设计稿导出 [tokenName: UIColor](或自行解析 JSON/Plist)
XPThemeSizeManager.registerColorTokensProvider { appearance in
let table = DesignColorLoader.tokens(for: appearance)
let fallback = appearance == .dark ? XPColorTokens.defaultDark : XPColorTokens.defaultLight
// 标准字段映射后,其余 key 自动进 extra
return XPColorTokens.fromDesignTokens(table, mapping: .default, fallback: fallback)
}
// 使用:标准字段 + 设计扩展 token
let colors = XPThemeSizeManager.shared.currentSnapshot.colors
view.backgroundColor = colors.background
cardView.backgroundColor = colors.color(named: "card_bg")
// 或 colors.extra["card_bg"]
// 设计 key 与代码不一致时,改 mapping 即可:
let mapping = XPColorTokenMapping(
background: "page_bg",
textPrimary: "text_primary",
textSecondary: "text_secondary",
accent: "brand",
separator: "divider"
)
let appScale = XPTypographyScale(
body: XPStyleSizePair(normal: 16, large: 20),
title: XPStyleSizePair(normal: 18, large: 24),
headline: XPStyleSizePair(normal: 20, large: 28),
caption: XPStyleSizePair(normal: 12, large: 14)
)
XPThemeSizeManager.registerTypographyProvider { size in
XPTypography(contentSize: size, scale: appScale)
}注册后 currentSnapshot.colors / typography 使用自定义逻辑;色板或排版变化会触发 themeSizeDidChangeNotification。
内置默认:XPColorTokens.defaultLight / defaultDark,XPTypographyScale.default。
appearance(外观) × contentSize(内容尺寸)
.system → light|dark .normal | .large
↓
XPThemeSnapshot(颜色 / 字体 / 圆角等指标)
↓
themeSizeDidChangeNotification(去重后单次广播)
flowchart TB
subgraph App["宿主 App"]
Settings["设置页"]
UI["UILabel · UIButton · CALayer …"]
end
subgraph Core["Core"]
Mgr["XPThemeSizeManager"]
Snap["XPThemeSnapshot"]
end
subgraph Theme["Theme"]
Resolver["XPThemeAppearanceResolver"]
Observer["XPThemeSizeAppearanceObserver"]
Tokens["XPColorTokens"]
end
subgraph FontSize["FontSize"]
Mix["MixedResource · MixFont · XPFont"]
end
subgraph UIKitExt["UIKit"]
Ext["控件 Extension"]
NM["NotificationManager"]
end
subgraph Legacy["Legacy 可选"]
Shim["XPFontSizeManager shim"]
end
Settings --> Mgr
Mgr --> Snap
Theme --> Mgr
FontSize --> Mgr
UI --> Ext
Ext --> Mix
Ext --> NM
NM --> Mgr
Legacy --> Mgr
XPFontSizeManage/ # 仓库名保持不变
├── XPThemeSize.podspec # 2.0 主 Pod
├── XPFontSizeManage.podspec # 1.x(弃用说明)
├── Sources/
│ ├── Core/ # XPThemeSizeManager、Snapshot
│ ├── Theme/ # 外观解析、trait 监听、ColorTokens
│ ├── FontSize/ # MixedResource、XPFont
│ ├── UIKit/ # 控件扩展
│ └── Legacy/ # 1.x API 兼容
├── XPFontSizeManage.podspec # 1.0 已废弃(源码见 git tag 1.0.0)
└── Example/
| 已安装 | 缺失维度的默认 |
|---|---|
仅 FontSize |
appearance 固定 light |
仅 Theme |
contentSize 固定 normal |
UIKit(含 Theme + FontSize) |
用户配置 + 可跟随系统外观 |
| 1.0 | 2.0 |
|---|---|
import XPFontSizeManage |
import XPThemeSize |
pod 'XPFontSizeManage' |
pod 'XPThemeSize/UIKit' |
XPFontSizeManager.fontSize |
XPThemeSizeManager.shared.contentSize |
XPFontSizeManager.switchFontSize() |
XPThemeSizeManager.shared.switchContentSize() |
XPFontSizeManager.isLargeFont |
XPThemeSizeManager.shared.isLargeContent |
fontSizeDidChangeNotification |
themeSizeDidChangeNotification |
FontSize |
XPContentSize(或 Legacy 下仍可用 FontSize typealias) |
fontSizeChangeCallBack |
themeChangeCallback(参数为 XPContentSize) |
| 无深浅色 | appearancePreference + currentSnapshot.colors |
最小改动路径: 先增加 pod 'XPThemeSize/Legacy',仅替换 import 与 Pod 名,旧 API 仍可编译;再逐步改用 XPThemeSizeManager 与 Snapshot。
| Demo | 说明 |
|---|---|
| 主题与字号设置 | appearancePreference + contentSize + Snapshot 预览 |
| Label / TextField / TextView | fontSize、xp.fontSize、XPFont |
| UIButton | 分状态字体、颜色、imageEdgeInsets |
| UIView & CALayer | themeChangeCallback、圆角/边框 |
| 移除监听 | 动态绑定与 fontSize = nil |
| 1.0 兼容 API | XPFontSizeManager / FontSize |
| 类型 | 说明 |
|---|---|
XPThemeSizeManager |
单例:偏好读写、currentSnapshot、通知 |
XPThemeSnapshot |
当前生效主题快照 |
XPAppearance / XPAppearancePreference |
有效外观 / 用户偏好 |
XPContentSize |
.normal / .large |
MixFont / MixColor / MixedResource |
双态资源,unfold() 读 Snapshot |
XPThemeSizeAppearanceObserver |
窗口 trait → Manager 刷新 |
控件扩展与 1.0 基本一致,见 快速开始。
- 设置
fontSize或 Button 相关属性时自动注册themeSizeDidChangeNotification监听。 fontSize = nil或removeAllFontSizeObservers()可解除绑定。- Example「移除监听」页演示完整流程。
本库提供 App 内固定两档 字号(normal / large),与系统「辅助功能 → 更大字体」的 Dynamic Type 不同机制,可并存。MVP 不跟随系统 Dynamic Type;后续可在 spec 中扩展 contentSizePreference。
- 变更记录:CHANGELOG.md
- 2.0 版本号以 XPThemeSize.podspec 为准
- 1.x 维护见 XPFontSizeManage.podspec(已弃用,仅修复)
jamalping — [email protected]
基于 MIT License 发布。