Files
2026-04-13 19:54:37 +08:00

394 lines
9.9 KiB
Markdown
Raw Permalink 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.
# 02-桌面组件系统
桌面组件Desktop Component是阑山桌面插件的核心功能。本文详细讲解组件系统的工作原理和开发方法。
---
## 🎯 什么是桌面组件
桌面组件是显示在阑山桌面上的可视化元素,用户可以自由:
- 添加/删除组件
- 拖动调整位置
- 调整大小
- 配置属性
**常见组件示例:**
- 时钟组件 - 显示当前时间
- 天气组件 - 显示天气信息
- 日历组件 - 显示日期和日程
- 系统监控 - 显示 CPU/内存使用率
---
## 📐 网格系统
阑山桌面使用网格系统管理组件布局。
### 网格概念
```
┌─────────────────────────────────────────┐
│ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │
│ │ 2x2│ │ 2x2│ │ 2x2│ │ 2x2│ │
│ │ 格 │ │ 格 │ │ 格 │ │ 格 │ │
│ └────┘ └────┘ └────┘ └────┘ │
│ ┌────┐ ┌────────┐ ┌────┐ │
│ │ 2x2│ │ 4x2 │ │ 2x2│ │
│ │ 格 │ │ 格 │ │ 格 │ │
│ └────┘ └────────┘ └────┘ │
│ ┌────────┐ ┌────────┐ │
│ │ 4x3 │ │ 4x3 │ │
│ │ 格 │ │ 格 │ │
│ └────────┘ └────────┘ │
└─────────────────────────────────────────┘
每格大小:约 60-80 像素(根据 DPI 自动调整)
```
### 组件尺寸
组件尺寸以**格数**为单位:
| 属性 | 说明 | 示例 |
|-----|------|------|
| `MinWidthCells` | 最小宽度(格数) | 4 = 4格宽 |
| `MinHeightCells` | 最小高度(格数) | 3 = 3格高 |
**常见尺寸参考:**
| 组件类型 | 推荐尺寸 | 实际像素(约) |
|---------|---------|--------------|
| 小图标 | 2x2 | 120x120 |
| 天气卡片 | 4x3 | 240x180 |
| 时钟 | 4x4 | 240x240 |
| 日历 | 6x4 | 360x240 |
| 宽面板 | 8x3 | 480x180 |
---
## 🏗️ 创建组件
### 步骤 1创建组件类
组件是继承自 Avalonia 控件的类:
```csharp
using Avalonia.Controls;
using LanMountainDesktop.PluginSdk;
namespace MyPlugin;
public class WeatherWidget : Border // 继承自 Border 或其他控件
{
public WeatherWidget(PluginDesktopComponentContext context)
{
// 组件初始化
InitializeComponent(context);
}
private void InitializeComponent(PluginDesktopComponentContext context)
{
// 设置背景
Background = new SolidColorBrush(Colors.Transparent);
// 设置圆角(使用宿主主题)
CornerRadius = context.Appearance.ResolveCornerRadius(
PluginCornerRadiusPreset.Component);
// 创建内容
var textBlock = new TextBlock
{
Text = "天气组件",
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center
};
Child = textBlock;
}
}
```
### 步骤 2注册组件
`Plugin.Initialize` 中注册:
```csharp
public override void Initialize(HostBuilderContext context, IServiceCollection services)
{
services.AddPluginDesktopComponent<WeatherWidget>(
new PluginDesktopComponentOptions
{
ComponentId = "MyPlugin.Weather", // 唯一标识
DisplayName = "天气", // 显示名称
IconKey = "Weather", // 图标Fluent 图标名)
Category = "工具", // 分类
MinWidthCells = 4, // 最小宽度(格)
MinHeightCells = 3, // 最小高度(格)
CornerRadiusPreset = PluginCornerRadiusPreset.Component // 圆角预设
});
}
```
### PluginDesktopComponentOptions 详解
| 属性 | 必需 | 说明 | 示例 |
|-----|------|------|------|
| `ComponentId` | ✅ | 唯一标识符 | `"MyPlugin.Weather"` |
| `DisplayName` | ✅ | 显示名称 | `"天气"` |
| `IconKey` | ✅ | 图标键名 | `"Weather"``"Clock"` |
| `Category` | ✅ | 分类 | `"工具"``"信息"` |
| `MinWidthCells` | ✅ | 最小宽度(格) | `4` |
| `MinHeightCells` | ✅ | 最小高度(格) | `3` |
| `CornerRadiusPreset` | ❌ | 圆角预设 | `PluginCornerRadiusPreset.Component` |
| `ResizeMode` | ❌ | 调整大小模式 | `PluginDesktopComponentResizeMode.Free` |
### 常用 Fluent 图标
| 图标键名 | 用途 |
|---------|------|
| `Weather` | 天气相关 |
| `Clock` | 时钟、时间 |
| `Calendar` | 日历、日期 |
| `Settings` | 设置 |
| `Home` | 主页 |
| `Search` | 搜索 |
| `Star` | 收藏 |
| `Heart` | 喜欢 |
| `Info` | 信息 |
| `Warning` | 警告 |
完整图标列表:[Fluent UI System Icons](https://github.com/microsoft/fluentui-system-icons)
---
## 🎨 组件外观
### 圆角设置
插件必须使用宿主提供的圆角系统,以保持视觉一致性:
```csharp
public WeatherWidget(PluginDesktopComponentContext context)
{
// 获取组件标准圆角
var cornerRadius = context.Appearance.ResolveCornerRadius(
PluginCornerRadiusPreset.Component);
CornerRadius = cornerRadius;
}
```
**可用的圆角预设:**
| 预设 | 用途 |
|-----|------|
| `Micro` | 微小元素 |
| `Xs` | 小元素 |
| `Sm` | 小卡片 |
| `Md` | 普通按钮/卡片 |
| `Lg` | 大面板 |
| `Xl` | 强调容器 |
| `Component` | **桌面组件标准** |
| `Default` | 自适应 |
### 背景与透明
```csharp
// 透明背景(推荐,让宿主壁纸透出)
Background = new SolidColorBrush(Colors.Transparent);
// 毛玻璃效果
Background = new SolidColorBrush(Color.Parse("#40FFFFFF"));
// 纯色背景
Background = new SolidColorBrush(Color.Parse("#FF2D2D2D"));
```
### 响应主题变化
```csharp
public WeatherWidget(PluginDesktopComponentContext context)
{
// 订阅主题变化
context.Appearance.AppearanceChanged += (_, _) =>
{
UpdateAppearance();
};
UpdateAppearance();
}
private void UpdateAppearance()
{
// 根据当前主题更新颜色
var isDark = Application.Current?.ActualThemeVariant == ThemeVariant.Dark;
Foreground = new SolidColorBrush(isDark ? Colors.White : Colors.Black);
}
```
---
## 📏 尺寸与布局
### 获取实际尺寸
```csharp
public WeatherWidget(PluginDesktopComponentContext context)
{
// 订阅尺寸变化
SizeChanged += OnSizeChanged;
}
private void OnSizeChanged(object? sender, SizeChangedEventArgs e)
{
// 获取当前实际尺寸(像素)
var width = Bounds.Width;
var height = Bounds.Height;
// 根据尺寸调整内容
if (width < 200)
{
// 小尺寸模式
ShowCompactView();
}
else
{
// 完整模式
ShowFullView();
}
}
```
### 自适应布局
```csharp
private void UpdateLayout()
{
var width = Bounds.Width;
var height = Bounds.Height;
// 根据宽高比调整布局
if (width > height * 2)
{
// 宽屏模式 - 水平排列
_layout.Orientation = Orientation.Horizontal;
}
else
{
// 正常模式 - 垂直排列
_layout.Orientation = Orientation.Vertical;
}
}
```
---
## 🔄 组件生命周期事件
```csharp
public WeatherWidget(PluginDesktopComponentContext context)
{
// 组件加载完成(此时已添加到视觉树)
Loaded += OnLoaded;
// 组件卸载(用户删除或关闭宿主)
Unloaded += OnUnloaded;
// 尺寸变化
SizeChanged += OnSizeChanged;
}
private async void OnLoaded(object? sender, RoutedEventArgs e)
{
// 加载数据
await LoadDataAsync();
// 启动定时器
_timer = new Timer(OnTimerTick, null, TimeSpan.Zero, TimeSpan.FromMinutes(5));
}
private void OnUnloaded(object? sender, RoutedEventArgs e)
{
// 清理资源
_timer?.Dispose();
_httpClient?.Dispose();
}
```
---
## 💾 组件设置持久化
组件可以保存自己的设置:
```csharp
public class WeatherWidget : Border
{
private readonly IComponentSettingsAccessor _settings;
public WeatherWidget(PluginDesktopComponentContext context)
{
// 获取设置访问器
_settings = context.Settings;
// 读取设置
var city = _settings.GetValue<string>("city", defaultValue: "北京");
var autoRefresh = _settings.GetValue<bool>("auto_refresh", defaultValue: true);
// 保存设置
_settings.SetValue("city", "上海");
}
}
```
---
## 🐛 常见问题
### 问题 1组件不显示在库中
**排查:**
1. 确认已调用 `AddPluginDesktopComponent`
2. 检查 `ComponentId` 是否唯一
3. 确认组件类是 `public`
### 问题 2组件显示异常
**排查:**
1. 检查构造函数参数是否正确(需要 `PluginDesktopComponentContext`
2. 确认没有抛出未处理异常
3. 查看日志文件
### 问题 3圆角不生效
**原因:** 插件无法访问宿主 XAML 资源
**解决:** 使用代码设置圆角(见上文)
### 问题 4尺寸不正确
**排查:**
1. 检查 `MinWidthCells``MinHeightCells` 设置
2. 确认内容没有强制尺寸
---
## 📚 参考资源
- [PluginDesktopComponentOptions 源码](../../LanMountainDesktop.PluginSdk/PluginDesktopComponentOptions.cs)
- [04-外观与主题系统](04-外观与主题系统.md)
- [01-开发天气组件](../04-实战案例/01-开发天气组件.md)
---
## 🎯 下一步
学习如何添加设置页面:
👉 **[03-设置系统集成](03-设置系统集成.md)** - 让用户配置你的组件
---
*最后更新2026年4月*