美文网首页
Android识别多点触控

Android识别多点触控

作者: 一个不安分的Android开发 | 来源:发表于2019-11-27 09:28 被阅读0次

    正常开发中,单点触控场景遇到的比较多,比如识别 ACTION_DOWNACTION_UPACTION_MOVE 事件等。接下来我要介绍的是如何识别多点触控,即多个手指触摸屏幕。

    一、MotionEvent事件的分类

    官方文档:https://developer.android.com/training/gestures/multi?hl=zh_cn

    属性说明:

    • ACTION_DOWN:轻触屏幕的第一个手指,也是最先触发的事件。
    • ACTION_POINTER_DOWN:除了第一个手指之外,其他手指点击屏幕将触发该事件。
    • ACTION_POINTER_UP:除了最后一个手指,其他手指离开屏幕时会调用该事件。
    • ACTION_UP:最后一个手指离开屏幕时调用该事件。
    • ACTION_MOVE:手指移动时触发该事件。

    获取具体手指id:

    如果有两根手指在屏幕上,一根手指移动,另外一根手指保持禁止,ACTION_MOVE 中如何才能识别具体是哪根手指进行了移动?
    虽然Android没有直接提供api进行调用,但是可以使用其他方法进行获取。

    // 获取当前事件的手指id
    motionEvent.getPointerId(motionEvent.getActionIndex()));
    
    // 可以监控到多指事件但是回调的id不是ACTION_POINTER_DOWN和ACTION_POINTER_UP,下面会具体说明
    event.getAction();
    // 必须使用这个方法获取ACTION_POINTER_DOWN和ACTION_POINTER_UP的id
    event.getActionMasked();
    

    二、代码示例

    主要代码如下:

      @Override
      public boolean onTouchEvent(MotionEvent event) {
        // 获取当前手指的id 
        int pointerId = event.getPointerId(event.getActionIndex());
    
        // 识别多指必须使用getActionMasked()方法
        switch (event.getActionMasked()) {
          case MotionEvent.ACTION_DOWN:
            // 第一根手指点击屏幕
            Log.d(TAG, "ACTION_DOWN pointerId: " + pointerId);
            break;
          case MotionEvent.ACTION_POINTER_DOWN:
            // 屏幕上已存在手指,再点击会触发这个回调
            Log.d(TAG, "ACTION_POINTER_DOWN pointerId: " + pointerId);
            break;
          case MotionEvent.ACTION_POINTER_UP:
            //当屏幕上一根手指被抬起,此时屏幕上仍有别的手指
            Log.d(TAG, "ACTION_POINTER_UP pointerId: " + pointerId);
            break;
          case MotionEvent.ACTION_UP:
            //最后一根手指离开屏幕
            Log.d(TAG, "ACTION_UP pointerId: " + pointerId);
            break;
          default:
            break;
        }
        return super.onTouchEvent(event);
      }
    

    将食指、中指触摸屏幕,然后再放开中指和食指,运行结果如下:

    D/MainActivity: ACTION_DOWN pointerId: 0
    D/MainActivity: ACTION_POINTER_DOWN pointerId: 1
    D/MainActivity: ACTION_POINTER_UP pointerId: 1
    D/MainActivity: ACTION_UP pointerId: 0
    

    三、getAction、getActionMask、getActionIndex区别

    可以先看下三个方法的源码:

    public static final int ACTION_MASK = 0xff;
    public static final int ACTION_POINTER_INDEX_MASK = 0xff00;
    public static final int ACTION_POINTER_INDEX_SHIFT = 8;
    // 返回触控的所有信息
    public final int getAction() {
      return nativeGetAction(mNativePtr);
    }
    // 返回当前触控的动作信息,即低8位的信息
    public final int getActionMasked() {
      return nativeGetAction(mNativePtr) & ACTION_MASK;
    }
    // 获取当前触控的索引(比如:当你要监听是哪一个手指在屏幕上移动)
    public final int getActionIndex() {
      return (nativeGetAction(mNativePtr) & ACTION_POINTER_INDEX_MASK)
                  >> ACTION_POINTER_INDEX_SHIFT;
    }
    

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

    • ACTION_MASK:动作信息掩码,用于截取目标动作信息;
    • ACTION_POINTER_INDEX_MASK:高8位的位置信息掩码,用于截取索引信息;
    • ACTION_POINTER_INDEX_SHIFT:截取触控索引时所需的移位个数;
    • getAction():返回触控的所有信息
    • getActionMasked():返回当前触控的动作信息,即低8位的信息
    • getActionIndex():获取当前触控的索引(比如:当你要监听是哪一个手指在屏幕上移动)

    单词mask的意思是掩藏掩饰,在这里所表达的含义就是要把一部分信息掩饰掉,只保留要想的信息,无论是使用getAction还是getActionMasked,触屏事件都会回调到onTouchEvent,在多点操控时,以双指按下屏幕为例,系统会多回调一个值表示双指按下,如果使用getAction的话,这个值是261,如果使用getActionMasked这个值是5,所以对于多点操控,android只是多回调了一次,由于android使用低8位表示touch的具体动作,所以如果想在多点触控时做一些事情就需要使用getActionMasked,当然如果你不嫌麻烦,你可以可以使用硬编码的方式使用261(这个值目前已经不推荐使用了)。

    多点触控.png

    参考:
    https://blog.csdn.net/victory08/article/details/49101367
    https://blog.csdn.net/woshimalingyi/article/details/50383578

    相关文章

      网友评论

          本文标题:Android识别多点触控

          本文链接:https://www.haomeiwen.com/subject/zqmywctx.html