7.7 KiB
ToggleIconButton 切换图标按钮
概述
切换图标按钮(ToggleIconButton)是一个纯图标的切换按钮控件,在选中(Checked)和未选中(Unchecked)状态之间切换时可以显示不同的图标。它没有文本内容、无背景、无边框,仅通过图标和图标颜色来表达状态。
ToggleIconButton 常用于工具栏、面板头部的折叠/展开、收藏/取消收藏、排序方向切换等交互场景。在 Ant Design 中没有直接对应的组件,它是 AtomUI 基于 Avalonia ToggleButton 扩展的实用控件。
设计原理
设计定位
在 Ant Design 的组件体系中,切换类控件(Switch、Checkbox、Radio)都有较重的视觉表现和明确的表单语义。而在实际开发中,经常需要一种更轻量的切换方式——仅通过图标变化表达二元状态,不占据过多视觉空间。例如:
- 折叠/展开:Collapse 面板的箭头图标在展开和收起时切换方向
- 排序切换:表格列标题的排序图标在升序和降序之间切换
- 收藏/取消:心形或星形图标在空心和实心之间切换
ToggleIconButton 就是为这类轻量切换场景设计的。
Avalonia ToggleButton 基础能力
AtomUI 的 ToggleIconButton 通过 AbstractToggleIconButton 继承自 Avalonia 的 Avalonia.Controls.Primitives.ToggleButton。理解 Avalonia ToggleButton 的基础能力有助于理解 ToggleIconButton 的交互基础。
Avalonia ToggleButton 的核心职责:
Avalonia 的 ToggleButton 继承自 Button,在标准按钮的点击行为之上增加了 IsChecked 状态管理。每次点击时 IsChecked 在 true / false(以及可选的 null)之间切换。它的继承链为:
Control → TemplatedControl → ContentControl → Button → ToggleButton
Avalonia ToggleButton 提供的基础属性:
| 属性 | 说明 |
|---|---|
IsChecked |
切换状态:true(选中)、false(未选中)、null(不确定,当 IsThreeState=true 时) |
IsThreeState |
是否支持三态切换 |
Command / CommandParameter |
MVVM 命令绑定 |
ClickMode |
点击触发时机 |
IsPressed |
只读,是否处于按压状态 |
Avalonia ToggleButton 提供的基础伪类:
| 伪类 | 说明 |
|---|---|
:checked |
IsChecked == true |
:unchecked |
IsChecked == false |
:indeterminate |
IsChecked == null(三态模式) |
:pointerover |
鼠标悬浮 |
:pressed |
按下 |
:disabled |
禁用 |
AtomUI 的扩展设计
AtomUI ToggleIconButton 在 Avalonia ToggleButton 的基础上做了以下扩展:
| 扩展能力 | 实现方式 | 设计动机 |
|---|---|---|
| 双图标切换 | CheckedIcon + UnCheckedIcon 属性 |
选中和未选中状态显示不同图标,通过模板中两个 IconPresenter 的可见性切换实现 |
| 精细颜色控制 | NormalIconBrush / ActiveIconBrush / SelectedIconBrush / DisabledIconBrush |
四种状态各有独立的颜色属性,主题根据伪类自动切换 |
| 当前生效颜色 | IconBrush 属性 |
由主题根据当前状态自动设置的生效颜色 |
| 图标尺寸 | IconWidth / IconHeight 属性 |
精确控制图标渲染尺寸 |
| 过渡动画 | IMotionAwareControl + Background / RenderTransform 过渡 |
平滑的背景色和变换过渡 |
| Design Token | ButtonToken.ScopeProvider |
复用 Button 的 Token 作用域 |
功能详解
双图标切换机制
ToggleIconButton 通过两个属性分别设置选中和未选中状态的图标:
| 属性 | 用途 | 可见性条件 |
|---|---|---|
CheckedIcon |
选中状态(IsChecked = true)时显示的图标 |
:checked 伪类激活时可见 |
UnCheckedIcon |
未选中状态(IsChecked = false)时显示的图标 |
:unchecked 伪类激活时可见 |
模板中包含两个 IconPresenter,通过 IsChecked 绑定控制它们的交替显示。
颜色状态系统
ToggleIconButton 提供了精细的颜色控制体系,支持四种状态各自独立的颜色定义:
| 属性 | 对应状态 | 说明 |
|---|---|---|
NormalIconBrush |
未选中正常态 | 默认图标颜色 |
ActiveIconBrush |
悬浮/按下态 | 鼠标悬浮或按下时的图标颜色 |
SelectedIconBrush |
选中态 | IsChecked = true 时的图标颜色 |
DisabledIconBrush |
禁用态 | IsEnabled = false 时的图标颜色 |
IconBrush |
当前生效颜色 | 由主题根据当前状态自动赋值,实际渲染使用此属性 |
过渡动画
当 IsMotionEnabled = true 时,OnLoaded 阶段自动配置以下过渡:
Background:SolidColorBrushTransition(背景色平滑过渡)RenderTransform:TransformOperationsTransition(缩放/旋转等变换平滑过渡)
OnUnloaded 时清除过渡,避免不可见控件消耗资源。
继承关系
Avalonia.Controls.Primitives.TemplatedControl
└── Avalonia.Controls.ContentControl
└── Avalonia.Controls.Button
└── Avalonia.Controls.Primitives.ToggleButton
└── AtomUI.Controls.Commons.AbstractToggleIconButton (IMotionAwareControl) ← 设备无关基类
└── AtomUI.Desktop.Controls.ToggleIconButton ← 桌面实现
各层级职责划分:
| 层级 | 提供的能力 |
|---|---|
Avalonia.Controls.Button |
点击交互 → Click 事件、ICommand 绑定、IsPressed 状态 |
Avalonia.Controls.Primitives.ToggleButton |
IsChecked 状态管理、:checked / :unchecked 伪类、三态支持 |
AbstractToggleIconButton(基类层) |
CheckedIcon / UnCheckedIcon 双图标、四种颜色状态属性、IconWidth / IconHeight、过渡动画 |
ToggleIconButton(桌面层) |
注册 ButtonToken.ScopeProvider,由主题控制视觉表现 |
实现的共享接口:
| 接口 | 定义位置 | 作用 |
|---|---|---|
IMotionAwareControl |
AtomUI.Controls |
支持 IsMotionEnabled 过渡动画开关 |
源码位置
| 层级 | 文件路径 | 说明 |
|---|---|---|
| 基类 | src/AtomUI.Controls/Buttons/AbstractToggleIconButton.cs |
设备无关基类 |
| 控件类 | src/AtomUI.Desktop.Controls/Buttons/ToggleIconButton.cs |
桌面切换图标按钮 |
| 主题模板 | src/AtomUI.Desktop.Controls/Buttons/Themes/ToggleIconButtonTheme.axaml |
ControlTheme AXAML |
| 主题代码 | src/AtomUI.Desktop.Controls/Buttons/Themes/ToggleIconButtonTheme.cs |
主题 Code-behind |
| 主题常量 | src/AtomUI.Desktop.Controls/Buttons/Themes/ToggleIconButtonThemeConstants.cs |
模板部件名常量 |
模板结构
Border#Frame (背景 + 边框 + 圆角)
└── Panel#RootLayout (叠层容器)
├── IconPresenter#CheckedIconPresenter (选中图标,IsChecked=True 时可见)
└── IconPresenter#UnCheckedIconPresenter (未选中图标,IsChecked=False 时可见)
模板设计理由:
- Panel 叠层容器:两个
IconPresenter叠加放置在同一位置,通过IsVisible绑定IsChecked实现交替显示。使用Panel而非Grid是因为只需简单叠层,无需行列定义。 - 两个独立 IconPresenter:分开两个图标展示器而非运行时替换
Icon属性,避免了图标切换时的测量/排列抖动。
模板部件常量
| 常量名 | 值 | 说明 |
|---|---|---|
ToggleIconButtonThemeConstants.RootLayoutPart |
"PART_RootLayout" |
根布局面板 |
ToggleIconButtonThemeConstants.CheckedIconPresenterPart |
"PART_CheckedIconPresenter" |
选中态图标展示器 |
ToggleIconButtonThemeConstants.UnCheckedIconPresenterPart |
"PART_UnCheckedIconPresenter" |
未选中态图标展示器 |