Avalonia 动态设置主题和色彩

四套主题Default、Forest、Lavender、Nighttime,2种色彩Dark和Light

不同主题下需要显示的颜色不同,不同的色彩需要显示的图标颜色不同。

首先需要4个主题样式文件 Default.axmal、Forest.axmal、Lavender.axmal、Nighttime.axmal

2套图标资源,Dark和Light

动态实现:
1.资源(举个例子)
<ResourceDictionary xmlns="https://github.com/avaloniaui"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    >
  <Design.PreviewWith>
    <Border Margin="20"></Border>
  </Design.PreviewWith>
  <!-- Add Resources Here -->
  <ResourceDictionary.ThemeDictionaries>
  <ResourceDictionary x:Key="Dark">
    <Bitmap x:Key="default">avares://YourProjectName/Assets/Dark/default.png</Bitmap>
    <Bitmap x:Key="auto">avares://YourProjectName/Assets/Dark/auto.png</Bitmap>
    <Bitmap x:Key="close">avares://YourProjectName/Assets/Dark/close.png</Bitmap>
  </ResourceDictionary>
  </ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>

2.动态加载资源:

#region 定义主题色切换方法
/// <summary>
/// 切换为浅色主题
/// </summary>
public void SwitchToThemeColor(bool isDark)
{
    if (Application.Current is { } app)
    {
        if (isDark)
        {
            app.RequestedThemeVariant = ThemeVariant.Dark;
        }
        else
        {
            app.RequestedThemeVariant = ThemeVariant.Light;
        }
        ThemeColorInit(isDark);
    }
}
/// <summary>
/// 主题色切换
/// </summary>
/// <param name="themeName">主题名称</param>
/// <param name="isDark">色彩类型</param>
public void SwitchToTheme(string themeName, bool isDark)
{
    if (StyleIncludes.ContainsKey(themeName))
    {
        var styleInclude = StyleIncludes[themeName];

        // 清空所有旧样式
        Application.Current.Styles.Clear();

        // 加载主题样式
        Application.Current.Styles.Add(styleInclude);
        Application.Current.Styles.Add(DefultStyle);

        if (isDark)
        {
            Application.Current.RequestedThemeVariant = ThemeVariant.Dark;
        }
        else
        {
            Application.Current.RequestedThemeVariant = ThemeVariant.Light;
        }
        ThemeColorInit(isDark);
    }
}
/// <summary>
/// 通过选择的颜色主题,动态载入资源字典
/// </summary>
private void ThemeColorInit(bool isDark)
{
    try
    {
        var resources = App.Current.Resources.MergedDictionaries;

        // 清除现有资源字典
        resources.Clear();

        // 加载新的资源字典
        string sourceUri = isDark
            ? "avares://YourProjectName/Resources/DarkResource.axaml"
            : "avares://YourProjectName/Resources/LightResource.axaml";

        var newResources = new ResourceInclude(new Uri(sourceUri))
        {
            Source = new Uri(sourceUri)
        };

        resources.Add(newResources);
    }
    catch(Exception ex)
    {
        Debug.WriteLine(ex.Message);
    }
}
#endregion

2.Image 绑定
2.1(硬绑定)
<Image Source="{DynamicResource close}" Width="25" Height="25"/>
2.2 动态绑定(根据当前设置的色彩动态更新)
<Image Source="{Binding Icon, Converter={StaticResource ResourceKeyConverter}}" Margin="0,10,0,5" Width="25" Height="25"/>

ResourceKeyConverter的实现(Conver文件)
/// <summary>
/// ResourceKey״̬
/// </summary>
public class ResourceKeyConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is string resourceKey)
        {
            // 获取当前主题
            var currentTheme = Application.Current.RequestedThemeVariant;
            // 根据当前主题获取相应的资源字典
            string themeKey = currentTheme == ThemeVariant.Dark ? "Dark" : "Light";

            if (Application.Current?.Resources.TryGetResource(resourceKey, currentTheme, out var resource) == true)
            {
                return resource;
            }
        }
        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

posted @ 2025-01-19 22:57  一步一个坑  阅读(453)  评论(0)    收藏  举报