主题引擎
Narrator Android · ThemeEngine 单例 · 8 内置主题 · 16 色 ThemeColors 数据模型
Narrator 实现了运行时主题引擎,允许用户在应用运行时切换色彩主题并持久化。
主题数据由 ThemeEngine 单例管理,对应 Web 端 themeService.ts。
内置主题从 assets/themes/list.json + colors.json 加载,
所有持久化经 ThemeStorageManager 按主题 ID 统一管理。
1. 8 个内置主题
主题列表来自 assets/themes/list.json,每个主题对应 colors.json 中一条 16 色配色:
| ID | 名称 | 主色 primary | 强调色 accent | 背景 background | 预览 |
|---|---|---|---|---|---|
Th_0001 | 默认 | #F97316 橙 | #B9232C 红 | #FFF7ED | 暖白 |
Th_0002 | 薰衣草 | #8B5CF6 紫 | #A78BFA | #F8FAFC | 淡紫 |
Th_0003 | 海洋 | #0EA5E9 蓝 | #38BDF8 | #F0F9FF | 淡蓝 |
Th_0004 | 森林 | #10B981 绿 | #34D399 | #F0FDF4 | 浅绿 |
Th_0005 | 暮色 | #F97316 橙 | #FB923C | #FFF7ED | 暖白 |
Th_0006 | 夜阑 | #1E293B 深灰 | #475569 | #0F172A | 深蓝黑(暗色) |
Th_0007 | 樱花 | #EC4899 粉 | #F472B6 | #FDF2F8 | 淡粉 |
Th_0008 | 抹茶 | #65A30D 黄绿 | #84CC16 | #F7FEE7 | 浅黄绿 |
#0F172A、文字 #F1F5F9、
旁白色 narrator 改为 #A78BFA、导演色 director 改为 #FBBF24,与其他亮色主题形成日/夜对照。
👉 前往主题调色盘 查看每个主题的完整 16 色板交互预览。
2. 数据模型
2.1 ThemeColors — 16 色数据类
文件:theme/ThemeColors.java | 对应 Web types/theme.ts ThemeColors
提供 14 / 15 / 16 色三个重载构造:14 色构造中 labelText 由 #475569 默认、buttonText 默认白色;16 色构造完整指定。
另有静态工具 midpointWithBlack(hex):取某颜色与黑色的中值,用于推算暗色背景。
2.2 ThemeJSON 示例(colors.json 条目)
每个主题在 assets/themes/colors.json 中的完整 16 色定义(以 Th_0001 为例):
2.3 list.json — 主题清单
3. ThemeEngine 单例
文件:theme/ThemeEngine.java | 对应 Web themeService.ts
- 构造时调用
loadBuiltinThemesFromJson()(读 assets/themes)+loadCustomThemesFromStorage()。 activeThemeId由ThemeStorageManager.getActiveThemeId()提供,缺失时回退Th_0001。- 当 assets 读取失败,硬编码注入
Th_0001「默认」作为兜底。
3.1 ThemePreset 预设数据类
4. 存储位置
| 路径 / 键 | 用途 |
|---|---|
assets/themes/list.json | 内置主题清单(id / name / preview 渐变) |
assets/themes/colors.json | 每个主题的 16 色 ThemeColors 定义 |
SharedPreferences("carrot_theme") | 当前激活主题 ID(键 active_theme,默认 Th_0001) |
ThemeStorageManager | 统一管理自定义主题的持久化与激活 ID |
5. 主题应用流程
启动阶段(MainActivity.applySavedTheme()):
ThemeEngine.loadActiveColors(this)取激活主题配色;为空时读SharedPreferences中的active_theme,再从引擎预设表反查颜色。- 设置状态栏 / 导航栏 / DecorView 背景为
colors.background。 - 预初始化
ThemeColorsUtil.applyColors(this, colors),供后续 Fragment 读取。
渲染阶段(MainActivity.applyDynamicThemeColors()):将主题色应用到顶部栏、底部导航、抽屉与指示条(详见 导航-动态主题配色)。
切换阶段(UiFragment):用户点击主题卡片 → ThemeEngine 切换 → 写入 SharedPreferences → 各 View 通过 ThemeColorsUtil 动态应用。
narrator(#8B5CF6 紫,演绎/剧本叙述用)与 director(#F59E0B 金,导演决策标签)是 Narrator 区别于通用主题的两条专属色。
夜阑主题把两者改为 #A78BFA 与 #FBBF24 以适配深色背景。
6. 支撑工具类
| 类 | 职责 |
|---|---|
theme/ThemeStorageManager | 自定义主题 suspenss持久化、激活主题 ID 读写 |
util/ThemeColorsUtil | 缓存当前 ThemeColors,对外提供 get(ctx) 与各色 int 取值(primary / textPrimary / surface / sidebarBg / onPrimary 等) |
util/ThemeApplier | 将 ThemeColors 应用到指定 View / 控件 |
util/ThemeColorsUtil + ThemeApplier | 演绎流中对话气泡按 narrator/director 着色 |
7. 规划 / 自定义主题
- 由
ThemeStorageManager管理用户自定义主题;自定义主题与 8 个内置主题一并通过getAllThemes()暴露给UiFragment。 - 设计文档(
docs/INDEX.md §8)规划了「风格 / 版式 / 导入」三 Tab 编辑器、ZIP 主题包导入(与 WebconfigService.importThemeZip()格式兼容)、以及导出分享。