Files

9.1 KiB
Raw Permalink Blame History

HyperLinkButton 超链接按钮

概述

超链接按钮(HyperLinkButton)是一个外观类似超链接的按钮控件,支持点击后自动打开浏览器导航到指定 URI。它继承了 Button 的所有能力(尺寸、图标、加载状态、命令绑定),但视觉上呈现为链接文本的样式,用于需要跳转或导航的场景。

HyperLinkButton 对应 Ant Design Button 的 type="link" 变体,但在 AtomUI 中被提取为一个独立的控件类,提供了更丰富的链接交互能力(如 NavigateUri 自动导航、IsVisited 已访问状态跟踪)。


设计原理

Ant Design 的链接按钮设计

Ant Design 的按钮体系中,Button type="link" 是视觉权重最低的按钮变体——无背景、无边框,仅保留链接色文字。它的设计意图是暗示导航而非操作,适合放在内容流中作为跳转入口。在 Web 环境中,Ant Design 通过 href 属性支持真实的超链接导航。

AtomUI 的扩展设计

AtomUI 将链接按钮提取为独立的 HyperLinkButton 控件,主要基于以下考量:

  1. 桌面端导航需求:桌面应用同样有「打开浏览器」的导航需求,需要 NavigateUri + Launcher.LaunchUriAsync 集成
  2. 已访问状态:Web 浏览器天然支持 :visited 伪类,桌面端需要显式实现 IsVisited 属性和对应的伪类
  3. 关注点分离:链接按钮的颜色体系(ColorLink 系列)和交互模式(导航而非操作)与普通 Button 有本质区别,独立为专用控件更清晰
扩展能力 实现方式 设计动机
真实导航 NavigateUri 属性 + Launcher.LaunchUriAsync 桌面端的超链接跳转,对齐 Ant Design 的 href
已访问状态 IsVisited 属性 + :visited 伪类 跟踪链接是否已被点击过,可进行视觉区分
三种尺寸 ISizeTypeAware 接口 + SizeType 共享属性 与全局尺寸体系一致
危险样式 IsDanger 属性 + :danger 伪类 红色链接,适用于危险操作(删除、移除等)
幽灵模式 IsGhost 属性 背景透明,适用于有色背景场景
加载状态 IsLoading 属性 + LoadingOutlined 图标 旋转图标 + 降低不透明度,用于异步操作等待
图标支持 Icon 属性(PathIcon 类型) 在链接文本前显示图标
过渡动画 IMotionAwareControl + Transitions 前景色、背景色平滑过渡
Design Token 复用 ButtonToken 作用域 间距和字体 Token 与 Button 共享,颜色使用链接色系

导航机制

当设置 NavigateUri 属性后,点击按钮触发以下流程:

  1. 调用 OnClick() 基类方法(触发 Click 事件和 Command 执行)
  2. 检查 NavigateUri 是否不为 null
  3. 通过 TopLevel.GetTopLevel(this).Launcher.LaunchUriAsync(uri) 异步打开系统默认浏览器
  4. 导航成功后自动将 IsVisited 设为 true,激活 :visited 伪类

注意:即使设置了 NavigateUri,Click 事件和 Command 仍然会正常触发。NavigateUri 是额外的导航行为,不会替代 Button 的基本点击机制。


功能详解

链接导航(NavigateUri)

通过 NavigateUri 属性设置目标 URI:

  • 支持任意 URI 格式(https://、mailto:、file:// 等)
  • 点击后异步调用系统 Launcher 打开默认程序
  • 导航成功后 IsVisited 自动设为 true
  • 导航失败(如无效 URI)时 IsVisited 保持不变

已访问状态(IsVisited)

  • 导航成功后自动设置
  • 可通过 :visited 伪类在样式中进行视觉区分
  • 可手动设置 IsVisited = true/false 来控制状态
  • 可通过数据绑定持久化已访问记录

危险样式(IsDanger)

通过 IsDanger 属性启用红色链接样式:

  • 正常态使用 ColorError
  • 悬浮态使用 ColorErrorHover
  • 按下态使用 ColorErrorActive
  • 图标颜色同步切换

加载状态(IsLoading)

当 IsLoading = true 时:

  1. :loading 伪类被激活
  2. 原图标隐藏,替换为旋转的 LoadingOutlined 图标
  3. 整体不透明度降至 SharedToken.OpacityLoading

过渡动画

HyperLinkButton 在加载时配置以下过渡动画:

  • Background:背景色渐变过渡
  • Foreground:前景色(文本色)渐变过渡

通过 IsMotionEnabled 属性可控制是否启用过渡动画。


与 Ant Design 规范的对齐程度

特性 Ant Design (React) AtomUI (Avalonia) 对齐情况
链接样式 ✅ Button type="link" ✅ HyperLinkButton ✅ 完全对齐
三种尺寸 size ✅ large / medium / small ✅ SizeType 属性 ✅ 完全对齐
图标 icon ✅ ReactNode ✅ Icon 属性(PathIcon) ✅ 完全对齐
危险样式 danger ✅ 布尔属性 ✅ IsDanger 属性 ✅ 完全对齐
加载中 loading ✅ 布尔属性 ✅ IsLoading 属性 ✅ 完全对齐
禁用 disabled ✅ 布尔属性 ✅ IsEnabled 属性 ✅ 完全对齐
真实导航 href ✅ href + target ✅ NavigateUri ✅ 完全对齐(桌面端通过系统 Launcher)
已访问状态 — (浏览器原生) ✅ IsVisited + :visited 伪类 ✅ AtomUI 扩展
幽灵模式 ghost ✅ 布尔属性 ✅ IsGhost 属性 ✅ 完全对齐

继承关系

Avalonia.Controls.Primitives.TemplatedControl
  └── Avalonia.Controls.ContentControl
        └── Avalonia.Controls.Button (ICommandSource, IClickableControl)
              └── AtomUI.Controls.Commons.AbstractHyperLinkButton (ISizeTypeAware, IMotionAwareControl)
                    └── AtomUI.Desktop.Controls.HyperLinkButton

跨平台架构

HyperLinkButton 遵循 AtomUI 的两层控件模型:

层级 类 职责
基类(AtomUI.Controls) AbstractHyperLinkButton 设备无关的共享行为:属性定义、导航逻辑、伪类管理、过渡动画配置
桌面端(AtomUI.Desktop.Controls) HyperLinkButton 注册 ButtonToken 作用域,桌面端特定的主题和样式

各层级职责划分:

层级 提供的能力
Avalonia.Controls.Button 指针交互 → Click 事件、ICommand 绑定、IsPressed 状态、HotKey 快捷键、Flyout 弹出
AbstractHyperLinkButton NavigateUri + Launcher 导航、IsVisited 已访问追踪、SizeType 尺寸、IsDanger / IsGhost / IsLoading 状态、Icon 图标、IsMotionEnabled 动画开关、伪类管理
HyperLinkButton ButtonToken 作用域注册(复用 Button 的间距/字体 Token)

实现的共享接口:

接口 定义位置 作用
ISizeTypeAware AtomUI.Controls.Shared 支持 SizeType(Small / Middle / Large)三种尺寸切换
IMotionAwareControl AtomUI.Controls.Shared 支持动画开关,控制过渡动画的启用/禁用

源码位置

层级 文件路径 说明
基类 src/AtomUI.Controls/Buttons/AbstractHyperLinkButton.cs 设备无关基类(行为、属性、导航逻辑)
伪类常量 src/AtomUI.Controls/Buttons/ButtonPseudoClass.cs 共享伪类定义(与 Button 共用)
控件类 src/AtomUI.Desktop.Controls/Buttons/HyperLinkButton.cs 桌面端具体实现
主题模板 src/AtomUI.Desktop.Controls/Buttons/Themes/HyperLinkButtonTheme.axaml ControlTheme AXAML
模板常量 src/AtomUI.Desktop.Controls/Buttons/Themes/ButtonThemeConstants.cs 模板部件名称常量(与 Button 共用)
Gallery 使用 controlgallery/AtomUIGallery/ShowCases/Views/General/AboutUsPage.axaml 实际使用示例

模板结构

HyperLinkButton 采用简洁的单层 Border + StackPanel 布局:

Border#Frame                                ← 主框架(承载 Padding、CornerRadius)
└── StackPanel#PART_MainInfoLayout          ← 内容布局容器(水平排列、居中对齐)
    ├── LoadingOutlined#PART_LoadingIcon     ← 加载旋转图标(默认隐藏,:loading 时显示)
    ├── IconPresenter#PART_ButtonIcon        ← 按钮图标展示器(默认显示,:loading 时隐藏)
    └── ContentPresenter#PART_ContentPresenter  ← 文本内容

与 Button 模板的区别:

  • 无波纹层:HyperLinkButton 不使用 WaveSpiritDecorator(链接按钮不需要点击波纹)
  • 无阴影层:链接按钮无阴影效果
  • 无焦点指示器层:使用更简洁的焦点样式
  • 背景始终透明:正常态和幽灵态背景均为透明

模板部件常量

HyperLinkButton 复用 ButtonThemeConstants 中的常量:

常量名 值 说明
ButtonThemeConstants.MainInfoLayoutPart "PART_MainInfoLayout" 内容布局面板
ButtonThemeConstants.LoadingIconPart "PART_LoadingIcon" 加载旋转图标
ButtonThemeConstants.ButtonIconPart "PART_ButtonIcon" 按钮图标展示器
ButtonThemeConstants.ContentPresenterPart "PART_ContentPresenter" 内容展示器