Files
AtomUI/docs/Desktop.Controls/ToggleIconButton/ToggleIconButton.md
T

165 lines
7.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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"` | 未选中态图标展示器 |