mirror of
https://github.com/AtomUI/AtomUI.git
synced 2026-10-22 17:35:30 +08:00
150 lines
8.2 KiB
Markdown
150 lines
8.2 KiB
Markdown
# ButtonSpinner 按钮微调器
|
||
|
||
## 概述
|
||
|
||
按钮微调器(ButtonSpinner)是一个带有上下调整按钮的装饰容器,允许用户通过点击按钮、键盘方向键或鼠标滚轮来触发数值增减操作。它是一个通用的装饰容器——自身不管理数值,只负责将「增加/减少」意图通过 `Spin` 事件传递给外部逻辑。
|
||
|
||
**ButtonSpinner 是 AtomUI 的扩展控件,在 Ant Design 5.0 中没有直接对应的独立组件**。它的设计灵感来自 Ant Design 的 InputNumber(数字输入框)中的步进按钮区域,但被抽象为一个独立的、可复用的装饰容器。典型使用场景包括:
|
||
|
||
- 作为 `NumericUpDown` 的内部实现基础
|
||
- 为任意内容提供步进增减功能
|
||
- 需要上下调整按钮的自定义输入场景
|
||
|
||
ButtonSpinner 继承自 Avalonia 的 `Spinner` 基类,并融合了 AtomUI 的 Design Token 系统、尺寸系统、样式变体系统和输入控件状态系统,提供与 AtomUI 其他输入类控件一致的视觉体验。
|
||
|
||
---
|
||
|
||
## 设计原理
|
||
|
||
### Avalonia 基础能力
|
||
|
||
ButtonSpinner 继承自 `Avalonia.Controls.Primitives.Spinner`,该基类提供了以下核心能力:
|
||
|
||
| 能力 | 说明 |
|
||
|---|---|
|
||
| `Spin` 事件 | `EventHandler<SpinEventArgs>` — 当用户触发增减操作时引发 |
|
||
| `SpinDirection` | 枚举:`Increase` / `Decrease` — 指示增减方向 |
|
||
| `ValidSpinDirection` | 位标志枚举:`None` / `Increase` / `Decrease` — 控制哪些方向可用 |
|
||
| `Content` / `ContentTemplate` | 内容承载能力(继承自 `ContentControl`) |
|
||
|
||
### AtomUI 的扩展设计
|
||
|
||
ButtonSpinner 在 Avalonia 基础上增加了以下 AtomUI 特性:
|
||
|
||
| 扩展能力 | 实现方式 | 设计动机 |
|
||
|---|---|---|
|
||
| **三种尺寸** | `ISizeTypeAware` — `SizeType` 属性(Large/Middle/Small) | 对齐 Ant Design 的尺寸系统 |
|
||
| **三种样式变体** | `IInputControlStyleVariantAware` — `StyleVariant` 属性(Outline/Filled/Borderless) | 对齐 Ant Design Input 的三种变体 |
|
||
| **输入状态** | `IInputControlStatusAware` — `Status` 属性(Error/Warning) | 对齐 Ant Design 的验证状态反馈 |
|
||
| **前后缀内容** | `InnerLeftContent` / `InnerRightContent` | 对齐 Ant Design Input 的 prefix/suffix |
|
||
| **前后附加组件** | `LeftAddOn` / `RightAddOn`(继承自 `AddOnDecoratedBox`) | 对齐 Ant Design Input 的 addonBefore/addonAfter |
|
||
| **操作按钮位置** | `ButtonSpinnerLocation` 枚举(Left/Right) | 灵活控制步进按钮的显示位置 |
|
||
| **浮动操作按钮** | `IsButtonSpinnerFloatable` 属性 | 操作按钮在鼠标悬浮时滑入,离开时滑出 |
|
||
| **紧凑空间** | `ICompactSpaceAware` 接口 | 在 `Space.Compact` 容器中自动调整布局 |
|
||
| **过渡动画** | `IMotionAwareControl` 接口 | 操作按钮的滑入/滑出动画 |
|
||
| **键盘/滚轮交互** | 方向键 ↑↓ / 鼠标滚轮 | 多种输入方式触发 Spin |
|
||
|
||
### 浮动操作按钮(Floatable Handle)
|
||
|
||
这是 ButtonSpinner 独有的特性:当 `IsButtonSpinnerFloatable="True"` 时,操作按钮平时隐藏,鼠标悬浮在控件上时通过滑动动画显示。该特性的设计目的是在不需要频繁调整数值的场景下减少视觉噪音。
|
||
|
||
**动画行为:**
|
||
- 鼠标进入 → 操作按钮从边缘滑入(带不透明度渐变),同时内容区域向反方向收缩让出空间
|
||
- 鼠标离开 → 操作按钮滑出,内容区域恢复原始位置
|
||
- 动画使用 `MotionDurationMid` Token 控制时长
|
||
|
||
---
|
||
|
||
## 继承关系
|
||
|
||
```
|
||
Avalonia.Controls.ContentControl
|
||
└── Avalonia.Controls.Primitives.Spinner (Spin 事件, ValidSpinDirection)
|
||
└── AtomUI.Desktop.Controls.ButtonSpinner
|
||
(ISizeTypeAware, IInputControlStyleVariantAware,
|
||
IInputControlStatusAware, IMotionAwareControl, ICompactSpaceAware)
|
||
```
|
||
|
||
**内部组件关系:**
|
||
|
||
```
|
||
ButtonSpinner
|
||
├── ButtonSpinnerDecoratedBox (extends AddOnDecoratedBox)
|
||
│ ├── LeftAddOn / RightAddOn ← 外部附加组件
|
||
│ ├── InnerLeftContent / InnerRightContent ← 内部前后缀
|
||
│ ├── Content ← 用户内容
|
||
│ └── SpinnerContent
|
||
│ └── ButtonSpinnerHandle ← 操作按钮容器
|
||
│ ├── IconButton (IncreaseButton, ↑)
|
||
│ └── IconButton (DecreaseButton, ↓)
|
||
└── ButtonSpinnerContentPanel (extends DockPanel) ← 内容布局面板
|
||
```
|
||
|
||
**实现的共享接口:**
|
||
|
||
| 接口 | 作用 |
|
||
|---|---|
|
||
| `ISizeTypeAware` | 支持 Large/Middle/Small 三种尺寸 |
|
||
| `IInputControlStyleVariantAware` | 支持 Outline/Filled/Borderless 三种样式变体 |
|
||
| `IInputControlStatusAware` | 支持 Error/Warning 验证状态 |
|
||
| `IMotionAwareControl` | 支持 `IsMotionEnabled` 动画控制 |
|
||
| `ICompactSpaceAware` | 支持紧凑空间自动布局调整 |
|
||
|
||
---
|
||
|
||
## 源码位置
|
||
|
||
| 层级 | 文件路径 | 说明 |
|
||
|---|---|---|
|
||
| 控件类 | `src/AtomUI.Desktop.Controls/ButtonSpinner/ButtonSpinner.cs` | 主控件类 |
|
||
| 内部控件 | `src/AtomUI.Desktop.Controls/ButtonSpinner/ButtonSpinnerDecoratedBox.cs` | 装饰容器(浮动动画逻辑) |
|
||
| 内部控件 | `src/AtomUI.Desktop.Controls/ButtonSpinner/ButtonSpinnerHandle.cs` | 操作按钮容器(自定义渲染边框) |
|
||
| 内部控件 | `src/AtomUI.Desktop.Controls/ButtonSpinner/ButtonSpinnerContentPanel.cs` | 内容布局面板 |
|
||
| 伪类 | `src/AtomUI.Desktop.Controls/ButtonSpinner/ButtonSpinnerPseudoClass.cs` | 伪类常量 |
|
||
| Token 定义 | `src/AtomUI.Desktop.Controls/ButtonSpinner/ButtonSpinnerToken.cs` | 组件级 Design Token |
|
||
| 主题模板 | `src/AtomUI.Desktop.Controls/ButtonSpinner/Themes/ButtonSpinnerTheme.axaml` | 控件主题模板 |
|
||
| 主题模板 | `src/AtomUI.Desktop.Controls/ButtonSpinner/Themes/ButtonSpinnerHandleTheme.axaml` | 操作按钮主题 |
|
||
| 主题模板 | `src/AtomUI.Desktop.Controls/ButtonSpinner/Themes/ButtonSpinnerDecoratedBoxTheme.axaml` | 装饰容器主题 |
|
||
| 主题常量 | `src/AtomUI.Desktop.Controls/ButtonSpinner/Themes/ButtonSpinnerThemeConstants.cs` | 模板部件名常量 |
|
||
| 主题注册 | `src/AtomUI.Desktop.Controls/ButtonSpinner/Themes/ButtonSpinnerThemes.axaml` | 主题资源注册 |
|
||
| Gallery 示例 | `controlgallery/AtomUIGallery/ShowCases/Views/Navigation/ButtonSpinnerShowCase.axaml` | 使用范例 |
|
||
|
||
---
|
||
|
||
## 模板结构
|
||
|
||
```
|
||
ButtonSpinner
|
||
└── ButtonSpinnerDecoratedBox (PART_DecoratedBox) ← 装饰容器
|
||
├── [LeftAddOn] ← 左侧附加组件(可选)
|
||
├── InnerBox ← 内部输入区域
|
||
│ ├── [InnerLeftContent] ← 前缀(可选)
|
||
│ ├── Content ← 用户内容
|
||
│ └── [InnerRightContent] ← 后缀(可选)
|
||
├── ButtonSpinnerHandle (SpinnerContent) ← 操作按钮区域
|
||
│ └── UniformGrid (1列 × 2行)
|
||
│ ├── IconButton (PART_IncreaseButton, ↑) ← 增加按钮
|
||
│ └── IconButton (PART_DecreaseButton, ↓) ← 减少按钮
|
||
└── [RightAddOn] ← 右侧附加组件(可选)
|
||
```
|
||
|
||
### 模板部件常量
|
||
|
||
| 常量 | 值 | 说明 |
|
||
|---|---|---|
|
||
| `ButtonSpinnerThemeConstants.DecoratedBoxPart` | `"PART_DecoratedBox"` | 装饰容器部件 |
|
||
| `ButtonSpinnerThemeConstants.IncreaseButtonPart` | `"PART_IncreaseButton"` | 增加按钮部件 |
|
||
| `ButtonSpinnerThemeConstants.DecreaseButtonPart` | `"PART_DecreaseButton"` | 减少按钮部件 |
|
||
| `ButtonSpinnerThemeConstants.SpinnerHandlePart` | `"PART_SpinnerHandle"` | 操作手柄部件 |
|
||
|
||
### 交互行为
|
||
|
||
| 触发方式 | 条件 | 行为 |
|
||
|---|---|---|
|
||
| 点击增加按钮 | `AllowSpin == true` | 触发 `Spin` 事件,方向 `Increase` |
|
||
| 点击减少按钮 | `AllowSpin == true` | 触发 `Spin` 事件,方向 `Decrease` |
|
||
| 键盘 ↑ 键 | `AllowSpin == true`,非 XY 导航模式 | 触发 `Spin` 事件,方向 `Increase` |
|
||
| 键盘 ↓ 键 | `AllowSpin == true`,非 XY 导航模式 | 触发 `Spin` 事件,方向 `Decrease` |
|
||
| 鼠标滚轮向上 | `AllowSpin == true`,控件获得键盘焦点 | 触发 `Spin` 事件,方向 `Increase` |
|
||
| 鼠标滚轮向下 | `AllowSpin == true`,控件获得键盘焦点 | 触发 `Spin` 事件,方向 `Decrease` |
|