Files
LanMountainDesktop/docs/archive/Plugins develop/02-核心概念与原理/02-桌面组件系统.md
2026-06-08 03:54:33 +08:00

9.9 KiB
Raw Blame History

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 控件的类:

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 中注册:

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


🎨 组件外观

圆角设置

插件必须使用宿主提供的圆角系统,以保持视觉一致性:

public WeatherWidget(PluginDesktopComponentContext context)
{
    // 获取组件标准圆角
    var cornerRadius = context.Appearance.ResolveCornerRadius(
        PluginCornerRadiusPreset.Component);
    
    CornerRadius = cornerRadius;
}

可用的圆角预设:

预设 用途
Micro 微小元素
Xs 小元素
Sm 小卡片
Md 普通按钮/卡片
Lg 大面板
Xl 强调容器
Component 桌面组件标准
Default 自适应

背景与透明

// 透明背景(推荐,让宿主壁纸透出)
Background = new SolidColorBrush(Colors.Transparent);

// 毛玻璃效果
Background = new SolidColorBrush(Color.Parse("#40FFFFFF"));

// 纯色背景
Background = new SolidColorBrush(Color.Parse("#FF2D2D2D"));

响应主题变化

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);
}

📏 尺寸与布局

获取实际尺寸

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();
    }
}

自适应布局

private void UpdateLayout()
{
    var width = Bounds.Width;
    var height = Bounds.Height;
    
    // 根据宽高比调整布局
    if (width > height * 2)
    {
        // 宽屏模式 - 水平排列
        _layout.Orientation = Orientation.Horizontal;
    }
    else
    {
        // 正常模式 - 垂直排列
        _layout.Orientation = Orientation.Vertical;
    }
}

🔄 组件生命周期事件

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();
}

💾 组件设置持久化

组件可以保存自己的设置:

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. 检查 MinWidthCellsMinHeightCells 设置
  2. 确认内容没有强制尺寸

📚 参考资源


🎯 下一步

学习如何添加设置页面:

👉 03-设置系统集成 - 让用户配置你的组件


最后更新2026年4月