使用语音调用 UI 元素
启用了语音的 Shell (VES) 是 Windows 语音平台的一种扩展,可在应用中实现一流的语音体验,使用户可以使用语音来调用屏幕控件和通过听写插入文本。 VES 致力于在所有 Windows Shell 和设备上提供通用的端到端“看到它,说出来”体验,并尽可能减少应用开发人员所需的工作量。 为实现此目标,它利用 Microsoft 语音平台和 UI 自动化 (UIA) 框架。
用户体验演练
下面概述了用户在 Xbox 上使用 VES 时的体验,在深入了解 VES 工作原理的详细信息之前,它应该可帮助设置上下文。
用户打开 Xbox 控制台,并且要浏览其应用以查找感兴趣的内容:
用户:“你好小娜,打开我的游戏和应用”
用户保持处于主动侦听模式 (ALM),这意味着控制台现在正在侦听用户调用屏幕上可见的控件,而无需每次都说“你好小娜”。 用户现在可以切换到查看应用并滚动浏览应用列表:
用户:“应用程序”
若要滚动视图,用户可以只需说:
用户:“向下滚动”
用户看到他们感兴趣的应用的框图,但忘记了名称。 用户要求显示语音提示标签:
用户:“显示标签”
现在已经清楚该说什么,可以启动应用了:
用户:“电影和电视”
若要退出主动聆听模式,用户需告知 Xbox 停止聆听:
用户:“停止聆听”
稍后,可以通过以下方式启动新的主动聆听会话:
用户:“你好小娜,进行选择”或“你好小娜,选择”
UI 自动化依赖项
VES 是UI 自动化客户端,依赖于应用通过其 UI 自动化提供程序公开的信息。 这是 Windows 平台上的讲述人功能已使用的基础结构。 通过 UI 自动化可以编程方式访问用户界面元素,包括控件的名称、其类型和实现的控件模式。 当 UI 在应用中更改时,VES 会响应 UIA 更新事件,并重新分析更新的 UI 自动化树以查找所有可操作项,使用此信息构建语音识别语法。
所有 UWP 应用都可以访问 UI 自动化框架,并且可以公开有关 UI 的信息,而不依赖于它们所构建的图形框架(XAML、DirectX/Direct3D 等)。 在某些情况下(如 XAML),大部分的繁重工作由框架完成,从而大大减少了支持讲述人和 VES 所需的工作。
有关 UI 自动化的详细信息,请参阅 UI 自动化基础知识。
控件调用名称
VES 采用以下启发式方法来确定要向语音识别器注册为控件名称的短语(即用户为调用控件而需要说的内容)。 这也是将在语音提示标签中显示的短语。
按优先级顺序排序的名称源:
- 如果元素具有
LabeledBy
附加属性,则 VES 会使用此文本标签的AutomationProperties.Name
。 - 元素的
AutomationProperties.Name
。 在 XAML 中,控件的文本内容会用作AutomationProperties.Name
的默认值。 - 如果控件是列表项或按钮,则 VES 会查找具有有效
AutomationProperties.Name
的第一个子元素。
可操作控件
如果 VES 实现以下自动化控件模式之一,则它会将控件视为可操作:
InvokePattern(例如,按钮)- 表示用于启动或执行单个明确操作的控件,并且这些控件在激活时不保持其状态。
TogglePattern(例如,复选框)- 表示一个控件,该控件可以在一组状态之间循环,并在设置后保持状态。
SelectionItemPattern(例如,组合框)- 表示一个控件,该控件充当可选子项集合的容器。
ExpandCollapsePattern(例如,组合框)- 表示控件,用于以可视化方式展开来显示内容或者以可视化方式折叠来隐藏内容。
ScrollPattern(例如,列表)- 表示充当子元素集合的可滚动容器的控件。
可滚动容器
对于支持 ScrollPattern 的可滚动容器,VES 会侦听语音命令(如“向左滚动”、“向右滚动”等),并且在用户触发其中一个命令时,将使用适当的参数调用 Scroll。 滚动命令基于 HorizontalScrollPercent
和 VerticalScrollPercent
属性的值进行注入。 例如,如果 HorizontalScrollPercent
大于 0,则添加“向左滚动”;如果小于 100,则添加“向右滚动”,等等。
讲述人重叠
讲述人应用程序也是一种 UI 自动化客户端,将 AutomationProperties.Name
属性用作对当前所选 UI 元素读取的文本的源之一。 为了提供更好的辅助功能体验,许多应用开发人员依靠使用较长描述性文本重载 Name
属性,目标是在讲述人阅读时提供更多信息和上下文。 但是,这会导致两个功能之间发生冲突:VES 需要与控件的可见文本匹配或紧密匹配的较短短语,而讲述人可从更长、更具描述性的短语中受益,以提供更好的上下文。
为了解决此问题,从 Windows 10 创意者更新开始,讲述人已更新为也查看 AutomationProperties.HelpText
属性。 如果此属性不为空,则讲述人会讲述其内容以及 AutomationProperties.Name
。 如果 HelpText
为空,则讲述人仅阅读名称的内容。 这样便可在需要时使用较长的描述性字符串,但在 Name
属性中维持容易进行语音识别的较短短语。
有关详细信息,请参阅 UI 中辅助功能支持的自动化属性。
主动聆听模式 (ALM)
进入 ALM
在 Xbox 上,VES 不会一直聆听语音输入。 用户需要通过说出以下内容来显式进入主动聆听模式:
- “你好小娜,选择”,或
- “你好小娜,请选择”
有其他几个 Cortana 命令还会在完成时使用户保持主动侦听模式,例如“你好小娜,登录”或“你好小娜,去主页”。
进入 ALM 会具有以下效果:
Cortana 覆盖层会显示在右上角,告知用户他们可以说出所看到的内容。 用户说话时,语音识别器识别的短语片段也会显示在此位置。
VES 会分析 UIA 树,查找所有可操作控件,在语音识别语法中注册其文本,并启动连续聆听会话。
退出 ALM
在用户使用语音与 UI 交互时,系统会保留在 ALM 中。 可通过两种方式退出 ALM:
- 用户明确说“停止侦听”,或者
- 如果在进入 ALM 的 17 秒内或是自上次正识别后没有正识别,则会出现超时
调用控件
在 ALM 中时,用户可以使用语音与 UI 交互。 如果 UI 配置正确(具有与可见文本匹配的名称属性),则使用语音执行操作应该是无缝的自然体验。 用户应该能够只需说出在屏幕上看到的内容。
Xbox 上的覆盖层 UI
VES 为控件派生的名称可能与 UI 中的实际可见文本不同。 这可能是因为控件的 Name
属性或附加 LabeledBy
元素显式设置为不同的字符串。 或者,控件没有 GUI 文本,而只有图标或图像元素。
在这些情况下,用户需要一种方法来查看为调用此类控件而需要说出的内容。 因此,在处于主动侦听模式后,可以通过说“显示标签”来显示语音提示。 这会使语音提示标签出现在每个可操作控件顶部。
标签数限制为 100 个;因此,如果应用的 UI 具有的可操作控件多于 100 个,则有些控件不会显示语音提示标签。 在这种情况下,选择哪些标签不是确定性的,因为这取决于 UIA 树中首次枚举的当前 UI 的结构和组成。
显示语音提示标签后,没有用于隐藏它们的命令,这些标签会保持可见,直到发生以下事件之一:
- 用户调用控件
- 用户导航离开当前场景
- 用户说“停止侦听”
- 主动聆听模式超时
语音提示标签的位置
语音提示标签在控件的 BoundingRectangle 中水平和垂直居中。 当控件较小且紧密分组时,标签可能会重叠/被其他标签遮盖,VES 会尝试将这些标签分开,确保它们可见。 但是,这不能保证在 100% 的时间内都有效。 如果存在非常拥挤的 UI,则可能会导致某些标签被其他标签遮盖。 请使用“显示标签”查看 UI,以确保有足够的空间用于显示语音提示。
组合框
展开组合框时,组合框中的每个项都会获得其自己的语音提示标签,并且通常位于下拉列表后面的现有控件顶部。 为了避免呈现混乱且令人困惑的标签(其中组合框项标签与组合框后面控件的标签混合在一起),当组合框展开时,只显示其子项的标签;所有其他语音提示标签都会隐藏。 用户随后可以选择下拉项之一或“关闭”组合框。
折叠组合框上的标签:
展开组合框上的标签:
可滚动控件
对于可滚动控件,滚动命令的语音提示会在控件的每个边缘上居中。 语音提示只针对可操作的滚动方向进行显示。例如,如果垂直滚动不可用,则“向上滚动”和“向下滚动”不会显示。 当存在多个可滚动区域时,VES 将使用序号来区分(例如。“向右滚动 1”、“向右滚动 2”等)。
消除歧义
当多个 UI 元素具有相同名称,或者语音识别器匹配了多个候选项时,VES 会进入消除歧义模式。 在此模式下,会为所涉及的元素显示语音提示标签,以便用户可以选择正确标签。 用户可以通过说出“取消”来退出消除歧义模式。
例如:
在主动聆听模式下,解除消除歧义模式之前;用户说出“我不明确”:
两个按钮都匹配;消除歧义模式已启动:
选择了“选择 2”时显示单击操作:
示例 UI
下面是基于 XAML 的 UI 的示例,以各种方式设置 AutomationProperties.Name:
<Page
x:Class="VESSampleCSharp.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:VESSampleCSharp"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Button x:Name="button1" Content="Hello World" HorizontalAlignment="Left" Margin="44,56,0,0" VerticalAlignment="Top"/>
<Button x:Name="button2" AutomationProperties.Name="Launch Game" Content="Launch" HorizontalAlignment="Left" Margin="44,106,0,0" VerticalAlignment="Top" Width="99"/>
<TextBlock AutomationProperties.Name="Day of Week" x:Name="label1" HorizontalAlignment="Left" Height="22" Margin="168,62,0,0" TextWrapping="Wrap" Text="Select Day of Week:" VerticalAlignment="Top" Width="137"/>
<ComboBox AutomationProperties.LabeledBy="{Binding ElementName=label1}" x:Name="comboBox" HorizontalAlignment="Left" Margin="310,57,0,0" VerticalAlignment="Top" Width="120">
<ComboBoxItem Content="Monday" IsSelected="True"/>
<ComboBoxItem Content="Tuesday"/>
<ComboBoxItem Content="Wednesday"/>
<ComboBoxItem Content="Thursday"/>
<ComboBoxItem Content="Friday"/>
<ComboBoxItem Content="Saturday"/>
<ComboBoxItem Content="Sunday"/>
</ComboBox>
<Button x:Name="button3" HorizontalAlignment="Left" Margin="44,156,0,0" VerticalAlignment="Top" Width="213">
<Grid>
<TextBlock AutomationProperties.Name="Accept">Accept Offer</TextBlock>
<TextBlock Margin="0,25,0,0" Foreground="#FF5A5A5A">Exclusive offer just for you</TextBlock>
</Grid>
</Button>
</Grid>
</Page>
在此处使用上面的示例是带有和不带语音提示标签的 UI 的外观。
在主动聆听模式中,不显示标签:
在主动聆听模式中,在用户说出“显示标签”后:
对于 button1
,XAML 使用控件可见文本内容中的文本自动填充 AutomationProperties.Name
属性。 这便是即使未设置显式 AutomationProperties.Name
,也存在语音提示标签的原因。
对于 button2
,我们将 AutomationProperties.Name
显式设置为控件文本以外的其他内容。
对于 comboBox
,我们使用 LabeledBy
属性引用 label1
作为自动化 Name
的源。在 label1
中,我们将 AutomationProperties.Name
设置为比屏幕上呈现的内容更自然的短语(“星期几”而不是“选择星期几”)。
最后,对于 button3
,VES 从第一个子元素抓取 Name
,因为 button3
本身未设置 AutomationProperties.Name
。