UWP – 按空格时不要点击事件(如电影和电视应用程序)

我正在制作自定义媒体播放器,并尝试重现与电影和电视应用(Windows 10 CU)相同的行为。

无论如何, 空间都用于播放和暂停video。 在聚焦时, 空格 用于单击按钮(但输入是)。 这种行为打破了一些关于键盘可访问性的规则,但我认为没关系。 用于播放和暂停的空间是用户期望的。

问题是:他们是怎么做到的?

我发现了一些半解决方案:

解决方案1 Window.Current.CoreWindow.KeyDown以及if Click Event Handler

Page.xaml.cs:

 protected override void OnNavigatedTo(NavigationEventArgs e) { Window.Current.CoreWindow.KeyDown += CoreWindowOnKeyDown; //... } bool isItSpace; private void CoreWindowOnKeyDown(CoreWindow sender, KeyEventArgs args) { if (args.VirtualKey == VirtualKey.Space) isItSpace = true; } private void ButtonBase_OnClick(object sender, RoutedEventArgs e) { if (isItSpace) { isItSpace = false; return; } //... } 

Page.xaml:

  

为什么不:

  • 需要在每个Click Handler中添加if
  • 有按钮点击动画……

解决方案2Window.Current.CoreWindow.KeyDown禁用焦点按钮并在KeyUp启用它

就像是:

  if (FocusManager.GetFocusedElement() is Button) { var bu = (Button)FocusManager.GetFocusedElement(); bu.IsEnabled = false; } 

为什么不

  • 它从禁用按钮更改焦点。 启用后需要将其更改回来。 重点是跳..
  • 出现禁用和启用动画
  • 太hackie了

解决方案3 button.ClickMode = ClickMode.Hover

ClickMode设置为“ Hover ,无法使用键盘单击它。 当我在Window的KeyDown处理程序中更改它时(如解决方案2),它仍然第一次冒泡到Click事件。 解决方案可以将所有按钮设置为Hover ,但在这种情况下, Enter不会导致Click,我需要更改所有按钮…

你有什么更好的解决方案吗?

这个问题归结为,当您单击媒体命令栏中的按钮时,它会自动聚焦 ,而Enter键空格键等将自动触发按钮的操作。

因此,要解决此问题,您只需要找到一种方法来从中删除自动对焦。

在Windows 10 build 14393之前,您可以尝试在单击后手动将焦点设置为其他元素,但这对我来说就像是一个黑客。

在1 4393年 ,他们引入了一个名为AllowFocusOnInteraction的新属性,它可以在这种特殊情况下帮助你。 基本上,这样做的目的是在用户与控件交互后自动聚焦控件,因此焦点将保留在当前聚焦的元素上。

要应用此function,您需要获取MediaTransportControls控件的默认样式,您可以在其中访问所有媒体命令栏按钮。

然后你只需将AllowFocusOnInteraction="False"附加到除PlayPauseButton之外的所有AppBarButton (不要忘记Flyout的按钮,如AudioMuteButton !)。

我甚至会更进一步,在最初加载页面时手动将焦点设置在PlayPauseButton上。 因此,每当按下 Space键时,您将在此按钮上看到一个很好的按下视觉,以指示已调用播放/暂停操作。

另请注意,这样做不会影响键盘导航。 如果用户想要,他仍然可以使用Tab键在按钮之间导航。 因此一般用户可访问性不受影响。


更新

我个人希望任何有针对性的按钮能够在Space键盘上做出反应,但如果你想要与官方电影和电视应用程序完全相同的视觉行为,那也是可能的。

我们不是编写大量的代码隐藏,而是创建一个封装所有逻辑的ExtendedAppBarButton

这个想法与您的解决方案2非常相似,我们将使用

 AddHandler(KeyDownEvent, new KeyEventHandler(OnKeyDown), true); AddHandler(KeyUpEvent, new KeyEventHandler(OnKeyUp), true); 

每当按下Space键时切换IsEnabled 。 此外,我们将有一个特殊的IsPlayPauseButton依赖项属性,该属性订阅WindowKeyDown事件,以便在设置为True时手动调用按钮单击。

在我们的ExtendedAppBarButton的默认样式中,我们需要确保正确设置以下内容 –

      

请注意, UseSystemFocusVisuals设置为False ,因为我们正在创建自己的焦点视觉,以避免系统出现一个您已经注意到的闪烁问题。

  

此外,我们将删除Disabled状态内的Storybaord ,因为我们不希望在IsEnabled属性更改之间发生任何动画。

最后,您需要获取MediaTransportControls的默认样式,并将所有AppBarButton替换为我们刚刚创建的样式。

这里有很多东西,但是一旦你完成所有设置,你就不必担心在你的媒体页面上处理所有这些了。

我已经在这里创建了一个简单的演示项目,以防任何事情都不清楚。 随意检查出来。