主题引擎

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浅黄绿
🌙 夜阑主题(Th_0006)是唯一的内置暗色主题:背景 #0F172A、文字 #F1F5F9、 旁白色 narrator 改为 #A78BFA、导演色 director 改为 #FBBF24,与其他亮色主题形成日/夜对照。

👉 前往主题调色盘 查看每个主题的完整 16 色板交互预览。

2. 数据模型

2.1 ThemeColors — 16 色数据类

文件theme/ThemeColors.java | 对应 Web types/theme.ts ThemeColors

public class ThemeColors { public final String primary; // 主色 #F97316 public final String accent; // 强调色 #B9232C public final String background; // 背景 #FFF7ED public final String surface; // 卡片 #FFFDF5 public final String text; // 主文字 #0F172A public final String textSecondary; // 次文字 #475569 public final String textMuted; // 弱文字 #64748B public final String labelText; // 标签 #475569 public final String buttonText; // 按钮文 #FFFFFF public final String border; // 边框 #1E293B public final String danger; // 危险 #EF4444 public final String success; // 成功 #059669 public final String warning; // 警告 #D97706 public final String info; // 信息 #3B82F6 public final String narrator; // 旁白 #8B5CF6 public final String director; // 导演 #F59E0B }

提供 14 / 15 / 16 色三个重载构造:14 色构造中 labelText#475569 默认、buttonText 默认白色;16 色构造完整指定。

另有静态工具 midpointWithBlack(hex):取某颜色与黑色的中值,用于推算暗色背景。

2.2 ThemeJSON 示例(colors.json 条目)

每个主题在 assets/themes/colors.json 中的完整 16 色定义(以 Th_0001 为例):

{ "Th_0001": { "primary": "#F97316", "accent": "#B9232C", "background": "#FFF7ED", "surface": "#FFFDF5", "text": "#0F172A", "textSecondary": "#475569", "textMuted": "#64748B", "border": "#1E293B", "danger": "#EF4444", "success": "#059669", "warning": "#D97706", "info": "#3B82F6", "narrator": "#8B5CF6", "director": "#F59E0B", "buttonText": "#FFFFFF" } }

2.3 list.json — 主题清单

[ { "id": "Th_0001", "name": "默认", "previewStart": "#FFF7ED", "previewEnd": "#F5E6D3" }, { "id": "Th_0002", "name": "薰衣草", "previewStart": "#f5f3ff", "previewEnd": "#ede9fe" }, { "id": "Th_0003", "name": "海洋", "previewStart": "#f0f9ff", "previewEnd": "#e0f2fe" }, { "id": "Th_0004", "name": "森林", "previewStart": "#f0fdf4", "previewEnd": "#dcfce7" }, { "id": "Th_0005", "name": "暮色", "previewStart": "#fff7ed", "previewEnd": "#ffedd5" }, { "id": "Th_0006", "name": "夜阑", "previewStart": "#1e293b", "previewEnd": "#0f172a" }, { "id": "Th_0007", "name": "樱花", "previewStart": "#fdf2f8", "previewEnd": "#fce7f3" }, { "id": "Th_0008", "name": "抹茶", "previewStart": "#f7fee7", "previewEnd": "#ecfccb" } ]

3. ThemeEngine 单例

文件theme/ThemeEngine.java | 对应 Web themeService.ts

public class ThemeEngine { private static ThemeEngine instance; // 单例 private final Map<String,ThemePreset> builtinThemes; // 内置 private final Map<String,ThemePreset> customThemes; // 用户自定义 private String activeThemeId; public static synchronized ThemeEngine getInstance(Context ctx); public static synchronized ThemeEngine getInstance(); // 已持有实例时 public Map<String,ThemePreset> getAllThemes(); // 内置 + 自定义 public static ThemeColors loadActiveColors(Context ctx); // 给 MainActivity 用 }

3.1 ThemePreset 预设数据类

public static class ThemePreset { public final String id; public final String name; public final ThemeColors colors; public final String previewStart; // 渐变起色 public final String previewEnd; // 渐变幻色 }

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()):

渲染阶段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. 规划 / 自定义主题