Windows 10 开发日记(三)-- 如何在手势开始之前判断手指数量

这是我们在实际项目中经常要面临的问题,因为你很可能会出现这种需求:单手操作与双手操作的行为不同,在手势开始之时就需要知道到底是单手还是双手。

方案一:  

了解了这个需求之后,我迅速凭借经验,感觉在ManipulationStarting或者ManipulationStarted事件传入的参数中应该类似于e.GetPointers()类似的方法,用于获得当前有多少个手指在屏幕上。感觉三年的Windows 开发经验终于有了点小用,节省了我好多效率不免心生有预感。。。但是当寻找了半天之后,胸中顿时有几万只草泥马奔腾而过,不是说的是底层事件吗?底层事件连最简单的判断有几个手指头都不行么?TouchFrame才叫底层事件好吗???

    public class ManipulationStartedRoutedEventArgs : RoutedEventArgs, IManipulationStartedRoutedEventArgs
    {
        public ManipulationStartedRoutedEventArgs();

        public UIElement Container { get; }
        public ManipulationDelta Cumulative { get; }
        public System.Boolean Handled { get; set; }
        public PointerDeviceType PointerDeviceType { get; }
        public Point Position { get; }

        public void Complete();
    }

  各位请看,我不会冤枉好人的,根本就没有一个集合性的东西,这个Point倒是手指在屏幕上的接触点,但是这都是Started事件了好么?我要的是在Started之前就知道有几个手指头跟屏幕接触好么?

方案二:

抱着”微软虐我千百遍,我待微软如初恋"的心态,我继续寻找方案二。心想:如果我能获得这个容器,甚至我获取这个App所在的Frame,应该有暴露方法判断有多少个手指吧。具体的过程我就不说了,神马UIElement,Control,Frame,都没有啊,都没有。

方案三:

     抱着“人在屋檐下,不得不低头”的心态,我继续寻找方案三,(毕竟技术是你微软的,项目是我的,还得继续啊,一万只草泥马又呼啸而来。。。),去MSDN上面扒了扒跟输入相关的知识点,终于发现了一个东西,并且是一个比较熟悉的东西:PointerPressed,中级事件,这个事件我们上篇已经做过实验了,它会在ManipulationStarting之前触发,就是说,如果我在这个事件触发之时,能获取手指的个数,那我就能解决这个问题了!(https://msdn.microsoft.com/en-us/library/windows/apps/xaml/jj150606.aspx, 这篇文章详细介绍了Pointer相关的知识,有兴趣的朋友可以去看看,草泥马统统不见了,前途一片光明啊,哈哈哈)

可以这么说,每一次点击都会触发一次PointerPressed事件,并且这个事件带来的参数能够获得接触点的信息,这个信息包含了PointerID,就是说,每一次点击,系统会标识这个接触点,松开后系统回收这个标记,那么我们本地可以实现一个字典,以PointerID为key,对应的Pointer为Value,那么在OnManipulationStarting事件中我就能判断是几个手指啦,说干就干

        private Dictionary<uint, Point?> _contacts; //与屏幕接触的点的集合

        /// <summary>
        /// 手指按下
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPointerPressed(PointerRoutedEventArgs e)
        {
            //if (e.Pointer.PointerDeviceType != Windows.Devices.Input.PointerDeviceType.Mouse)
            //{
                _contacts[e.Pointer.PointerId] = e.GetCurrentPoint(this).Position;
            //}
            e.Handled = true;
        }

        /// <summary>
        /// 手指离开
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPointerReleased(PointerRoutedEventArgs e)
        {
            //if (e.Pointer.PointerDeviceType != Windows.Devices.Input.PointerDeviceType.Mouse)
            //{
                if (_contacts.ContainsKey(e.Pointer.PointerId))
                {
                    _contacts[e.Pointer.PointerId] = null;
                    _contacts.Remove(e.Pointer.PointerId);
                }
            //}
            e.Handled = true;
        }

        /// <summary>
        /// 手指放上只会出发starting事件,要移动才开始触发started事件
        /// </summary>
        /// <param name="e"></param>
        protected override void OnManipulationStarted(ManipulationStartedRoutedEventArgs e)
        {
            int count = _contacts.Count;

            if (count == 1)
            {// 如果这时手指只有一根,则认为在对比模式
                _viewController.OnManipulationStarted(e);
            }
            else if (count > 1)
            {// 如果手指超过一根,则认为在缩放模式下
                e.Handled = true;
            }
        }

      哇哈哈哈哈,到了这个时候,功能做完了,是时候回过头来看看,为什么ManipulationStarting不能提供GetPoints()的方法。从实验的结果来看,ManipulationStarting应该还是只针对单次操作来说的,又或者说,ManipulationStarting只是一个“预备”的动作,并不能做很多事情。但是ManipulationDelta又可以判断双手操作中的:Scale,额,这个要在以后慢慢琢磨了。

如果你也遇到了在操作之前判断手指的情况,这篇文章对你应该会有帮助。

手势部分就到此,因为我在项目中也仅仅遇到了这些问题,不排除后续还有更复杂的情况出现,或者又扩展了很多其他问题。

时间: 2024-10-25 13:38:06

Windows 10 开发日记(三)-- 如何在手势开始之前判断手指数量的相关文章

Windows 10 开发日记(二)-- 手势顺序调研

前文再续,书接上一回. 上回说到Windows10手势分为高中低三个档次,于是心血来潮想要研究一下这三个等级的操作顺序是如何的?Manipulation手势的几个事件的触发顺序又是怎么样的,什么时候触发Starting,什么时候触发Started?UserControl自身有一个虚方法:OnManipulationStarting,OnManipulationStarted,它同时又有ManipulationStarted,ManipulationStarted事件,为什么功能类似的东西要有不同

Windows 10 开发日记(五)-- 当Binding遇到异步 -- 解决方案

前文再续,上一章提出了问题,本章提出了三种解决方案: 解决方案一:手动进行异步转换,核心思想:将binding做的事情放入CodeBehind FilterItemControl.XAML: <Grid> <Image x:Name="FilterImage" Stretch="UniformToFill"/> <Grid VerticalAlignment="Bottom" Height="20"

Windows 10 开发日记(四)-- 当Binding遇到异步 -- 问题的引出

Binding之于MVVM来说的重要性无需多说,Binding之于DataTemplate来说的重要性也无需多说,Binding的重要性也无需多说,异步也不用多说了,今天就到此为止吧... -------------------------------------------------冷冷的分割线------------------------------------------------------ 但是,当你要binding的数据是一个需要异步操作的结果的时候呢? 这是我们在项目中遇到的

Windows移动开发(三)——闭关修炼

上一次,我们了解了委托,委托和Lambda表达式结合是一件灰常灰常爽的事情,这也是只有.Net才有,自己偷着笑去吧.几天这次,我要介绍一下继承和多态,这是进行面向对象编程必须熟练掌握的技术和思想. 1.1 类 继承,儿子继承父亲的遗产,这是生活中的体现,在面向对象的编程中,父亲和儿子都是对象的抽象集合,也就是类.什么是类呢?就是一些具有共同特征的对象集合,例如:狗都有四条腿,一条尾巴,两只眼睛,狗都会游泳,都爱吃骨头,所以我们把具有以上特征的动物抽象成狗,我们进行面向对象编程也是这样,面向对象的

Windows 10开发基础——XML和JSON (二)

主要内容: Linq to XML Newtonsoft.Json.Linq来解析JSON 博客园RSS(http://www.cnblogs.com/rss)的解析 UWP调用自己实现的Web API 1.Linq to XML     Linq to XML不是一个新鲜的话题了,网上以及各种资料对这个介绍都比较多.今天就简单了解下,不做深入的研究...在代码中生成XML文档,使用Linq to XML会比Windows.Data.Xml.Dom命名空间下的类简单,使用起来也更加灵活.Linq

Windows 10开发基础——文件、文件夹和库(一)

主要内容: 1.枚举查询文件和文件夹 2.文本文件读写的三种方法——创建写入和读取文件 3.获得文件的属性 枚举查询文件和文件夹 先了解一下文件查询的几个方法: StorageFolder.GetFilesAsync: 获取当前文件夹中的所有文件,返回一个 IReadOnlyList<StorageFile>集合 IReadOnlyList<StorageFile> fileList =await picturesFolder.GetFilesAsync(); StorageFol

Windows 10开发基础——指针事件和操作事件(一)

主要内容: 1.指针事件 2.操作事件 1.指针事件 指针事件由各种活动输入源引发,包括触摸.触摸板.笔和鼠标(它们替代传统的鼠标事件).指针事件基于单一输入点(手指.笔尖.鼠标光标),但不支持基于速度的交互.下面是指针事件列表及其相关的事件参数列表: 事件或类 描述 PointerPressed 单根手指触摸屏幕时发生. PointerReleased 该同一触摸接触抬起时发生. PointerMoved 在屏幕上拖动指针时发生. PointerEntered 在指针进入元素的点击测试区时发生

Windows 10开发基础——文件、文件夹和库(二)

主要内容: 使用选取器打开和保存文件 关于文件.文件夹和库,如果深究其实还是有比较多的内容,我们这一次来学习一下选取器就收了.还有上篇博文中读写文本文件的三种方式可以细细体会一下. 文件选取器包含文件打开选取器(FileOpenPicker.FolderPicker)和文件保存选取器(FileSavePicker),分别用来打开文件和保存文件,这两个选取器的使用方法大致相同. FileOpenPicker类: ViewMode ,获取或设置文件选取器用来展示文件或文件夹的视图模式,属性值由Pic

(OpenCV) VS2013 + opencv-2.4.10.exe + Windows 10 开发环境配置

主要配置2点: - Windows 环境变量. - VC++ 配置. STEP BY STEP: 1. 双击 ”opencv-2.4.10.exe“,解压到本地文件夹 “C:\ ". 2. 设置环境变量: 2.1) 新建User variables: Variable name: OPENCV, Variable value:  C:\opencv\build 2.2) 编辑 System variables 中的 Path 变量, 添加: %OPENCV%\x86\vc12\bin 3. 设置