Files
AtomUI/docs/Core/ThemeSystem/ThemeCustomizationGuide.md
T

627 lines
23 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AtomUI 主题定制 — 开发者指南
> 本文档面向 **AtomUI 应用开发者**,提供主题定制的完整实践指南:从全局主题配置到局部覆盖,从 Shared Token 修改到组件级 Token 定制。配合 Gallery 示例代码进行说明。如需了解底层原理,请参阅 [ThemeCustomizationPrinciples.md](ThemeCustomizationPrinciples.md)。
---
## 1. 快速开始:主题定制能力概览
AtomUI 提供以下四种主题定制方式,按作用范围从大到小排列:
| 定制方式 | 作用范围 | 配置方式 | 典型场景 |
|---------|---------|---------|---------|
| **全局主题 XML** | 整个应用 | XML 定义文件 | 品牌主色、全局圆角、全局字号 |
| **全局 Shared Token 覆盖** | `ThemeConfigProvider` 子树 | AXAML `SharedTokenSetters` | 页面区域使用暗色主题 |
| **组件级 Token 覆盖** | 特定组件类型 | AXAML `ControlTokenInfoSetters` | 让所有 Button 使用绿色主色 |
| **算法切换** | `ThemeConfigProvider` 子树 | AXAML `Algorithms` | 局部暗色/紧凑模式 |
---
## 2. 修改全局 Shared Token
### 2.1 在 AXAML 中使用 ThemeConfigProvider
最常见的定制方式是通过 `ThemeConfigProvider` 修改 Seed Token。修改一个 Seed Token(如 `ColorPrimary`),所有由它派生的梯度 Token 会自动重新计算。
```xml
<atom:ThemeConfigProvider>
<atom:ThemeConfigProvider.SharedTokenSetters>
<!-- Seed Token,影响范围大 -->
<atom:TokenSetter Key="ColorPrimary" Value="#00b96b" />
<atom:TokenSetter Key="BorderRadius" Value="2" />
<!-- Map/Alias Token,影响范围小 -->
<atom:TokenSetter Key="ColorBgContainer" Value="#f6ffed" />
</atom:ThemeConfigProvider.SharedTokenSetters>
<!-- 此范围内的所有控件都使用修改后的 Token -->
<WrapPanel>
<atom:Button ButtonType="Primary">Primary Button</atom:Button>
<atom:Button>Default Button</atom:Button>
</WrapPanel>
</atom:ThemeConfigProvider>
```
**效果**:`ThemeConfigProvider` 内的按钮会使用绿色(`#00b96b`)作为主色,圆角为 2px,背景色为浅绿色。`ThemeConfigProvider` 外的控件不受影响。
### 2.2 常用 Seed Token
| Token 名称 | 类型 | 默认值 | 说明 |
|-----------|------|--------|------|
| `ColorPrimary` | `Color` | `#1677ff` | 品牌主色,影响所有主色系梯度 |
| `ColorSuccess` | `Color` | `#52c41a` | 成功色 |
| `ColorWarning` | `Color` | `#faad14` | 警戒色 |
| `ColorError` | `Color` | `#ff4d4f` | 错误色 |
| `ColorInfo` | `Color` | `#1677ff` | 信息色 |
| `FontSize` | `double` | `14` | 基准字号,影响所有字号梯度 |
| `BorderRadius` | `CornerRadius` | `6` | 基础圆角 |
| `SizeUnit` | `double` | `4` | 尺寸变化单位 |
| `SizeStep` | `double` | `4` | 尺寸步长 |
| `ControlHeight` | `double` | `32` | 基础控件高度 |
| `LineWidth` | `double` | `1` | 基础线宽 |
| `EnableMotion` | `bool` | `true` | 是否启用动画 |
> **提示**:完整的 Token 列表请参考 [TokenArchitecture.md](TokenArchitecture.md)。修改 Seed Token 是最高效的定制方式 — 修改一个值即可级联影响数十个派生值。
---
## 3. 使用预设算法
### 3.1 算法切换
通过 `Algorithms` 属性可以切换主题算法,实现暗色或紧凑布局:
```xml
<!-- 暗色主题 -->
<atom:ThemeConfigProvider>
<atom:ThemeConfigProvider.Algorithms>
<x:String>Dark</x:String>
</atom:ThemeConfigProvider.Algorithms>
<Border Background="#2b2d30" Padding="20">
<StackPanel Orientation="Horizontal" Spacing="5">
<atom:LineEdit PlaceholderText="Please input" Width="200" />
<atom:Button ButtonType="Primary">Submit</atom:Button>
</StackPanel>
</Border>
</atom:ThemeConfigProvider>
```
### 3.2 可用算法
| 算法名称 | 说明 |
|---------|------|
| `Default` | 默认亮色算法(始终包含,无需显式声明) |
| `Dark` | 暗色算法 |
| `Compact` | 紧凑算法(更小的尺寸和间距) |
算法可以组合使用。例如同时启用暗色和紧凑:
```xml
<atom:ThemeConfigProvider>
<atom:ThemeConfigProvider.Algorithms>
<x:String>Dark</x:String>
<x:String>Compact</x:String>
</atom:ThemeConfigProvider.Algorithms>
<!-- 暗色 + 紧凑布局 -->
</atom:ThemeConfigProvider>
```
### 3.3 算法与 Token 覆盖组合
算法和 Token 覆盖可以同时使用:
```xml
<atom:ThemeConfigProvider>
<atom:ThemeConfigProvider.Algorithms>
<x:String>Dark</x:String>
</atom:ThemeConfigProvider.Algorithms>
<atom:ThemeConfigProvider.SharedTokenSetters>
<atom:TokenSetter Key="ColorPrimary" Value="#00b96b" />
</atom:ThemeConfigProvider.SharedTokenSetters>
<!-- 暗色主题 + 绿色主色 -->
</atom:ThemeConfigProvider>
```
---
## 4. 修改组件 Token
### 4.1 组件级 Shared Token 覆盖
通过 `ControlTokenInfoSetters` 可以修改特定组件消费的 Shared Token,不影响其他组件:
```xml
<atom:ThemeConfigProvider>
<atom:ThemeConfigProvider.ControlTokenInfoSetters>
<!-- 只修改 Button 的主色 -->
<atom:ControlTokenInfoSetter TokenId="Button" EnableAlgorithm="True">
<atom:TokenSetter Key="ColorPrimary" Value="#00b96b" />
</atom:ControlTokenInfoSetter>
<!-- 只修改 AddOnDecoratedBox(输入框装饰器)的主色 -->
<atom:ControlTokenInfoSetter TokenId="AddOnDecoratedBox" EnableAlgorithm="True">
<atom:TokenSetter Key="ColorPrimary" Value="#eb2f96" />
</atom:ControlTokenInfoSetter>
</atom:ThemeConfigProvider.ControlTokenInfoSetters>
<StackPanel Orientation="Horizontal" Spacing="5">
<atom:LineEdit PlaceholderText="Please input" Width="200" />
<atom:Button ButtonType="Primary">Submit</atom:Button>
</StackPanel>
</atom:ThemeConfigProvider>
```
**效果**:Button 使用绿色主色,输入框装饰使用粉色主色,其他控件保持全局默认。
### 4.2 EnableAlgorithm 的作用
`EnableAlgorithm` 控制覆盖的 Shared Token 是否经过算法重新派生:
| `EnableAlgorithm` | 行为 | 适用场景 |
|---|---|---|
| `True` | 修改 `ColorPrimary` 后,`ColorPrimaryHover`、`ColorPrimaryBg` 等梯度色自动重算 | 需要完整色系联动时 |
| `False`(默认) | 只有被显式修改的 Token 值变化,其他保持全局值 | 精确控制单个值时 |
**对比示例(来自 Gallery):**
```xml
<!-- EnableAlgorithm=True:修改 ColorPrimary 后 Hover/Active 等梯度色自动联动 -->
<atom:ControlTokenInfoSetter TokenId="Button" EnableAlgorithm="True">
<atom:TokenSetter Key="ColorPrimary" Value="#00b96b" />
</atom:ControlTokenInfoSetter>
<!-- EnableAlgorithm=False:只有 ColorPrimary 本身变化,Hover 等保持默认 -->
<atom:ControlTokenInfoSetter TokenId="Button">
<atom:TokenSetter Key="ColorPrimary" Value="#00b96b" />
</atom:ControlTokenInfoSetter>
```
### 4.3 组件自身 Token(ControlTokenSetter)
要修改组件自身的专属 Token(非 Shared Token),使用 `ControlTokenSetter`:
```xml
<atom:ControlTokenInfoSetter TokenId="Button">
<!-- 修改组件消费的 Shared Token -->
<atom:TokenSetter Key="ColorPrimary" Value="#00b96b" />
<!-- 修改组件自身的专属 Token -->
<atom:ControlTokenSetter Key="PaddingInline" Value="20" />
</atom:ControlTokenInfoSetter>
```
> **注意**:`TokenSetter` 和 `ControlTokenSetter` 是不同的类型。`TokenSetter` 用于 Shared Token(Seed/Map/Alias),`ControlTokenSetter` 用于组件自身的 Component Token。
### 4.4 常见的 TokenId
`TokenId` 对应组件 Token 类中的 `const string ID`。常见值:
| TokenId | 对应组件 |
|---------|---------|
| `Button` | 按钮 |
| `LineEdit` | 单行输入框 |
| `AddOnDecoratedBox` | 输入框装饰器 |
| `CheckBox` | 复选框 |
| `Radio` | 单选按钮 |
| `Select` | 选择器 |
| `Tag` | 标签 |
| `Alert` | 警告提示 |
| `Badge` | 徽标 |
| `Tabs` | 标签页 |
> 要查看某个组件的 TokenId,请查看对应的 `*Token.cs` 文件中的 `public const string ID` 常量。
---
## 5. 嵌套主题
### 5.1 基本嵌套
`ThemeConfigProvider` 可以任意层级嵌套,每层定义自己的 Token 覆盖:
```xml
<atom:ThemeConfigProvider>
<atom:ThemeConfigProvider.SharedTokenSetters>
<atom:TokenSetter Key="ColorPrimary" Value="#1677ff" />
</atom:ThemeConfigProvider.SharedTokenSetters>
<Border Padding="20">
<StackPanel Orientation="Horizontal" Spacing="5">
<!-- 使用 #1677ff 蓝色 -->
<atom:Button ButtonType="Primary">Theme 1</atom:Button>
<atom:ThemeConfigProvider>
<atom:ThemeConfigProvider.SharedTokenSetters>
<atom:TokenSetter Key="ColorPrimary" Value="#00b96b" />
</atom:ThemeConfigProvider.SharedTokenSetters>
<!-- 使用 #00b96b 绿色 -->
<atom:Button ButtonType="Primary">Theme 2</atom:Button>
</atom:ThemeConfigProvider>
</StackPanel>
</Border>
</atom:ThemeConfigProvider>
```
### 5.2 典型场景
- **侧边栏暗色**:主内容区使用亮色,侧边栏嵌套暗色 `ThemeConfigProvider`。
- **卡片高亮**:某张卡片使用不同的品牌色突出显示。
- **表单区域**:表单区域使用紧凑布局,其他区域保持默认。
---
## 6. 全局主题 XML 定义文件
### 6.1 创建自定义主题文件
创建 XML 文件(如 `MyBrand.xml`):
```xml
<?xml version="1.0" encoding="UTF-8"?>
<Theme Name="My Brand Theme" IsDefault="false">
<Algorithms>Default</Algorithms>
<SharedTokens>
<Token Name="ColorPrimary" Value="#722ed1" />
<Token Name="ColorSuccess" Value="#13c2c2" />
<Token Name="BorderRadius" Value="8" />
<Token Name="FontSize" Value="16" />
</SharedTokens>
<ControlTokens>
<ControlToken Id="Button" EnableAlgorithm="true">
<Token Name="ColorPrimary" Value="#722ed1" IsShared="true" />
</ControlToken>
</ControlTokens>
</Theme>
```
### 6.2 XML Schema 参考
**`<Theme>` 根元素:**
| 属性 | 必填 | 说明 |
|------|------|------|
| `Name` | 是 | 主题显示名称 |
| `IsDefault` | 是 | 是否为默认主题(`true`/`false`) |
**`<Algorithms>` 元素:**
- 内容为逗号分隔的算法名:`Default`、`Dark`、`Compact`。
- 示例:`<Algorithms>Default,Dark</Algorithms>`
**`<SharedTokens>` 子元素 `<Token>`:**
| 属性 | 必填 | 说明 |
|------|------|------|
| `Name` | 是 | Token 属性名(如 `ColorPrimary`) |
| `Value` | 是 | Token 值(字符串格式,自动转换) |
**`<ControlTokens>` → `<ControlToken>` 子元素:**
| 属性 | 必填 | 说明 |
|------|------|------|
| `Id` | 是 | 组件 Token ID(如 `Button`) |
| `EnableAlgorithm` | 否 | 是否启用算法派生(默认 `false`) |
**`<ControlToken>` 内的 `<Token>`:**
| 属性 | 必填 | 说明 |
|------|------|------|
| `Name` | 是 | Token 名称 |
| `Value` | 是 | Token 值 |
| `IsShared` | 否 | `true` 表示覆盖 Shared Token,`false`/省略 表示覆盖组件自身 Token |
### 6.3 注册自定义主题
将主题文件放置在以下位置之一:
1. **应用数据目录**:`{AppData}/{AppName}/Themes/MyBrand.xml` — 自动扫描。
2. **自定义目录**:通过 `ThemeManager.AddCustomThemePaths()` 注册。
3. **嵌入资源**:通过 `IThemeAssetPathProvider` 注册(库开发者模式)。
### 6.4 激活自定义主题
```csharp
this.UseAtomUI(builder =>
{
builder.UseDesktopControls();
builder.WithDefaultTheme("MyBrand"); // 使用主题文件名(不含扩展名)
});
```
---
## 7. 关键 API 参考
### 7.1 AXAML 类型与标记扩展
| 类型 | AXAML 标签 | 说明 |
|------|-----------|------|
| `ThemeConfigProvider` | `<atom:ThemeConfigProvider>` | 局部主题配置容器 |
| `TokenSetter` | `<atom:TokenSetter>` | Shared Token 设置器 |
| `ControlTokenSetter` | `<atom:ControlTokenSetter>` | 组件自身 Token 设置器 |
| `ControlTokenInfoSetter` | `<atom:ControlTokenInfoSetter>` | 组件级 Token 配置块 |
| `SharedTokenResourceExtension` | `{atom:SharedTokenResource ...}` | 全局 Token 资源引用 |
| `TokenResourceExtension<T>` | `{atom:ButtonTokenResource ...}` 等 | 组件 Token 资源引用 |
### 7.2 ThemeConfigProvider 属性
| 属性 | 类型 | 说明 |
|------|------|------|
| `Content` | `Control?` | 子内容(`[Content]` 标记,可直接写子控件) |
| `Algorithms` | `List<string>` | 算法列表(`"Default"`, `"Dark"`, `"Compact"`) |
| `SharedTokenSetters` | `List<TokenSetter>` | 全局 Token 覆盖列表 |
| `ControlTokenInfoSetters` | `List<ControlTokenInfoSetter>` | 组件级 Token 覆盖列表 |
### 7.3 TokenSetter 属性
| 属性 | 类型 | 说明 |
|------|------|------|
| `Key` | `string` | Token 属性名(如 `"ColorPrimary"`) |
| `Value` | `string` | Token 值(字符串格式) |
### 7.4 ControlTokenInfoSetter 属性
| 属性 | 类型 | 说明 |
|------|------|------|
| `TokenId` | `string` | 组件 Token ID |
| `EnableAlgorithm` | `bool` | 是否对覆盖的 Shared Token 启用算法派生(默认 `false`) |
| `Setters` | `List<TokenSetter>` | Token 设置器列表(支持 `TokenSetter` 和 `ControlTokenSetter`) |
### 7.5 C# API
```csharp
// IThemeManagerBuilder — 应用启动时配置
public interface IThemeManagerBuilder
{
void WithDefaultTheme(string themeId); // 设置默认主题
void WithDefaultFontFamily(FontFamily fontFamily); // 覆盖默认字体
void WithDefaultFontFamily(string fontFamily);
void WithThemeVariantCalculatorFactory(IThemeVariantCalculatorFactory factory); // 自定义算法工厂
}
// IThemeManager — 运行时访问
public interface IThemeManager
{
IReadOnlyCollection<ITheme> AvailableThemes { get; } // 所有可用主题
ITheme? ActivatedTheme { get; } // 当前激活的主题
bool IsDarkThemeMode { get; set; } // 暗色模式开关
bool IsCompactThemeMode { get; set; } // 紧凑模式开关
bool IsMotionEnabled { get; set; } // 动效开关
}
// ITheme — 主题实例
public interface ITheme
{
DesignToken SharedToken { get; } // 全局 SharedToken
IControlDesignToken? GetControlToken(string tokenId); // 获取组件 Token
}
```
---
## 8. Gallery 示例解读
Gallery 应用中的 `CustomizeThemeShowCase.axaml` 展示了四个典型的主题定制场景。
### 8.1 示例 1:修改 Design Token
```xml
<atom:ThemeConfigProvider>
<atom:ThemeConfigProvider.SharedTokenSetters>
<atom:TokenSetter Key="ColorPrimary" Value="#00b96b" />
<atom:TokenSetter Key="BorderRadius" Value="2" />
<atom:TokenSetter Key="ColorBgContainer" Value="#f6ffed" />
</atom:ThemeConfigProvider.SharedTokenSetters>
<WrapPanel>
<atom:Button ButtonType="Primary">Primary Button</atom:Button>
<atom:Button>Default Button</atom:Button>
</WrapPanel>
</atom:ThemeConfigProvider>
```
**要点**:
- `ColorPrimary` 是 Seed Token,修改后所有主色系梯度自动联动。
- `BorderRadius` 是 Seed Token,修改后所有圆角梯度自动联动。
- `ColorBgContainer` 是 Alias Token,只影响容器背景色这一个值。
### 8.2 示例 2:使用预设算法
```xml
<atom:ThemeConfigProvider>
<atom:ThemeConfigProvider.Algorithms>
<x:String>Dark</x:String>
</atom:ThemeConfigProvider.Algorithms>
<Border Background="#2b2d30" Padding="20">
<StackPanel Orientation="Horizontal" Spacing="5">
<atom:LineEdit PlaceholderText="Please input" Width="200" />
<atom:Button ButtonType="Primary">Submit</atom:Button>
</StackPanel>
</Border>
</atom:ThemeConfigProvider>
```
**要点**:
- `Algorithms` 列表中添加 `"Dark"` 即可切换到暗色算法。
- 暗色算法会自动反转色彩体系:浅色背景变深色,深色文字变浅色。
- 外层 `Border` 设置深色背景以匹配暗色主题。
### 8.3 示例 3:定制组件 Token
```xml
<!-- EnableAlgorithm=True:自动派生梯度色 -->
<atom:ThemeConfigProvider>
<atom:ThemeConfigProvider.ControlTokenInfoSetters>
<atom:ControlTokenInfoSetter TokenId="Button" EnableAlgorithm="True">
<atom:TokenSetter Key="ColorPrimary" Value="#00b96b" />
</atom:ControlTokenInfoSetter>
<atom:ControlTokenInfoSetter TokenId="AddOnDecoratedBox" EnableAlgorithm="True">
<atom:TokenSetter Key="ColorPrimary" Value="#eb2f96" />
</atom:ControlTokenInfoSetter>
</atom:ThemeConfigProvider.ControlTokenInfoSetters>
<StackPanel Orientation="Horizontal" Spacing="5">
<atom:LineEdit PlaceholderText="Please input" Width="200" />
<atom:Button ButtonType="Primary">Submit</atom:Button>
</StackPanel>
</atom:ThemeConfigProvider>
<!-- EnableAlgorithm=False:直接覆盖,不派生 -->
<atom:ThemeConfigProvider>
<atom:ThemeConfigProvider.ControlTokenInfoSetters>
<atom:ControlTokenInfoSetter TokenId="Button">
<atom:TokenSetter Key="ColorPrimary" Value="#00b96b" />
</atom:ControlTokenInfoSetter>
</atom:ThemeConfigProvider.ControlTokenInfoSetters>
...
</atom:ThemeConfigProvider>
```
**要点**:
- 不同组件可以使用不同的主色,互不影响。
- `EnableAlgorithm="True"` 时 Hover/Active 等交互色会自动联动。
### 8.4 示例 4:嵌套主题
```xml
<atom:ThemeConfigProvider>
<atom:ThemeConfigProvider.SharedTokenSetters>
<atom:TokenSetter Key="ColorPrimary" Value="#1677ff" />
</atom:ThemeConfigProvider.SharedTokenSetters>
<StackPanel Orientation="Horizontal" Spacing="5">
<atom:Button ButtonType="Primary">Theme 1</atom:Button>
<atom:ThemeConfigProvider>
<atom:ThemeConfigProvider.SharedTokenSetters>
<atom:TokenSetter Key="ColorPrimary" Value="#00b96b" />
</atom:ThemeConfigProvider.SharedTokenSetters>
<atom:Button ButtonType="Primary">Theme 2</atom:Button>
</atom:ThemeConfigProvider>
</StackPanel>
</atom:ThemeConfigProvider>
```
**要点**:
- "Theme 1" 按钮使用外层蓝色(`#1677ff`)。
- "Theme 2" 按钮使用内层绿色(`#00b96b`)。
- 嵌套层的 Token 不继承父层 — 未设置的 Token 使用框架默认值。
---
## 9. 运行时主题切换
### 9.1 全局暗色/紧凑模式切换
通过 `IThemeManager` 可以在运行时切换暗色模式和紧凑模式:
```csharp
var themeManager = AvaloniaLocator.Current.GetRequiredService<IThemeManager>();
// 切换暗色模式
themeManager.IsDarkThemeMode = true;
// 切换紧凑模式
themeManager.IsCompactThemeMode = true;
// 组合:暗色 + 紧凑
themeManager.IsDarkThemeMode = true;
themeManager.IsCompactThemeMode = true;
```
### 9.2 切换主题变体
```csharp
// 切换到特定主题变体
Application.Current.RequestedThemeVariant =
Theme.BuildThemeVariant("DaybreakBlue", new List<ThemeAlgorithm>
{
ThemeAlgorithm.Default,
ThemeAlgorithm.Dark
});
```
### 9.3 禁用动画
```csharp
var themeManager = AvaloniaLocator.Current.GetRequiredService<IThemeManager>();
themeManager.IsMotionEnabled = false;
```
或在 AXAML 中通过 Token 覆盖:
```xml
<atom:ThemeConfigProvider>
<atom:ThemeConfigProvider.SharedTokenSetters>
<atom:TokenSetter Key="EnableMotion" Value="false" />
</atom:ThemeConfigProvider.SharedTokenSetters>
<!-- 此范围内的控件动画被禁用 -->
</atom:ThemeConfigProvider>
```
---
## 10. 常见问题与注意事项
### 10.1 Token 名称必须精确匹配
`TokenSetter` 的 `Key` 必须与 `DesignToken` 类中的**属性名**完全一致(PascalCase)。常见错误:
```xml
<!-- ❌ 错误:使用了 camelCase -->
<atom:TokenSetter Key="colorPrimary" Value="#00b96b" />
<!-- ✅ 正确:使用 PascalCase -->
<atom:TokenSetter Key="ColorPrimary" Value="#00b96b" />
```
### 10.2 值类型自动转换
Token 值在 XML/AXAML 中以字符串形式提供,AtomUI 内置的 `ITokenValueConverter` 会自动转换为目标类型:
| 字符串格式 | 转换为 | 示例 |
|-----------|--------|------|
| `#1677ff` | `Color` | 十六进制颜色 |
| `red`, `blue` | `Color` | 颜色名称 |
| `14` | `double` | 数值 |
| `6` | `CornerRadius` | 圆角(统一四角) |
| `true` / `false` | `bool` | 布尔值 |
| `1` | `double` (LineWidth) | 线宽 |
### 10.3 ThemeConfigProvider 的独立性
每个 `ThemeConfigProvider` 都是**独立计算**的 — 它不继承父级 `ThemeConfigProvider` 的 Token 值。未显式设置的 Token 使用 `DesignToken` 类中的代码默认值(即 Ant Design 5.0 标准值)。
如果你希望只修改某几个 Token 而保持其他不变,直接设置那几个即可 — 其他 Token 会使用标准默认值。
### 10.4 性能考虑
- **`ThemeConfigProvider` 的计算开销**:每个 `ThemeConfigProvider` 实例会创建独立的 `DesignToken` 和所有注册的 `ControlDesignToken` 实例,并走完整的算法推导流程。在页面上大量使用 `ThemeConfigProvider` 可能有性能影响。
- **建议**:尽量在较高层级使用 `ThemeConfigProvider`,避免在列表项等重复元素中使用。
- **组件级覆盖** 相对轻量,因为只 Clone 和重算目标组件的 SharedToken。
### 10.5 TokenSetter vs ControlTokenSetter
在 `ControlTokenInfoSetter` 内部,正确区分两种 Setter:
| Setter 类型 | 用于 | 示例 |
|------------|------|------|
| `<atom:TokenSetter>` | 覆盖组件消费的 Shared Token | `ColorPrimary`, `FontSize`, `BorderRadius` |
| `<atom:ControlTokenSetter>` | 覆盖组件自身的 Component Token | `PaddingInline`, `PrimaryColor`, `DangerColor` |
### 10.6 多主题切换与持久化
AtomUI 的 `ThemePool` 包含所有已发现主题的算法组合变体。切换主题时:
1. 目标主题会按需加载(首次激活时加载)。
2. 已加载的主题会缓存在 `ThemePool` 中。
3. 主题切换通过 Avalonia 的 `ThemeDictionaries` 机制实现,无需重启。
如需持久化用户的主题选择,应用层需要自行保存主题 ID 和算法组合,并在下次启动时通过 `WithDefaultTheme()` 恢复。
---
## 11. 文档索引
| 文档 | 描述 |
|------|------|
| [Overview.md](Overview.md) | 主题系统总览 |
| [TokenArchitecture.md](TokenArchitecture.md) | Design Token 四层架构详解 |
| [ThemeAlgorithm.md](ThemeAlgorithm.md) | 主题算法与调色板生成 |
| [ThemeManagement.md](ThemeManagement.md) | 主题管理器与主题生命周期 |
| [TokenResourceBinding.md](TokenResourceBinding.md) | Token 资源绑定与 Source Generator |
| [ThemeCustomizationPrinciples.md](ThemeCustomizationPrinciples.md) | 主题自定义原理说明(本指南的姐妹篇) |
| [ThemeCustomizationGuide.md](ThemeCustomizationGuide.md) | 本文件 — 主题定制开发者指南 |