UWP - 按空格时不要触发 Click 事件(如在电影和电视应用中) [英] UWP - Don't fire Click event when pressing space (like in Movies & TV app)

查看:12
本文介绍了UWP - 按空格时不要触发 Click 事件(如在电影和电视应用中)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am working on custom media player and trying to reproduce same behavior as in Movies & TV app (Windows 10 CU).

Space 用于 Play &无论如何都要暂停视频.空格 用于在按钮聚焦时单击按钮(但 Enter 是).此行为违反了有关键盘的一些规则 可访问性,但我认为还可以.Space 用于游戏和娱乐暂停是用户所期望的.

Space is used to Play & Pause video no matter what. Space is not used to click buttons when they are focused (but Enter is). This behavior breaks some rules about keyboard accessibility, but I think it is OK. Space for Play & Pause is something that user expect.

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

Question is: How they did it?

我找到了一些半解:

方案一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
  • 有按钮点击动画...

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

Solution 2 Disable focused Button in Window.Current.CoreWindow.KeyDown and enable it in KeyUp

类似于:

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

为什么不

  • 它改变了禁用按钮的焦点.启用后需要改回来.焦点在跳跃..
  • 禁用和启用动画显示
  • 它太黑了

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

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

When ClickMode is set to Hover it is not possible to Click it with keyboard. When I change it in KeyDown handler of Window (like solution 2) it still bubble to Click event for the first time. Solution could be set all buttons to Hover, but in that case Enter will not cause the Click and I need to change all buttons...

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

Are there any better solutions on your mind?

推荐答案

这个问题归结为,当你从媒体命令栏点击一个按钮时,它会自动获得焦点和keybaord键像 EnterSpace 会自动触发按钮的动作.

This issue comes down to, when you click on a button from the media command bar, it automatically gets focused, and keybaord keys like Enter or Space will automatically trigger the action of the button.

所以要解决这个问题,你只需要找到一种方法来消除它们的自动对焦.

So to solve the issue, you just need to find a way to remove the auto-focus from them.

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

Prior to Windows 10 build 14393, you can try manually setting the focus to some other element after the click, but this feels like a hack to me.

14393 中,他们引入了一个名为 AllowFocusOnInteraction 的新属性,它可以在这种特殊情况下为您提供帮助.基本上,这样做是为了在用户与其交互后自动聚焦控件,因此焦点将保持在当前聚焦的元素上.

In 14393, they introduced a new property called AllowFocusOnInteraction which can help you in this particular case. Basically, what this does is to not auto-focus a control after the user interacts with it, so the focus will remain on the currently focused element.

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

To apply this, you will need to obtain the default style of the MediaTransportControls control, where you can have access to all the media command bar buttons.

然后您只需将 AllowFocusOnInteraction="False" 附加到所有 AppBarButtons(不要忘记 Flyouts 内的按钮,例如 AudioMuteButton!) 除了 PlayPauseButton.

Then you just attach AllowFocusOnInteraction="False" to all the AppBarButtons (don't forget buttons inside Flyouts such as AudioMuteButton!) except the PlayPauseButton.

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

I would even go one step further to manually set the focus on the PlayPauseButton when the page is initially loaded. So after that whenever the Space key is hit, you will see a nice pressed visual on this button to indicate the play/pause action has been invoked.

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

Please also note doing this will not affect keybaord navigation. If the user wants, he can still use the Tab key to navigate between buttons. So general user accessibility is not affected.

我个人希望任何聚焦的按钮都能对 Space 按键做出反应,但如果您想要与官方 Films & 完全相同的视觉行为.电视应用程序,这也是可能的.

I personally would like any focused button to react on Space key press, but if you want the absolute same visual behavior as in the offical Films & TV app, that's possible too.

与其编写大量代码隐藏,不如创建一个封装所有逻辑的 ExtendedAppBarButton.

Rather than writting a lot of code-behind, let's create an ExtendedAppBarButton that encapsulates all the logic.

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

The idea is very similar with your Solution 2, we will use

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

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

to toggle IsEnabled whenever the Space key is pressed. Also, we will have a special IsPlayPauseButton dependency property that subscribes to the KeyDown event of the Window to manually invoke the button click, whenever it's set to True.

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

Inside the default style of our ExtendedAppBarButton, we need to make sure we have the following set properly -

<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,因为我们正在创建自己的焦点视觉效果,以避免系统出现您已经注意到的闪烁问题.

Note the UseSystemFocusVisuals is set to False 'cause we are creating our own focus visual to avoid the system one flashing issue that you have already noticed.

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

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

Also, we will remove the Storybaord inside the Disabled state as we don't want any animation to happen between the IsEnabled property changes.

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

Finally, you will need to obtain the default style of MediaTransportControls and replace all the AppBarButtons with the one we just created.

这里有很多事情要做,但是一旦您完成所有设置,您就无需担心在媒体页面上处理所有这些事情.

There's a lot of stuff going on here, but once you have everything setup, you don't need to worry about handling all these on your media pages ever.

我在这里创建了一个简单的演示项目,以防万一.请随意查看.

I have created a simple demo project here in case anything is unclear. Feel free to check it out.

这篇关于UWP - 按空格时不要触发 Click 事件(如在电影和电视应用中)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆