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

7.4 KiB
Raw Blame History

04-外观与主题系统

阑山桌面支持暗色/浅色主题切换,插件需要适配宿主的视觉风格,保持界面一致性。


🎨 主题系统概述

阑山桌面使用 Avalonia UI 的主题系统,支持:

  • 浅色主题 - 明亮背景,深色文字
  • 深色主题 - 深色背景,浅色文字
  • 跟随系统 - 自动匹配 Windows/macOS 主题

🌗 检测当前主题

在组件中检测

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 中无效。

使用代码设置圆角

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 自适应 根据尺寸自动计算

内部元素圆角

组件内部的卡片、按钮应使用更小的圆角:

// 组件根容器 - 使用 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)
};

🎨 颜色系统

推荐的颜色策略

// 透明背景(推荐)- 让宿主壁纸透出
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"); // 阑山桌面主色调

文字颜色

// 主要文字
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"));

🔄 响应外观变化

订阅外观变化事件

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 控件库,它们自动适配主题:

<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. 始终使用透明背景

// ✅ 好的做法
Background = new SolidColorBrush(Colors.Transparent);

// ❌ 避免硬编码背景色
Background = new SolidColorBrush(Colors.White);

2. 组件根容器必须使用 Component 圆角

// ✅ 正确
CornerRadius = context.ResolveCornerRadius(PluginCornerRadiusPreset.Component);

// ❌ 错误 - 硬编码
CornerRadius = new CornerRadius(18);

3. 响应主题变化

// ✅ 订阅变化事件
Application.Current.ActualThemeVariantChanged += OnThemeChanged;

// ❌ 只在构造函数中设置一次

4. 使用语义化颜色

// ✅ 根据用途选择颜色
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 控件

📚 参考资源


🎯 下一步

学习插件间通信:

👉 05-插件间通信 - 与其他插件协作


最后更新2026年4月