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,额,这个要在以后慢慢琢磨了。

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

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

        

  

原文地址:https://www.cnblogs.com/DinoWu/p/4528816.html