- UI组件
- 桌面应用
【免费下载链接】SukiUI
UI Theme for AvaloniaUI
SukiUI 是面向 AvaloniaUI 的界面主题库,其所有主题能力都收敛在SukiTheme这一个类上:明暗切换、主题色更换、多语言资源乃至背景渲染均通过它对外暴露。本文以SukiTheme.GetInstance()的获取方式为切入点,结合仓库源码逐步拆解它的注册、单例语义、核心 API 与底层资源机制,读完你可以在自己的 AvaloniaUI 应用中完成主题实例的初始化、获取与运行时动态切换。
SukiTheme 是什么:一个挂在 Application 上的主题 Styles
SukiTheme本质上是一个继承自 AvaloniaStyles的样式容器(见 SukiUI/Theme/Index.axaml.cs),它必须在应用启动阶段作为一项样式注册进App.axaml的Application.Styles中。参考 Demo 工程的 SukiUI.Demo/App.axaml,注册方式如下:
<Application.Styles> <FluentTheme /> <suki:SukiTheme Locale="en-US" ThemeColor="Blue" /> <!-- 其他 StyleInclude --> </Application.Styles>其中Locale用于指定 SukiUI 内建控件的本地化语言,ThemeColor用于指定启动时的初始主题色(默认为SukiColor.Blue)。从源码看,SukiTheme在构造时(Index.axaml.cs)会依次完成四件事:
- 通过
AvaloniaXamlLoader.Load(this)加载自身的 XAML 资源; - 缓存
Application.Current并订阅ActualThemeVariantChanged事件,用于回传基础主题(明/暗)的变更通知; - 将仓库内置的 4 套默认主题色(Orange / Red / Green / Blue)逐个注册进可用主题集合;
- 根据
IsRightToLeft、ThemeColor、Locale的初始值初始化对应的资源。
获取 SukiTheme 实例
SukiUI 官方文档给出的获取方式只有一行(见 docs/docs/zh/documentation/theming/basic.md):
SukiTheme theme = SukiTheme.GetInstance();SukiTheme对外暴露了两个静态的GetInstance重载(Index.axaml.cs):
public static SukiTheme GetInstance(Application app) public static SukiTheme GetInstance() // 内部等价于 GetInstance(Application.Current!)两者的实现逻辑一致:在传入(或当前)应用的Styles集合中,用FirstOrDefault找到第一个类型为SukiTheme的样式实例并返回。其语义值得注意:
- “单例”是由注册方式保证的:因为
SukiTheme是定义在App.axaml里、随应用生命周期存在的样式对象,所以GetInstance每次都会返回同一个实例,这使它成为应用内全局共享的主题管理入口; - 未注册会抛异常:如果
App.axaml的Application.Styles中没有SukiTheme,GetInstance会抛出InvalidOperationException,提示 “Ensure SukiTheme has been set in Application.Styles in App.axaml.”。因此在使用任何主题 API 之前,务必确认主题已正确注册。
拿到实例之后:SukiTheme 的核心能力一览
GetInstance只是入口,文档所在 theaming 目录下的姊妹文档(theme.md、theme-color.md)进一步展示了拿到实例后可用的完整 API,这里汇总为四类能力:
1. 明暗主题切换,对应ThemeVariant级别的切换:
SukiTheme.GetInstance().ChangeBaseTheme(ThemeVariant.Dark); // 切到暗色 SukiTheme.GetInstance().ChangeBaseTheme(ThemeVariant.Light); // 切到亮色 SukiTheme.GetInstance().SwitchBaseTheme(); // 明暗互切2. 主题色切换,包括“盲切下一个”和“切到指定色”:
SukiTheme.GetInstance().SwitchColorTheme(); // 按注册顺序循环切换 SukiTheme.GetInstance().ChangeColorTheme(SukiColor.Red); // 切到内置主题色 SukiTheme.GetInstance().ChangeColorTheme(PurpleTheme); // 切到自定义主题3. 自定义主题色的创建、注册与激活,配合 SukiUI/Models/SukiColorTheme.cs 中的SukiColorTheme记录类型:
var PurpleTheme = new SukiColorTheme("Purple", Colors.Purple, Colors.DarkBlue); SukiTheme.GetInstance().AddColorTheme(PurpleTheme); // 注册(不激活) SukiTheme.GetInstance().ChangeColorTheme(PurpleTheme); // 注册并激活SukiColorTheme的核心字段是DisplayName、Primary与Accent:构造时它会自动把两个颜色按 0.5 系数压暗生成PrimaryDark/AccentDark,用于明暗主题下的配色一致性;此外还会预计算着色器所需的背景色。需要说明的是,ChangeColorTheme(SukiColor)只对 4 套内置主题有效,若传入未定义的颜色会抛出异常(源码中SetColorThemeResourcesOnColorThemeChanged会检查DefaultColorThemes字典)。
4. 事件订阅,用于在主题切换时同步非DynamicResource的控件状态:
SukiTheme.GetInstance().OnColorThemeChanged += theme => Console.WriteLine("Color theme change triggered !"); SukiTheme.GetInstance().OnBaseThemeChanged += variant => Console.WriteLine("Theme changed triggered !");从源码(Index.axaml.cs)可见,OnColorThemeChanged的回调参数是SukiColorTheme,OnBaseThemeChanged的回调参数是ThemeVariant,分别对应主题色与明暗两个维度的变更。
源码级原理:切换主题时底层发生了什么
以ChangeColorTheme(SukiColorTheme)为例,调用链为(Index.axaml.cs):
ChangeColorTheme → SetColorTheme → SetColorWithOpacities / SetResourceSetColorTheme会把主题色的Primary、PrimaryDark、Accent、AccentDark四个颜色写入应用的全局资源SukiPrimaryColor、SukiPrimaryDarkColor、SukiAccentColor、SukiAccentDarkColor。更有价值的是SetColorWithOpacities:它会对主色和强调色各生成 11 档带透明度的变体资源(SukiPrimaryColor75、SukiPrimaryColor50、SukiPrimaryColor25、SukiPrimaryColor10……直至SukiPrimaryColor0),并在暗色主题下额外生成两档提亮色SukiPrimaryColor120、SukiPrimaryColor150(通过Lighten按 0.7 / 1.0 系数向白色混合)。这一整套资源就是 SukiUI 控件样式在主题切换时实时变色的数据来源。
SwitchColorTheme()的实现也值得注意(Index.axaml.cs):它先在ColorThemes集合中定位当前激活主题的下标,再取(index + 1) % ColorThemes.Count作为下一个主题,即按注册顺序“循环盲切”。自定义主题通过AddColorTheme/AddColorThemes加入集合后,同样会参与这个循环;AddColorTheme内部用HashSet去重,重复添加同一个主题会抛出InvalidOperationException。
明暗切换的底层则直接作用于Application:ChangeBaseTheme(ThemeVariant)会设置_app.RequestedThemeVariant,随后调用RefreshActiveColorThemeResources()依据新的基础主题重新生成带透明度与提亮档位的主题资源;SwitchBaseTheme()则在当前ActualThemeVariant的明暗之间取反切换。
实战小结
要在一款 AvaloniaUI 应用中启用并管理 SukiUI 主题,完整的链路是:
- 在
App.axaml的Application.Styles中加入<suki:SukiTheme Locale="en-US" ThemeColor="Blue" />; - 在任意代码位置通过
SukiTheme.GetInstance()获取全局实例; - 调用
ChangeBaseTheme/SwitchBaseTheme管理明暗,调用ChangeColorTheme/SwitchColorTheme/AddColorTheme管理主题色; - 需要感知切换时订阅
OnBaseThemeChanged/OnColorThemeChanged。
由于GetInstance强依赖应用样式中的注册,建议所有主题操作都收敛到应用启动完成后执行,并在调用前确保Application.Current已就绪。掌握了这一入口,SukiUI 的主题体系便尽在掌握。
- UI组件
- 桌面应用
【免费下载链接】SukiUI
UI Theme for AvaloniaUI
相关推荐
SukiUI 主题系统实战指南:用 SukiTheme 掌控明暗与颜色主题切换
SukiUI 主题系统实战指南:用 SukiTheme 掌控明暗与颜色主题切换 SukiUI 是面向 AvaloniaUI 的现代 UI 主题库,其主题能力的核
UI组件桌面应用SukiUI 明暗主题切换完全指南:基于 Avalonia Theme Variant 的 SukiTheme 主题系统
SukiUI 明暗主题切换完全指南:基于 Avalonia Theme Variant 的 SukiTheme 主题系统 SukiUI 是一套基于 Avalon
UI组件桌面应用SukiUI 颜色主题切换与自定义色系注册:从 SukiTheme 到 SukiColorTheme 的完整实战指南
SukiUI 颜色主题切换与自定义色系注册:从 SukiTheme 到 SukiColorTheme 的完整实战指南 SukiUI 是构建在 AvaloniaU
UI组件桌面应用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考