• android 多点触控


      本文转自:http://blog.csdn.net/woshimalingyi/article/details/50383578

    一、MotionEvent事件的分类

          触控分为两类:单点触控多点触控

          1、如何获取触控事件信息?

            安卓中使用32位(int)来存储触控事件的动作信息触控索引。高16位暂时不用,后16位中高8位存储触控信息,低8位存储动作信息。

            在安卓当中,使用ACTION_MASK、ACTION_MASK_SHIFT、ACTION_POINTER_INDEX_MASK、ACTION_POINTER_INDEX_SHIFT这四个属性来获得触控事件信息。

            属性说明:

             ACTION_MASK = 8(0x00ff)  :动作信息掩码,用于截取目标动作信息;

             ACTION_MASK_SHIFT = 8(0x00ff) : 截取动作信息时所需移位个数

             ACTION_POINTER_INDEX_MASK =65280(0xff00) :高8位的位置信息掩码,用于截取索引信息

             ACTION_POINTER_INDEX_SHIFT= 8(0x00ff) :截取触控索引时所需的移位个数

            如果我们想要获取当前触控的全部信息,则使用

                            getAction();返回的是触控的所有信息

            如果我们仅仅需要获取当前触控的动作信息,则使用

                            getActionMasked();返回当前触控的动作信息,即低8位的信息

            如果我们想要获取的是当前触控的索引(比如:当你要监听是哪一个手指离开屏幕)

                            getActionIndex();可以达到效果,返回当前触控动作的索引

     2、如何区别动作类型?

              在一般的单点触控事件当中,我们只需要使用getAction()得到动作类型,再用ACTION_UP、ACTION_DOWN区分就可以达到目的。但是在多点触控的时候,则需要我

             们使用getActionMasked()获得动作信息,然后再区分动作是属于那一类。

             动作类型:

             ACTION_DOWN  :   第一个手指按下

             ACTION_UP    : 最后一个手指离开

             ACTION_POINTER_DOWN :非第一个手指按下

             ACTION_POINTER_UP : 非最后一个手指离开

             ACTION_POINTER_1_DOWN : 这是之前SDK版本所使用的,表示第一个手指按下,它的数值跟ACTION_DOWN是相等的

            ACTION_POINTER_2_DOWN:第二根手指按下

            ACTION_POINTER_3_DOWN:第三根手指按下

            ACTION_POINTER_x_DOWN:第x根手指离开

           原理:

             取mAction(触控信息)低8位,屏蔽高8位;

             即: actionType = (ACTION_MASK&mAction);

             例如:mAction= 0x0105H  (表示索引为1动作为:ACTION_DOWN,第一个手指按下)

             则:actionType= (0x00ff&0x0105)  = 5 = ACTION_DOWN;

    3、如何知道是哪个手指离开?

          如果在单点触控的情况下,监听离开直接使用ACTION_UP即可。但如果在多点触控的情况下,就需要我们定位是哪一个手指离开。这个使用就需要使用到getActionIndex()来获取触控动作的索引。从而得知是哪一个点离开了或者哪一个点按下了。

          其实getActionIndex()的实现原理很简单:

           取mAction(触控动作)高8位信息,然后再右移8位得到索引。

          即: Index = (ACTION_POINTER_INDEX_MASK&mACTION)>> ACTION_POINTER_MASK;

           例如:mAction = 0x0105H  (表示索引为1动作为:ACTION_DOWN,第一个手指按下)

           则:index= (0xff00&0x0105) >> 0x00ff = 1;

    三、为什么要使用掩码和位操作?

       很多人,我一开始也疑惑,为什么不从一开始就使用两个整型来存储动作和索引信息呢。这样不是更容易让人理解吗?不过看了API文档的解释之后,才明白这是为了节省内存。因为动作就那么几个,位置信息在高八位以上,还有24位的信息用来存储索引信息(2的24次方个点,绝对够用!)。因此只需要一个32位的整型就可以存储这两个信息。而且计算机内部也只是识别 01序列的,我们搞IT的免不了会接触到一些汇编,汇编语言里面的知识在这里就派上用场了,比如:移位、按位逻辑运算等知识。而且熟悉了位存储之后,对于Android的其他类别属性的理解也会更加有帮助。

    以上都是转载的别人的博客,下面是我自己写tank大战时候,自己控制tank移动和射击的触控事件:(注意里面的一些注释:多点触控 event.getAction()& MotionEvent.ACTION_MASK  和  当2个手指同时按着的时候 event.getActionIndex()时候总是0,因此得遍历所有点来处理移动射击事件

    int directionDownIndex = -1;
        int boomDownIndex = -1;
        @Override
        public boolean onTouchEvent(MotionEvent event) {
    
            switch (event.getAction()& MotionEvent.ACTION_MASK)
            {
                case MotionEvent.ACTION_DOWN://第一个点按下时 将设计
                    int x = (int)event.getX();
                    int y = (int)event.getY();
                    System.out.println("第一个点" + event.getActionIndex());
                  if(pointDown(boomCenter , x, y , r2))//判断点击的地点是否在按钮处, 并记录下按下点的索引
                  {
                      boomDownIndex =0;
                  }
                  else if(pointDown(directionBtCenter, x ,y , r))
                  {
                      directionDownIndex = 0;
                  }
    
                    break;
                case MotionEvent.ACTION_POINTER_DOWN://新的点被按下时,并记录下按下点的索引
                    int index = event.getActionIndex();
                    int x1 = (int) event.getX(index);
                    int y1 = (int) event.getY(index);
                    System.out.println("第2个点" + event.getActionIndex());
                    if (pointDown(boomCenter, x1, y1, r2)&&boomDownIndex == -1)
                    {
                        boomDownIndex = index;
                    }
                    else if (pointDown(directionBtCenter, x1, y1, r)&&directionDownIndex == -1)
                    {
                        directionDownIndex = index;
                    }
                    break;
                case MotionEvent.ACTION_MOVE: // 这里发现当2个手指同时按着的时候 event.getActionIndex()时候总是0,因此得遍历所有点来处理移动射击事件
                    int pointNumber = event.getPointerCount();
                    for(int i = 0 ; i < pointNumber ; i++) {
    
                        int x2 = (int) event.getX(i);
                        int y2 = (int) event.getY(i);
    
                        if( i== boomDownIndex)
                        {
                            myTank.myShot();
                           // myTank.balls.size();
                        }
                        else if(i == directionDownIndex)
                        {
                            setDirectionCenterBtCenter(directionBtCenter,x2 , y2 , r , r3);
                            changeDirection(x2, y2);
                            myTank.move(screenWidth , screenHeight);
                        }
                    }
                    break;
                case MotionEvent.ACTION_POINTER_UP://将2个按钮的索引值归为初始值
                    if(event.getActionIndex() == directionDownIndex)
                        directionDownIndex = -1;
                    else if(boomDownIndex == event.getActionIndex())
                          boomDownIndex = -1;
                    break;
                case MotionEvent.ACTION_UP:
                    directionDownIndex = -1;
                    boomDownIndex = -1;
                    break;
    
            }
            return true;// super.onTouchEvent(event);//
        }
  • 相关阅读:
    C语言:线程同步之信号量(sem_init,sem_post,sem_wait)
    SVN使用 -work
    atomic c++ y原子变量 替换锁代码
    原子变量
    perf
    内存泄露检测工具对比
    valgrind ----直接使用参数
    堆内存分析---特别棒
    调不尽的内存泄漏,用不完的 Valgrind(转)
    静态库动态库制作方法
  • 原文地址:https://www.cnblogs.com/bokeofzp/p/6699474.html
Copyright © 2020-2023  润新知