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

12 KiB
Raw Blame History

Tooltip 文字提示

概述

文字提示(ToolTip)是一种轻量级的浮层提示组件,在鼠标悬浮到目标元素上时显示提示信息。它是图形界面中最常见的辅助信息展示方式——无需用户主动操作,只要将鼠标移至目标区域即可获得上下文提示。常见用途包括:解释图标含义、补充说明按钮功能、展示被截断的完整文本等。

AtomUI 的 ToolTip 控件完整复刻了 Ant Design 5.0 Tooltip 的设计规范,在 .NET / Avalonia 平台上提供与 Ant Design React 版一致的视觉体验和交互行为。

注意:AtomUI 中该控件命名为 ToolTip,通过附加属性方式使用(atom:ToolTip.Tip="xxx"),可附加到任意控件上。


设计原理

Ant Design 的 Tooltip 设计哲学

Ant Design 对 Tooltip 的定位是:「简单的文字提示气泡框」。它是最轻量的信息提示方式,相比 Popover(气泡卡片)和 Popconfirm(气泡确认框)更简洁、更专注。

Ant Design 的 Tooltip 设计原则:

原则 说明
轻量 仅承载简短文字,不建议放置复杂内容或交互控件
非干扰 悬浮触发、离开消失,不阻塞用户操作流程
辅助性 作为补充信息存在,不承载核心信息
上下文感知 通过箭头和定位明确关联目标元素

Ant Design Tooltip 的核心特性:

  • 12 种弹出方向:Top、Bottom、Left、Right 及各方向的对齐变体
  • 箭头指示器:明确指向目标元素,帮助用户建立视觉关联
  • 预设颜色与自定义颜色:支持使用调色板颜色或任意自定义颜色
  • 延迟控制:通过 mouseEnterDelay / mouseLeaveDelay 防抖,避免频繁弹出

Avalonia ToolTip 基础能力

Avalonia 框架内置了基础的 ToolTip 支持(Avalonia.Controls.ToolTip),提供简单的文字提示功能。AtomUI 的 ToolTip 是完全独立的实现,不继承 Avalonia 内置 ToolTip,而是继承自 ContentControl 并结合自定义的 ToolTipService 实现完整的提示逻辑。

AtomUI ToolTip 与 Avalonia 内置 ToolTip 的对比:

特性 Avalonia 内置 ToolTip AtomUI ToolTip
箭头指示器 ❌ 不支持 ✅ 支持(ArrowDecoratedBox)
弹出方向 基础方向 12 种精确方向
预设颜色 ❌ 不支持 ✅ Ant Design 14 色调色板
自定义颜色 ❌ 不支持 ✅ 任意 Color
弹出/关闭动画 ❌ 无 ✅ Motion 动画系统
Design Token ❌ 无 ✅ 完整 Token 集成
阴影效果 ❌ 无 ✅ Token 驱动的阴影
箭头居中指向 ❌ 不支持 ✅ IsPointAtCenter

AtomUI 的实现设计

AtomUI 的 ToolTip 通过附加属性模式工作——不需要将 ToolTip 作为控件放到可视树中,而是通过 ToolTip.Tip 附加属性将提示信息关联到任意目标控件上。当鼠标悬浮到目标控件时,ToolTipService 负责创建 ToolTip 实例并通过 Popup 弹出。

功能 实现方式 设计动机
附加属性模式 ToolTip.Tip 附加属性 任何控件都可以添加 Tooltip,无需修改控件模板
12 种弹出方向 Placement 附加属性 + PopupUtils 全方位定位,自动计算锚点和重力方向
箭头指示器 ArrowDecoratedBox 内部控件 通过几何绘制的三角箭头明确指向目标元素
箭头居中指向 IsPointAtCenter + 偏移计算 箭头精确指向目标中心,而非气泡边缘
预设颜色 PresetColor + PresetPrimaryColor 调色板 使用 Ant Design 调色板的 14 种标准颜色
自定义颜色 Color 附加属性 任意背景色,满足品牌定制需求
延迟显示 ShowDelay / BetweenShowDelay + DispatcherTimer 防抖,避免鼠标快速滑过时频繁弹出
位置翻转 Popup.PositionFlipped 事件处理 当空间不足时自动翻转方向,箭头随之调整
弹出/关闭动画 MotionAwareOpen / MotionAwareClose 平滑的淡入淡出动画,可通过 IsMotionEnabled 控制
Design Token ToolTipToken + RegisterTokenResourceScope 所有视觉值从 Token 派生,支持主题切换

功能详解

附加属性使用模式

ToolTip 通过附加属性附加到任意控件上,核心附加属性包括:

  • atom:ToolTip.Tip:设置提示内容(可以是字符串,也可以是任意控件)
  • atom:ToolTip.Placement:设置弹出方向(默认 Top)
  • atom:ToolTip.IsShowArrow:是否显示箭头(默认 true)

当 Tip 为字符串时,ToolTip 内部通过 StringToTextBlockConverter 自动将字符串转换为 TextBlock,并设置自动换行(TextWrapping="Wrap")。

12 种弹出方向

通过 Placement 附加属性(PlacementMode 枚举)控制 ToolTip 的弹出位置:

          TL    Top    TR
           ┌──────────┐
      LT   │          │   RT
      Left │  Target  │   Right
      LB   │          │   RB
           └──────────┘
          BL   Bottom   BR

每种方向对应不同的锚点(PlacementAnchor)和重力(PlacementGravity)计算。当目标控件靠近屏幕边缘导致空间不足时,Popup 会自动翻转方向,ToolTip 通过 PopupFlippedEventArgs 事件同步调整箭头位置。

箭头控制

箭头由内部的 ArrowDecoratedBox 控件绘制,提供三种模式:

模式 属性设置 效果
显示箭头 IsShowArrow="True"(默认) 箭头指向目标控件方向的边缘
隐藏箭头 IsShowArrow="False" 不显示箭头,仅显示气泡框
箭头居中 IsShowArrow="True" + IsPointAtCenter="True" 箭头精确指向目标控件的中心点

注意:在某些弹出方向组合下(如 PlacementAnchor 和 PlacementGravity 不兼容),箭头会被自动禁用。这通过 PopupUtils.CanEnabledArrow() 判断。

颜色系统

ToolTip 提供三层颜色控制,按优先级从高到低:

  1. 预设颜色(PresetColor):使用 Ant Design 调色板的 14 种标准颜色(Blue、Red、Green、Orange、Gold、Yellow、Lime、Cyan、GeekBlue、Purple、Pink、Magenta、Volcano、Grey),颜色值由 PresetPrimaryColor.GetColor() 统一获取。
  2. 自定义颜色(Color):使用任意 Color 值作为 ToolTip 背景色。
  3. 默认颜色:由 ToolTipToken.ToolTipBackground 控制(通常为深灰/黑色),文字为白色(ToolTipToken.ToolTipColor)。

设置 PresetColor 或 Color 后,背景色会覆盖默认 Token 值,文字色保持不变。

ToolTipService(内部服务)

ToolTipService 是 ToolTip 系统的核心引擎,负责监听全局输入事件并管理 ToolTip 的显示/隐藏生命周期:

职责 实现方式
监听鼠标移动 订阅 IInputManager.Process,处理 RawPointerEventArgs
命中测试 沿可视树向上遍历,找到设置了 ToolTip.Tip 的最近控件
延迟显示 根据 ShowDelay 启动 DispatcherTimer
快速切换 根据 BetweenShowDelay 判断是否跳过延迟直接显示
自动关闭 鼠标离开目标控件/窗口时关闭,鼠标按下时关闭
自定义控制 IsCustomShowAndHide="True" 时跳过自动关闭逻辑

与 Ant Design 规范的对齐程度

特性 Ant Design (React) AtomUI (Avalonia) 对齐情况
12 种方向 placement ✅ ✅ PlacementMode 枚举 ✅ 完全对齐
箭头 arrow ✅ true / false / { pointAtCenter } ✅ IsShowArrow + IsPointAtCenter ✅ 完全对齐
预设颜色 color ✅ 预设名或自定义色 ✅ PresetColor + Color ✅ 完全对齐
延迟 mouseEnterDelay ✅ 秒 ✅ ShowDelay 毫秒 ✅ 对齐(单位不同)
连续延迟 mouseLeaveDelay ✅ ✅ BetweenShowDelay ✅ 对齐
自定义内容 ✅ ReactNode ✅ Tip 接受任意 object ✅ 对齐
受控模式 open ✅ ✅ IsOpen + IsCustomShowAndHide ✅ 对齐
打开回调 onOpenChange ✅ ✅ ToolTipOpening / ToolTipClosing 事件 ✅ 对齐
destroyTooltipOnHide ✅ ❌ Popup 复用 ⚠️ 无需,Avalonia 自动管理生命周期
getPopupContainer ✅ 指定挂载节点 ❌ 不适用 — 桌面端无 DOM 容器概念
overlayStyle / overlayClassName ✅ ❌ 通过 Style 选择器实现 ✅ Avalonia 方式等效
zIndex ✅ ❌ 由 Popup 系统自动管理 ✅ Avalonia 自动管理
fresh ✅ 5.10.0+ 强制重新渲染 ❌ 暂未支持 ⚠️ 待评估

继承关系

Avalonia.Controls.Primitives.TemplatedControl
  └── Avalonia.Controls.ContentControl
        └── AtomUI.Desktop.Controls.ToolTip
              ├── implements IMotionAwareControl
              ├── implements IArrowAwareShadowMaskInfoProvider (internal)
              └── implements IPopupHostProvider

注意:ToolTip 没有设备无关的基类(AtomUI.Controls 中无 AbstractToolTip),因为 ToolTip 的交互行为(鼠标悬浮触发)本身具有桌面端特性。未来移动端可能采用长按触发等不同交互方式,因此两端实现可能差异较大,不适合抽取共享基类。

各层级职责划分:

层级 提供的能力
ContentControl 任意内容容纳、Content / ContentTemplate、ContentPresenter 模板化呈现
AtomUI.Desktop.Controls.ToolTip Ant Design 视觉体系(箭头/方向/颜色)、附加属性接口、Design Token 集成、ToolTipService 交互服务、弹出动画、阴影效果

实现的接口:

接口 定义位置 作用
IMotionAwareControl AtomUI.Core 支持 IsMotionEnabled 动画开关
IArrowAwareShadowMaskInfoProvider AtomUI.Controls(internal) 为阴影渲染提供箭头感知的遮罩信息(圆角、边界、箭头位置)
IPopupHostProvider Avalonia.Controls 提供 Popup 宿主信息,用于弹出层管理

源码位置

层级 文件路径 说明
控件类 src/AtomUI.Desktop.Controls/Tooltip/Tooltip.cs ToolTip 控件及附加属性
服务类 src/AtomUI.Desktop.Controls/Tooltip/ToolTipService.cs ToolTip 交互服务(内部)
Token 定义 src/AtomUI.Desktop.Controls/Tooltip/ToolTipToken.cs 组件级 Design Token
主题模板 src/AtomUI.Desktop.Controls/Tooltip/Themes/ToolTipTheme.axaml ControlTheme AXAML
主题常量 src/AtomUI.Desktop.Controls/Tooltip/Themes/ToolTipThemeConstants.cs 模板部件名称常量
Gallery 示例 controlgallery/AtomUIGallery/ShowCases/Views/DataDisplay/TooltipShowCase.axaml 使用范例

模板结构

ToolTip 的 ControlTemplate 结构简洁,以 ArrowDecoratedBox 为核心容器:

ArrowDecoratedBox (PART_ToolTipContainer)           ← 箭头装饰盒子(承载背景、圆角、箭头绘制、阴影)
└── ContentPresenter (PART_ToolTipContentPresenter)  ← 内容展示器(字符串自动转为 TextBlock)

设计特点:

  • ArrowDecoratedBox:是 AtomUI 中专门用于箭头弹出组件的共享容器,在 ToolTip、Popover、Popconfirm 等组件中复用。它负责绘制三角箭头、管理内容区域圆角、计算箭头顶点位置。
  • StringToTextBlockConverter:当 Content 为字符串时,自动转换为带自动换行的 TextBlock(TextWrapping="Wrap"),确保长文本正确显示。
  • 背景色绑定:ArrowDecoratedBox.Background 通过 TemplateBinding 绑定到 ToolTip 的 Background 属性,当设置 PresetColor 或 Color 时,ToolTip 会更新 Background,进而驱动 ArrowDecoratedBox 的背景和箭头颜色同步变化。

模板部件常量

常量名 值 说明
ToolTipThemeConstants.ToolTipContainerPart "PART_ToolTipContainer" 箭头装饰盒子容器
ToolTipThemeConstants.ToolTipContainerPresenterPart "PART_ToolTipContentPresenter" 内容展示器