• Windows Store 手势编程小结


    最近完成了一个Windows Store上面的手势操作的页面。在这里总结了一下经验和心得,希望能和大家一起分享和讨论一下。

    首先,要纠正一个误区,在Windows Store里面,手势和鼠标的操作事件是不区分的。比如简单的手指滑动事件,正常的写法还是在PointerPressed, PointerMoved和PointerReleased里面去处理。大家可能认为,手势的事件应该在,ManipulationStarted和ManipulationDelta等事件里面去处理。但是如果我们在Manipulation事件里面处理了,Pointer的事件依然会被触发,而且我们也并不能通过这样的方式区分是鼠标,还是手势触发了这个事件。

    文档上是这样说的,Tapped,Pointer和Manipulation,是三个级别的输入相应事件。Tapped 最高,Pointer是中间,Manipulation是底层。如果高级别的事件被触发,底层的事件也会被触发,反之则不然。所以,如果能在高层处理的事件,尽量在高层处理,否则底层会写的很复杂。比如手指滑动的事件,应该在Pointer层面上解决,他比Manipulation的层次高。

    Windows Store 列举了一些常用的手势。

    Tap

    一个手指的点击

    Press and hold

    一个手指点击并长按

    Slide

    一个或多个手指向同一方向滑动

    Swipe

    一个或多个手指向同一方向短距离滑动

    Pinch

    两个以上手指聚拢

    Rotate

    两个以上手指旋转

    Stretch

    两个以上手指分散

     

     

    Tapped 的事件是最高级的,但是要在UIElement里面声明才能用相应的事件。比如 TappedDoubleTapped,RightTapped, 和Holding 对应的就是 IsTapEnabled,IsDoubleTapEnabledIsRightTapEnabled, 和 IsHoldingEnabled

     

    Pointer的层面就可以处理类似于Slide或者Swipe之类的手势,但是这样的手势没有对应的事件,我们只能在Pointer里面处理,Pointer里面可以提供多点触摸的支持。我们可以通过

    PointerRoutedEventArgs. GetCurrentPoint 函数获取PointerPoint,这个函数的坐标系选取可以根据传入的Element来确定。在这个类里面,我们可以用PointerId去区分不同手指的操作。PointerDevice可以帮我们区别鼠标和手势。

     

    另外,在SelectionStates的VisualStateGroup里面,可以处理SelectedSwiping事件,这是在ListViewItem的template里面的,请参考http://msdn.microsoft.com/en-us/library/windows/apps/jj709921.aspx

     

    Manipulation是最低层,他可以处理旋转,缩放,还有速度,这里我就不详细说明了,大家可以参考

    http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.input.manipulationdeltaroutedeventargs.aspx

    和这个例程

    http://code.msdn.microsoft.com/windowsapps/Input-XAML-user-input-e61c8054

     

    Tips 1:

    我这次做的是播放器的页面,只是处理手指移动的事件,但在做的过程中,我发现区别鼠标和手势还是很麻烦的一件事情。我们可以通过Windows.Devices.Input.PointerDevice.GetPointerDevices API 去获得这个设备有哪些输入设备,但是我们不能确定用户当前使用的是鼠标或者是触摸的设备。

     

    我的做法就是在PointerPressed事件里面判断当前使用的设备,并且设置一个标示符,在PointerMoved 事件里面通过标示符来区分手势和鼠标的操作。手势可以在播放器里面直接控制进度和音量,但是鼠标的移动事件并不需要这样。

     

    另外,要区别手势的点击和滑动更是一个头痛的问题,因为无论是点击,还是滑动,都要激发PointerPressed, PointerMoved和PointerReleased,这三个事件。我曾经很傻很天真的认为,手势操作我只需要处理PointerMoved事件就好了。但是这种情况有时会有Pointer这个结构体为空的状况,我也不清楚为什么。后来的解决方案是,在PointerPressed事件里面建一个10个Pointer的List,在PointerMoved里面对这个List添加Poninter,如果小于10,退出,这个时候就是点击事件,超过10个就是滑动事件。

    Tip 2:

    关于延时隐藏的问题,一开始我是用动画做的,但是后来发现,动画做完之后那个属性被锁定了。再去操作就很难,后来就改用ThreadPoolTimer,起一个UI线程来修改的。我之前的同事是用DispatcherTimer 去做的,我觉得这个做法需要timer.start和timer.stop函数去辅助,有些繁琐。

     

    Tip 3:

    Image 控件有个bug 就是用代码修改Image.Source 会失效,尤其是快速的切换这个Source。之前我做过一个用很多图片切换,形成一个动画的效果。这个实现的思路类似于双缓冲,通过设置Visibility来切换前后的Image,把后面的Image的Source修改,然后呈现到前端,再把前端的Image切换到后面换Source,这样的做法效果还不错。但是如果图片没有那么多,我们直接在一个Grid里面放所有的Image 然后修改Visibility好了。

  • 相关阅读:
    C语言提供的位运算符
    JAVA反射改动常量,以及其局限
    直击中关村创业大街,新街头霸王来了
    bind() to 0.0.0.0:80 failed (98: Address already in use)
    Eclipse 快捷方式 指定 固定 workspace
    C++对象模型——Inline Functions(第四章)
    eclipse中安装freemarker插件及ftl使用freemarker编辑器
    迷茫了好一阵决定做WEB前端
    ios代理的使用,正向传值,逆向传值
    easyUI Tab href,content差别
  • 原文地址:https://www.cnblogs.com/zjjcy/p/3191444.html
Copyright © 2020-2023  润新知