mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-23 18:04:26 +08:00
feat.新增了插件开发文档
This commit is contained in:
308
docs/Plugins develop/02-核心概念与原理/04-外观与主题系统.md
Normal file
308
docs/Plugins develop/02-核心概念与原理/04-外观与主题系统.md
Normal file
@@ -0,0 +1,308 @@
|
||||
# 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="" />
|
||||
</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月*
|
||||
Reference in New Issue
Block a user