首页 文章

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

提问于
浏览
4

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

无论如何,空间都用于播放和暂停视频 . 空间 is not 用于在聚焦时单击按钮(但输入是) . 这种行为打破了关于键盘accessibility的一些规则,但我认为没关系 . 用于播放和暂停的空间是用户期望的 .

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

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

Solution 1 Window.Current.CoreWindow.KeyDownif in 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:

<Button  Click="ButtonBase_OnClick"  >Button Text</Button>

为什么不:

  • 需要在每个Click Handler中添加 if

  • 有按钮点击动画......

Solution 2Window.Current.CoreWindow.KeyDown 中禁用聚焦按钮并在 KeyUp 中启用它

就像是:

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

为什么不

  • 它从禁用按钮更改焦点 . 启用后需要将其更改回来 . 焦点是跳跃..

  • 禁用并启用动画

  • 太hackie了

Solution 3 button.ClickMode = ClickMode.Hover

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

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

1 回答

  • 5

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

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

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

    在14393年,他们引入了一个名为 AllowFocusOnInteraction 的新属性,它可以帮助你解决这个问题 . 基本上,这样做是为了在用户与之交互后自动聚焦控件,因此焦点将保留在当前聚焦的元素上 .

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

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

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

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


    更新

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

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

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

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

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

    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" />
    

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

    <Rectangle x:Name="FocusVisual"
               Opacity="0"
               StrokeThickness="2"
               Stroke="{TemplateBinding BorderBrush}" />
    

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

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

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

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

相关问题