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

Ala*_*bra 4 c# xaml uwp

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

Space用于播放和暂停视频,无论如何.Space 不是用于在聚焦时点击按钮(但是Enter).这种行为打破了一些关于键盘可访问性的规则,但我认为没关系.SpacePlay和Pause是用户期望的.

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

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

方案1 Window.Current.CoreWindow.KeyDownifClick 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;
     }
    //...
 }
Run Code Online (Sandbox Code Playgroud)

Page.xaml:

<Button  Click="ButtonBase_OnClick"  >Button Text</Button>
Run Code Online (Sandbox Code Playgroud)

为什么不:

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

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

就像是:

    if (FocusManager.GetFocusedElement() is Button)
    {
        var bu = (Button)FocusManager.GetFocusedElement();
        bu.IsEnabled = false;
    }
Run Code Online (Sandbox Code Playgroud)

为什么不

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

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

ClickMode设置为Hover是不可能与键盘点击它.当我在KeyDownWindow的处理程序中更改它时(如解决方案2),它仍然第一次冒泡到Click事件.解决方案可以设置所有按钮Hover,但在这种情况下Enter不会导致Click和我需要更改所有按钮...

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

Jus*_* XL 5

这个问题归结到,当你点击从媒体命令栏按钮,就自动聚焦,并keybaord键,如EnterSpace将自动触发按钮的作用.

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

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

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

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

然后你只需要附上AllowFocusOnInteraction="False"所有的AppBarButtons(不要忘记Flyouts 里面的按钮,比如AudioMuteButton!)除了PlayPauseButton.

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

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


更新

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

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

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

AddHandler(KeyDownEvent, new KeyEventHandler(OnKeyDown), true);
AddHandler(KeyUpEvent, new KeyEventHandler(OnKeyUp), true);
Run Code Online (Sandbox Code Playgroud)

按下键IsEnabled时切换Space.此外,我们将有一个特殊的IsPlayPauseButton依赖项属性,只要设置为,就会订阅手动调用按钮单击的KeyDown事件.WindowTrue

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

<Setter Property="Width" Value="{ThemeResource MTCMediaButtonWidth}" />
<Setter Property="Height" Value="{ThemeResource MTCMediaButtonHeight}" />
<Setter Property="AllowFocusOnInteraction" Value="False" />
<Setter Property="AllowFocusWhenDisabled" Value="True" />
<Setter Property="UseSystemFocusVisuals" Value="False" />
Run Code Online (Sandbox Code Playgroud)

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

<Rectangle x:Name="FocusVisual"
           Opacity="0"
           StrokeThickness="2"
           Stroke="{TemplateBinding BorderBrush}" />
Run Code Online (Sandbox Code Playgroud)

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

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

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

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