Files
LanMountainDesktop/docs/archive/Plugins develop/02-核心概念与原理/04-外观与主题系统.md
2026-06-08 03:54:33 +08:00

309 lines
7.4 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.
# 04-外观与主题系统
阑山桌面支持暗色/浅色主题切换,插件需要适配宿主的视觉风格,保持界面一致性。
---
## 🎨 主题系统概述
阑山桌面使用 Avalonia UI 的主题系统,支持:
- **浅色主题** - 明亮背景,深色文字
- **深色主题** - 深色背景,浅色文字
- **跟随系统** - 自动匹配 Windows/macOS 主题
---
## 🌗 检测当前主题
### 在组件中检测
```csharp
using Avalonia;
using Avalonia.Styling;
public class MyWidget : Border
{
public MyWidget(PluginDesktopComponentContext context)
{
// 检测当前主题
var isDark = Application.Current?.ActualThemeVariant == ThemeVariant.Dark;
// 根据主题设置颜色
UpdateTheme(isDark);
// 监听主题变化
if (Application.Current != null)
{
Application.Current.ActualThemeVariantChanged += (_, _) =>
{
var newIsDark = Application.Current.ActualThemeVariant == ThemeVariant.Dark;
UpdateTheme(newIsDark);
};
}
}
private void UpdateTheme(bool isDark)
{
Background = new SolidColorBrush(
isDark ? Color.Parse("#FF1E1E1E") : Color.Parse("#FFFFFFFF"));
Foreground = new SolidColorBrush(
isDark ? Colors.White : Colors.Black);
}
}
```
---
## 📐 圆角系统
插件必须使用宿主提供的圆角系统,确保与内置组件视觉一致。
### 为什么插件不能使用 XAML 资源
插件运行在独立的 `AssemblyLoadContext` 中,无法直接访问宿主的资源字典。因此 `{DynamicResource DesignCornerRadiusComponent}` 在插件 XAML 中无效。
### 使用代码设置圆角
```csharp
public class MyWidget : Border
{
public MyWidget(PluginDesktopComponentContext context)
{
// 方法 1使用预设推荐
CornerRadius = context.Appearance.ResolveCornerRadius(
PluginCornerRadiusPreset.Component);
// 方法 2带最小/最大值限制
CornerRadius = context.Appearance.ResolveCornerRadius(
PluginCornerRadiusPreset.Component,
minimum: new CornerRadius(8),
maximum: new CornerRadius(24));
// 方法 3自定义基础值应用全局缩放
CornerRadius = context.Appearance.ResolveScaledCornerRadius(
baseRadius: 16,
minimum: 8,
maximum: 32);
}
}
```
### 圆角预设
| 预设 | 默认值 | 用途 |
|-----|-------|------|
| `Micro` | 6px | 微小元素 |
| `Xs` | 12px | 小元素、图标容器 |
| `Sm` | 14px | 小卡片 |
| `Md` | 20px | 普通按钮/卡片 |
| `Lg` | 28px | 大面板 |
| `Xl` | 32px | 强调容器 |
| `Island` | 36px | 大型容器 |
| `Component` | 18px | **桌面组件标准** |
| `Default` | 自适应 | 根据尺寸自动计算 |
### 内部元素圆角
组件内部的卡片、按钮应使用更小的圆角:
```csharp
// 组件根容器 - 使用 Component 预设
CornerRadius = context.ResolveCornerRadius(PluginCornerRadiusPreset.Component);
// 内部卡片 - 使用 Md 预设
var innerCard = new Border
{
CornerRadius = context.ResolveCornerRadius(PluginCornerRadiusPreset.Md),
Background = new SolidColorBrush(Colors.LightGray)
};
// 按钮 - 使用 Sm 预设
var button = new Button
{
CornerRadius = context.ResolveCornerRadius(PluginCornerRadiusPreset.Sm)
};
```
---
## 🎨 颜色系统
### 推荐的颜色策略
```csharp
// 透明背景(推荐)- 让宿主壁纸透出
Background = new SolidColorBrush(Colors.Transparent);
// 毛玻璃效果
Background = new SolidColorBrush(Color.Parse(isDark ? "#40FFFFFF" : "#40000000"));
// 卡片背景
Background = new SolidColorBrush(Color.Parse(isDark ? "#FF2D2D2D" : "#FFFFFFFF"));
// 强调色(使用系统强调色)
var accentColor = Color.Parse("#FF0078D4"); // 阑山桌面主色调
```
### 文字颜色
```csharp
// 主要文字
Foreground = new SolidColorBrush(isDark ? Colors.White : Colors.Black);
// 次要文字
Foreground = new SolidColorBrush(isDark ? Color.Parse("#FFCCCCCC") : Color.Parse("#FF666666"));
// 禁用文字
Foreground = new SolidColorBrush(isDark ? Color.Parse("#FF666666") : Color.Parse("#FF999999"));
```
---
## 🔄 响应外观变化
### 订阅外观变化事件
```csharp
public class MyWidget : Border
{
public MyWidget(PluginDesktopComponentContext context)
{
// 订阅外观变化
context.Appearance.AppearanceChanged += (_, _) =>
{
UpdateAppearance();
};
// 初始化
UpdateAppearance();
}
private void UpdateAppearance()
{
// 重新应用圆角(用户可能调整了全局圆角设置)
var context = ...; // 获取 context
CornerRadius = context.Appearance.ResolveCornerRadius(
PluginCornerRadiusPreset.Component);
// 更新主题颜色
var isDark = Application.Current?.ActualThemeVariant == ThemeVariant.Dark;
UpdateThemeColors(isDark);
}
}
```
---
## 🧩 使用 FluentAvalonia 控件
推荐使用 FluentAvalonia 控件库,它们自动适配主题:
```xml
<Window xmlns:ui="using:FluentAvalonia.UI.Controls">
<ui:SettingsExpander Header="设置项">
<ui:SettingsExpander.IconSource>
<ui:FontIconSource Glyph="&#xE713;" />
</ui:SettingsExpander.IconSource>
</ui:SettingsExpander>
</Window>
```
### 常用 FluentAvalonia 控件
| 控件 | 用途 |
|-----|------|
| `SettingsExpander` | 设置项展开器 |
| `SettingsCard` | 设置卡片 |
| `ColorPicker` | 颜色选择器 |
| `NumberBox` | 数字输入框 |
| `ToggleSwitch` | 开关 |
---
## 💡 最佳实践
### 1. 始终使用透明背景
```csharp
// ✅ 好的做法
Background = new SolidColorBrush(Colors.Transparent);
// ❌ 避免硬编码背景色
Background = new SolidColorBrush(Colors.White);
```
### 2. 组件根容器必须使用 Component 圆角
```csharp
// ✅ 正确
CornerRadius = context.ResolveCornerRadius(PluginCornerRadiusPreset.Component);
// ❌ 错误 - 硬编码
CornerRadius = new CornerRadius(18);
```
### 3. 响应主题变化
```csharp
// ✅ 订阅变化事件
Application.Current.ActualThemeVariantChanged += OnThemeChanged;
// ❌ 只在构造函数中设置一次
```
### 4. 使用语义化颜色
```csharp
// ✅ 根据用途选择颜色
var primaryText = isDark ? Colors.White : Colors.Black;
var secondaryText = isDark ? Color.Parse("#FFCCCCCC") : Color.Parse("#FF666666");
// ❌ 避免随意使用颜色
var textColor = Color.Parse("#FF123456");
```
---
## 🐛 常见问题
### 问题 1圆角不生效
**原因:** 在 XAML 中使用 `{DynamicResource}`
**解决:** 在代码中设置圆角(见上文)
### 问题 2主题切换后颜色不对
**原因:** 没有订阅主题变化事件
**解决:** 添加 `ActualThemeVariantChanged` 事件处理
### 问题 3组件与内置组件风格不一致
**排查:**
1. 检查圆角是否使用 `PluginCornerRadiusPreset.Component`
2. 检查背景是否透明
3. 检查是否使用了 FluentAvalonia 控件
---
## 📚 参考资源
- [CORNER_RADIUS_SPEC.md](../../docs/CORNER_RADIUS_SPEC.md)
- [VISUAL_SPEC.md](../../docs/VISUAL_SPEC.md)
- [FluentAvalonia 文档](https://github.com/amwx/FluentAvalonia)
---
## 🎯 下一步
学习插件间通信:
👉 **[05-插件间通信](05-插件间通信.md)** - 与其他插件协作
---
*最后更新2026年4月*