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

查看:116
本文介绍了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).

空格用于播放&无论如何都暂停视频.空格 用于在按钮被聚焦时单击按钮(但 Enter 则用于单击按钮).此行为违反了有关键盘

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?

我找到了一半解决方案:

I found some half-solutions:

解决方案1 ​​ Click事件处理程序

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

解决方案2 Window.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?

推荐答案

这个问题可归结为,当您从媒体命令栏中单击按钮时,它会自动成为 focused 和keybaord键例如 Enter Space 会自动触发按钮的操作.

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内部版本 14393 之前,您可以尝试在单击后将焦点手动设置为其他元素,但这对我来说就像是hack.

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.

要应用此功能,您将需要获取

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" 附加到所有 AppBarButton (不要忘记 Flyout 中的按钮,例如 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 键时,您都会在此按钮上看到被按下的按下画面,表明已调用了play/pause动作.

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 按键作出反应,但是如果您希望与官方电影和电视电影绝对相同的视觉行为电视应用,这也是可能的.

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 依赖项属性,该属性订阅 Window KeyDown 事件,以在设置时手动调用按钮单击到 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天全站免登陆