ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

WinUI TeachingTip 控件完整实战指南:半持久化内容丰富的 Flyout 交互设计

WinUI TeachingTip 控件完整实战指南:半持久化内容丰富的 Flyout 交互设计 WinUI TeachingTip 控件完整实战指南半持久化内容丰富的 Flyout 交互设计【免费下载链接】microsoft-ui-xamlWinUI: a modern UI framework with a rich set of controls and styles to build dynamic and high-performing Windows applications.项目地址: https://gitcode.com/GitHub_Trending/mi/microsoft-ui-xamlTeachingTip 是 WinUImicrosoft-ui-xaml中一种半持久化semi-persistent、内容丰富的浮出控件用于向用户告知、提醒或教学新功能与重要更新。它既能以尖角tail精确指向某个 UI 元素也能作为无目标提示悬浮在窗口边缘。本文将以仓库中 TeachingTipSpec.md 为核心骨架结合 控件源码 与 IDL 定义完整讲解 TeachingTip 的适用场景、13 种放置模式、按钮/图标/Hero 内容定制、轻触关闭light-dismiss、取消与延迟关闭事件以及无障碍与键盘/游戏手柄导航细节帮助你直接上手编写可运行的高质量引导提示。什么是 TeachingTip何时该用它原文定义A teaching tip is a semi-persistent and content-rich flyout that provides contextual information.TeachingTip 的典型用途是将用户注意力聚焦到新功能、重要更新或非必需但能改善体验的选项上或者教会用户如何完成某个任务。它可以通过尖角tail精确指向屏幕上的某个 UI 元素增强上下文清晰度完全不设置 Target作为无目标提示悬浮在窗口边缘由用户显式关闭点击右上角 X 或底部 Close 按钮或以**轻触关闭light-dismiss**方式在用户滚动或点击其他区域时自动消失。什么时候不应该用因为 TeachingTip 是瞬态的所以不推荐用它提示错误或重要的状态变更——这类信息应该使用 ContentDialog、InfoBar 等更持久、更需要用户确认的控件。原文档对此有明确说明这也是选择控件时的第一判断标准。推荐使用原则来自原文档 Recommendations提示内容应是非关键的不要在其中放置对应用体验至关重要的信息或选项避免过于频繁地弹出提示将提示分散在较长的会话或多个会话中才能让每条提示获得用户的独立关注保持简短、主题清晰研究表明用户平均只阅读 3-5 个单词、理解 2-3 个单词就会决定是否与提示交互对于预测会使用游戏手柄gamepad输入的应用务必参考 XY 焦点导航相关设计并在所有可能的 UI 配置下逐一测试每条提示的手柄可达性仓库源码TeachingTipAutomationPeer与焦点处理也印证了这一点详见后文输入与无障碍。基础用法创建一个 TeachingTip原文档提供了两种声明方式放置在 ResourceDictionary / 资源中或直接放在元素树element tree中。两种方式行为完全一致——TeachingTip 只在IsOpen true时显示不占据布局空间。有目标Targeted的 TeachingTip以下 XAML 演示默认外观通过Target属性绑定到按钮标题与副标题随之显示Button x:NameSaveButton ContentSave Button.Resources controls:TeachingTip x:NameAutoSaveTip Target{x:Bind SaveButton} TitleSave automatically SubtitleWhen you save your file to OneDrive, we save your changes as you go - so you never have to. /controls:TeachingTip /Button.Resources /Button在代码后置中控制显示时机例如首次启动时展示一次public MainPage() { this.InitializeComponent(); if (!HaveExplainedAutoSave()) { AutoSaveTip.IsOpen true; SetHaveExplainedAutoSave(); } }无目标Non-targeted的 TeachingTip当提示内容与屏幕上某个元素无关时不设置Target提示将相对于 XamlRoot 的边缘显示同时通过TailVisibilityCollapsed隐藏尖角Button x:NameSaveButton ContentSave / controls:TeachingTip x:NameAutoSaveTip TitleSaving automatically SubtitleWe save your changes as you go - so you never have to. /controls:TeachingTip从 TeachingTip.h 源码可以看到控件内部维护了m_target引用并在UpdateTail()中处理无目标且 TailVisibility 非 Visible 时折叠尖角的逻辑DetermineEffectivePlacement()则根据m_target是否存在分流到DetermineEffectivePlacementTargeted()/DetermineEffectivePlacementUntargeted()两套完全不同的放置算法。放置模式PreferredPlacement13 种模式与回退策略TeachingTip 复刻了 Flyout 的FlyoutPlacementMode行为通过TeachingTipPlacementMode枚举实现完整枚举见 TeachingTip.idlenum TeachingTipPlacementMode { Auto, Top, TopRight, TopLeft, Right, RightTop, RightBottom, Bottom, BottomRight, BottomLeft, Left, LeftTop, LeftBottom, Center, };默认行为有目标默认尝试放置在目标上方无目标默认放置在 XamlRoot底部居中与 Flyout 相同若首选放置模式空间不足将自动选择其他模式。有目标的放置语义放置模式第一个词表示提示将居中对齐于目标的哪一侧尖角tail始终位于该侧的中心并指向目标若存在第二个词则提示主体向该方向偏移。例如BottomLeft表示提示出现在目标下方、主体向左偏移。Center是唯一的特例尖角指向目标中心提示主体居中于目标上半部分。Button x:NameSaveButton ContentSave Button.Resources controls:TeachingTip x:NameAutoSaveTip Target{x:Bind SaveButton} TitleSaving automatically SubtitleWe save your changes as you go - so you never have to. PreferredPlacementBottomLeft /controls:TeachingTip /Button.Resources /Button无目标的放置语义第一个词表示提示居中对齐于 XamlRoot 的哪一侧有第二个词时提示会靠向对应角落。注意无目标模式下两个词的顺序不影响结果——TopRight与RightTop等价。Center会让提示出现在 XamlRoot 的水平和垂直中心。源码级回退算法从 TeachingTip.cpp 的GetPlacementFallbackOrder()可以看到真实的回退优先级算法维护一个 13 项优先级数组初始顺序为 Top → Bottom → Left → Right → 四个角 → 四个边 → Center然后根据首选方向做交换排序首选为 Bottom 系将 Bottom 提到 Top 之前首选为 Left/Right 系将横向Left/Right提到纵向之前Right 系再把 Right 提到 Left 之前最后用std::rotate把首选模式旋转到第一位。随后DetermineEffectivePlacementTargeted()对 13 种模式逐一计算可用性目标是否足够大、是否有足够空间、尖角是否保持 12px 边缘间距等见原文档Placement行为说明按优先级返回第一个可用模式若 13 种模式全部不可用返回tipDoesNotFit true此时 TeachingTip 将不会打开而是迭代完整的事件生命周期强制关闭并在调试模式下通过TeachingTipTestHooks记录因无空间而未打开的遥测计数。原文档特别警告如果应用在 Closing 事件中取消了关闭提示可能保持打开且没有可访问的关闭按钮。非首选因素placement 不考虑的条件根据原文档以下条件在放置时不会被优先考虑提示无足够空间完整显示而不被裁剪目标不够大无法维持提示对齐且保持尖角距提示边缘 12px目标元素过大无法在保持尖角居中的同时维持边缘对齐。放置边距PlacementMarginPlacementMargin控制有目标提示与目标之间、无目标提示与 XamlRoot 边缘之间的间距。与FrameworkElement.Margin相同它有 Left/Right/Top/Bottom 四个值只有与当前放置方向相关的值会被使用——例如PlacementMargin.Left仅在提示位于目标左侧或 XamlRoot 左边缘时生效。Button x:NameSaveButton ContentSave / controls:TeachingTip x:NameAutoSaveTip TitleSaving automatically SubtitleWe save your changes as you go - so you never have to. PreferredPlacementBottomLeft PlacementMargin80 /controls:TeachingTip以上示例将无目标提示的四个方向边距都设为 80。在源码中PositionPopup()/PositionTargetedPopup()/PositionUntargetedPopup()分别使用这些边距计算最终偏移UntargetedTipNearPlacementOffset、UntargetedTipFarPlacementOffset等工具函数直接读取s_untargetedTipWindowEdgeMargin与 PlacementMargin 求和。内容区、按钮、图标与 Hero Content添加内容Content任意 XAML 内容都可以放入Content属性文本、图片、视频、动画、复选框、超链接等。内容超出提示高度时会自动启用滚动条。Button x:NameSaveButton ContentSave Button.Resources controls:TeachingTip x:NameAutoSaveTip Target{x:Bind SaveButton} TitleSaving automatically SubtitleWe save your changes as you go - so you never have to. StackPanel CheckBox x:NameHideTipsCheckBox ContentDont show tips at start up IsChecked{x:Bind HidingTips, ModeTwoWay} / TextBlockYou can change your tip preferences in Hyperlink NavigateUriapp:/item/SettingsPageSettings/Hyperlink if you change your mind./TextBlock /StackPanel /controls:TeachingTip /Button.Resources /Button添加按钮默认情况下标题右侧显示一个标准的X 关闭按钮。可通过CloseButtonContent自定义关闭按钮文案——此时按钮会移动到提示底部。另外可通过ActionButtonContent添加自定义操作按钮并可选配ActionButtonCommand与ActionButtonCommandParameter注意轻触关闭light-dismiss启用的提示不会显示任何关闭按钮。Button x:NameSaveButton ContentSave Button.Resources controls:TeachingTip x:NameAutoSaveTip Target{x:Bind SaveButton} TitleSaving automatically SubtitleWe save your changes as you go - so you never have to. ActionButtonContentDisable ActionButtonCommandDisableAutoSave CloseButtonContentGot it! StackPanel CheckBox x:NameHideTipsCheckBox ContentDont show tips at start up IsChecked{x:Bind HidingTips, ModeTwoWay} / TextBlockYou can change your tip preferences in Hyperlink NavigateUriapp:/item/SettingsPageSettings/Hyperlink if you change your mind./TextBlock /StackPanel /controls:TeachingTip /Button.Resources /Button在 TeachingTip.xaml 模板中可以看到ButtonsStates状态组NoButtonsVisible/ActionButtonVisible/CloseButtonVisible/BothButtonsVisible与CloseButtonLocations状态组HeaderCloseButton/FooterCloseButton共同决定两个按钮的可见性、列位置与间距AlternateCloseButton则是标题旁的无边框 X 按钮其样式来自AlternateCloseButtonStyle主题资源。Hero Content通栏内容通过HeroContent属性添加拉伸到提示边缘的通栏媒体内容如图片、视频并用HeroContentPlacement将其置于提示顶部或底部Button x:NameSaveButton ContentSave Button.Resources controls:TeachingTip x:NameAutoSaveTip Target{x:Bind SaveButton} TitleSaving automatically SubtitleWe save your changes as you go - so you never have to. controls:TeachingTip.HeroContent Image SourceAssets/cloud.png / /controls:TeachingTip.HeroContent /controls:TeachingTip /Button.Resources /Button模板中的HeroContentPlacementStatesHeroContentTop/HeroContentBottom通过HeroContentBorder的 Grid.Row 与圆角转换器实现上下切换。值得注意的细节源码UpdateDynamicHeroContentPlacementToTop/Bottom与行为表Tail/Hero Content Avoidance为避免尖角从 Hero Content 中长出的视觉怪相控件会依次尝试将 Hero 内容移到顶部或底部HeroContentPlacement非 Auto 时禁用、沿提示边缘平移尖角edge-aligned 放置时禁用、更换提示放置模式非 Auto 放置时禁用。添加图标IconSource使用IconSource在标题/副标题旁添加图标推荐尺寸为 16px、24px、32pxButton x:NameSaveButton ContentSave Button.Resources controls:TeachingTip x:NameAutoSaveTip Target{x:Bind SaveButton} TitleSaving automatically SubtitleWe save your changes as you go - so you never have to. controls:TeachingTip.IconSource controls:SymbolIconSource SymbolSave / /controls:TeachingTip.IconSource /controls:TeachingTip /Button.Resources /Button模板中IconPresenter通过绑定TemplateSettings.IconElement渲染图标IconStates状态组控制有无图标时的间距TeachingTipTemplateSettings类见 TeachingTip.idl还暴露TopRightHighlightMargin/TopLeftHighlightMargin两个 Thickness用于让容器顶部 1px 高光边缘避让尖角保持视觉连续。轻触关闭Light-dismissIsLightDismissEnabled默认关闭。开启后提示会在用户滚动或与应用其他元素交互时自动消失因此当提示需要放置在可滚动区域中时轻触关闭是最佳方案。开启后控件会自动移除关闭按钮以向用户表明其轻触关闭行为模板LightDismissStates状态组同时会把背景切换为TeachingTipTransientBackground半透明画刷。Button x:NameSaveButton ContentSave / controls:TeachingTip x:NameAutoSaveTip TitleSaving automatically SubtitleWe save your changes as you go - so you never have to. IsLightDismissEnabledTrue /controls:TeachingTip源码层面CreateLightDismissIndicatorPopup()会创建专门的m_lightDismissIndicatorPopup用于捕获提示之外的点击/滚动OnLightDismissIndicatorPopupClosed()回调负责按LightDismiss原因触发关闭流程。IDL 中TeachingTipCloseReason枚举的三个成员CloseButton/LightDismiss/Programmatic正是Closing/Closed事件参数Reason的取值来源。逃逸 XamlRoot 边界ShouldConstrainToRootBounds在Windows 19H1 及以上版本设置ShouldConstrainToRootBoundsFalse可以让提示逃逸 XamlRoot 与屏幕边界始终按设定的PreferredPlacement定位。官方强烈建议同时启用IsLightDismissEnabled并将PreferredPlacement设为最接近 XamlRoot 中心的模式以保证最佳体验。在更早的 Windows 版本上该属性会被忽略提示始终约束在 XamlRoot 内。Button x:NameSaveButton ContentSave / controls:TeachingTip x:NameAutoSaveTip TitleSaving automatically SubtitleWe save your changes as you go - so you never have to. PreferredPlacementBottomRight PlacementMargin-80,-50,0,0 ShouldConstrainToRootBoundsFalse /controls:TeachingTip从 TeachingTip.cpp 的DetermineEffectivePlacement()可以看到当ShouldConstrainToRootBounds()为 false 时放置算法切换到GetEffectiveScreenBoundsInCoreWindowSpace()得到的屏幕边界而非窗口边界源码注释也指出由于缺少多显示器 API 信息超出根边界的场景不做特殊计算默认返回首选值或 Top该行为可通过SetReturnTopForOutOfWindowPlacement测试钩子调整。取消与延迟关闭Closing / Closed 事件Closing事件可用于**取消cancel或延迟defer**提示的关闭以便保持提示打开、为某个动作或自定义动画争取时间。关键行为关闭被取消时IsOpen会回到 true延迟期间deferral 未完成时IsOpen保持 false程序化关闭同样可以被取消。controls:TeachingTip x:NameEnableNewSettingsTip TitleNew ways to protect your privacy! SubtitlePlease close this tip and review our updated privacy policy and privacy settings. ClosingOnTipClosing /controls:TeachingTippublic async void OnTipClosing(object sender, TeachingTipClosingEventArgs args) { if (args.Reason TeachingTipCloseReason.CloseButton) { using (args.GetDeferral()) { bool success await UpdateUserSettings(User thisUsersID); if (!success) { // We were not able to update the settings! // Dont close the tip and display the reason why. args.Cancel true; ShowLastErrorMessage(); } } } }重要警告原文档原文强调如果没有任何放置选项能让提示完整显示提示会迭代完整的事件生命周期以强制关闭而不是在缺少可访问关闭按钮的情况下显示。如果应用此时取消了Closing事件提示可能保持打开且没有可访问的关闭按钮。IDL 中TeachingTipClosingEventArgs暴露Reason只读、Cancel可写与GetDeferral()TeachingTipClosedEventArgs只暴露Reason。另外仓库源码中还有一个[MUX_PREVIEW]的Opened事件TeachingTipOpenedEventArgs用于打开完成的回调。重新配置已打开的提示Reconfiguring部分内容与属性可以在提示打开期间修改并立即生效但以下变更必须关闭并重新打开才会生效图标属性IconSourceAction / Close 按钮相关属性在轻触关闭与显式关闭之间切换。特别注意原文档警告在提示打开时从手动关闭manual-dismiss切换到轻触关闭会先移除关闭按钮再启用轻触关闭行为提示可能卡在屏幕上无法关闭。事件与 API 速查Notable PropertiesAPI Notes 原表属性说明TailVisibility获取或设置提示尖角是折叠还是保持可见Auto / Visible / CollapsedPreferredPlacement获取或设置提示的默认放置模式ShouldConstrainToRootBounds获取或设置提示是否约束在根边界内Events原表事件说明ActionButtonClick操作按钮被点击后发生CloseButtonClick关闭按钮被点击后发生Closed提示关闭后发生Closing提示即将开始关闭时发生完整属性清单来自 IDL含默认值属性类型 / 默认值Title / SubtitlestringIsOpenbool默认falseTargetFrameworkElementTailVisibility默认AutoActionButtonContent / ActionButtonStyle / ActionButtonCommand / ActionButtonCommandParameterobject / Style / ICommand / objectCloseButtonContent / CloseButtonStyle / CloseButtonCommand / CloseButtonCommandParameterobject / Style / ICommand / objectPlacementMarginThicknessShouldConstrainToRootBoundsbool默认trueIsLightDismissEnabledbool默认falsePreferredPlacement默认AutoHeroContentPlacement默认AutoHeroContent / IconSourceUIElement / IconSourceTemplateSettingsTeachingTipTemplateSettings只读视觉与行为组件详解原文档 Appendix视觉组件Visual Components组件说明Container提示主体封装所有组件非模态内容高度/宽度超过上限时启用垂直滚动外缘有随尖角贴合的过程描边顶部边缘有 1px 高光并随尖角贴合Title半粗体在关闭按钮与容器边框处自动换行Subtitle在关闭按钮与容器边框处自动换行Content可定制任意 XAML 内容超过高度时滚动位于 Subtitle 下方、关闭/操作按钮上方Close Button默认在右上角显示 XRTL 语言自动移到左上角可设置为底部常规按钮也可完全隐藏以便在内容区自定义关闭方式轻触关闭时完全不显示Action Button允许用户触发自定义事件这是开箱提供的唯一非关闭按钮Tail指向屏幕 UI 元素的三角形延伸TailVisibility为 Auto 时有目标自动显示、无目标自动隐藏优先居中于目标距提示边缘保持12px间距不参与动画无阴影非矩形表面暂不支持阴影Icon默认位于标题/副标题左侧RTL 时自动移到右侧Hero Content拉伸到提示边缘的媒体可置于顶部或底部Scroll Bar内容过大时出现在内容区不会与右上角 X 按钮相交关于 Tail 的形状细节源码注释TeachingTip.h特别说明尖角设计为 8x16 像素形状实际实现为 10x20 形状并部分被提示内容遮挡这样可以让提示边框沿尖角形状贴合而无需在尖角与提示主体相接的边上画边框。同时MinimumTipEdgeToTailEdgeMargin()等函数精确计算了尖角与边缘的最小间距。行为组件Behavioral Components行为说明Opening通过IsOpen true显示带开启动画若任何位置都无足够空间完整显示则不会打开并将 IsOpen 覆写为 falseClosing三种关闭方式程序设IsOpenfalse、用户点击关闭按钮、轻触关闭用TeachingTipCloseReason区分可用Canceltrue阻止关闭可用 deferral 异步响应Placement有目标放置遵循 Flyout 先例Center使尖角指向元素中心无目标放置覆盖窗口每侧、每角与中心不优先考虑无足够空间、目标过小、目标过大无法保持尖角居中Light-dismiss用户滚动或点击应用其他区域时关闭Persistent Tip Location打开后提示不会随目标移动窗口调整大小除外Motion内置开/关动画可通过 Storyboard 自定义源码中CreateExpandAnimation/CreateContractAnimation默认展开 300ms、收起 200ms均可用测试钩子调整Tail/Hero Content Avoidance依次尝试移动 Hero 内容、平移尖角、更换放置模式避免尖角与 Hero 内容相交Out of Window Bounds新系统上可用ShouldConstrainToRootBoundsfalse让提示逃逸窗口改用屏幕边界参与放置算法输入与无障碍Inputs AccessibilityUI Automation 模式TeachingTip 会在持久提示与轻触关闭提示之间切换 Pane / Window 自动化模式可滚动内容区提供IScrollProvider实现自定义的tip Landmark模板中ContentRootGrid设置了AutomationProperties.LandmarkTypeCustom与规范一致。键盘导航状态操作提示出现无需任何操作即可调用提示提示获得焦点F6提示被加入 F6 区域导航停止点可用 F6 进入/离开TabNarrator 激活时提示自动加入 Narrator 导航停止点顶部类似 Popup / ContentDialog可通过 Tab 进入Tab 遍历提示Tab按顺序遍历所有可操作项在最后一个元素上按 Tab焦点循环回第一个元素左右方向键两个底部按钮都存在时可在其间导航Esc关闭提示提示被关闭1. 按 X 按钮2. 按关闭按钮3. 按操作按钮。Tab 使焦点前进到下一元素但不会关闭提示NarratorTeachingTip 复用 Windows 通知使用的现有 API。有目标提示会注入其目标名称在标题前与标题一起被 Narrator 朗读提供目标上下文。通知语音流程Click Up to move to new notification from App 名 提示内容触摸屏设备上可通过Swipe遍历所有可操作项在最后一项再次滑动会将焦点移到 Narrator 的全屏隐形关闭按钮双击屏幕关闭窗口再次滑动移出提示。游戏手柄Gamepad状态操作提示出现无需操作提示获得焦点空间导航spatial navigation可访问提示官方建议为提示可达性与测试做合理设计提示被导航空间导航遍历可操作项A 键交互如按下操作/关闭按钮B 键关闭提示提示被关闭1. 头部 X 按钮2. 底部关闭按钮3. 操作按钮4. B 键将焦点还给之前聚焦的元素原文档明确提醒TeachingTip 的手柄可达性并不被保证因此针对预测手柄输入的应用必须用应用 UI 的所有可能配置逐一测试。结语一段可复制的完整示例结合以上所有特性下面是一个同时包含目标、内容、Hero 内容、图标、双按钮与延迟关闭检查的完整示例可直接在 WinUI 3 应用中运行Button x:NameSaveButton ContentSave Button.Resources controls:TeachingTip x:NameAutoSaveTip Target{x:Bind SaveButton} TitleSaving automatically SubtitleWe save your changes as you go - so you never have to. PreferredPlacementBottom PlacementMargin12 ActionButtonContentDisable CloseButtonContentGot it! ClosingOnTipClosing controls:TeachingTip.IconSource controls:SymbolIconSource SymbolSave / /controls:TeachingTip.IconSource controls:TeachingTip.HeroContent Image SourceAssets/cloud.png / /controls:TeachingTip.HeroContent StackPanel CheckBox ContentDont show tips at start up / /StackPanel /controls:TeachingTip /Button.Resources /Buttonprivate void OnTipClosing(TeachingTip sender, TeachingTipClosingEventArgs args) { if (args.Reason TeachingTipCloseReason.CloseButton) { // 在此执行必要的清理若失败则 args.Cancel true 阻止关闭 } }后续你可以阅读 控件源码 深入放置算法、动画与焦点处理查看 API 测试 与 交互测试 了解已验证的行为矩阵在 TestUI 页面 中探索控件在真实应用里的各种配置形态参考 视觉组件附录图片Container、Title、ScrollBar 等核对控件外观规格。【免费下载链接】microsoft-ui-xamlWinUI: a modern UI framework with a rich set of controls and styles to build dynamic and high-performing Windows applications.项目地址: https://gitcode.com/GitHub_Trending/mi/microsoft-ui-xaml创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表