MotionEvent基本概念

26 篇文章 1 订阅

MotionEvent是事件传递中的一个重要概念——事件类型。

事件类型就是指MotionEvent对象所代表的动作。比如说,当你的一个手指在屏幕上滑动一下时,系统会产生一系列的触摸事件对象,他们所代表的动作有所不同。有的事件代表你手指按下这个动作,有的事件代表你手指在屏幕上滑动,还有的事件代表你手指离开屏幕。这些事件的事件类型就分别为ACTION_DOWN,ACTION_MOVE,和ACTION_UP。上述这个动作所产生的一系列事件,被称为一个事件流,它包括一个ACTION_DOWN事件,很多个ACTION_MOVE事件,和一个ACTION_UP事件。

        除了这三个类型外,还有很多不同的事件类型,比如ACTION_CANCEL。它代表当前的手势被取消。要理解这个类型,就必须要了解ViewGroup分发事件的机制。一般来说,如果一个子视图接收了父视图分发给它的ACTION_DOWN事件,那么与ACTION_DOWN事件相关的事件流就都要分发给这个子视图,但是如果父视图希望拦截其中的一些事件,不再继续转发事件给这个子视图的话,那么就需要给子视图一个ACTION_CANCEL事件。


        为了可以表示多个触摸点的动作,MotionEvent中引入了Pointer的概念,一个pointer就代表一个触摸点,每个pointer都有自己的事件类型,也有自己的横轴坐标值。一个MotionEvent对象中可能会存储多个pointer的相关信息,每个pointer都会有一个自己的id和index。pointer的id在整个事件流中是不会发生变化的,但是index会发生变化。


 MotionEvent类中的很多方法都是可以传入一个int值作为参数的,其实传入的就是pointer的index值。比如getX(pointerIndex)和getY(pointerIndex),此时,它们返回的就是index所代表的触摸点相关事件坐标值。


 由于pointer的index值在不同的MotionEvent对象中会发生变化,但是id值却不会变化。所以,当我们要记录一个触摸点的事件流时,就只需要保存其id,然后使用findPointerIndex(int)来获得其index值,然后再获得其他信息。

        第一个接触屏幕的手指触发ACTION_DOWN事件,如果屏幕上存在手指,新加入的手指就会触发ACTION_POINTER_UP事件,不会触发ACTION_DOWN事件;最后一个离开屏幕的手指触发ACTION_UP事件,如果屏幕上存在手指,离开的手指就会触发ACTION_POINTER_UP事件,不会触发ACTION_UP事件;每个手指移动都会触发ACTION_MOVE事件。为了分清到底是哪个手指在移动,就用到的actionId,pointerIndex和pointerId了。

        PointerCount: 当前屏幕上手指的数量
        ActionIndex: 使用MotionEventCompat.getActionIndex(event)来获取,手指下标
        PointerIndex: 屏幕上手指的索引,触碰屏幕的手指的信息(位置,压力,大小等)都会以数组的形式缓存到MotionEvent中,PointerIndex就是这些数组的索引。手指信息大多是通过pointerIndex来查获取的

        PointerId: 屏幕上手指的唯一标志,每次手指触发DOWN事件时就会被分配一个id,在该手指触发UP/CANCEL事件之前保持不变。id分配规律:每次分配的id值为0到pointerCount - 1里的一个未被分配的最小值。比如当前屏幕上有三根手指A, B, C,可知pointerCount为3,手指A的pointerId为0,B的pointerId为1,C的pointerId为2。此时又有新手指D加入,pointerCount就变成里4,为手指D分配pointerId时就从[0, 1, 2, 3]中查找,其中3没有被分配,所以手指D都pointerId为3。将手指AB离开屏幕,然后添加手指E,此时pointerCount为3,为手指E分配id时从[0, 1, 2]中查找,其中0,1都可以使用,选较小的0作为手指E的pointerId。此时屏幕上有3个手指,pointerCount为3,pointerId为[0, 2, 3]。其实知道这些值没啥用:),pointerId最主要的功能就是找到pointerIndex,然后再根据pointerIndex获取手指的其他信息。


        Android用一个32位的整型值表示一次TouchEvent事件,低8位表示touch事件的具体动作,比如按下,抬起,滑动,还有多点触控时的按下,抬起,这个和单点是区分开的,下面看具体的方法:
        1 getAction:触摸动作的原始32位信息,包括事件的动作,触控点信息
        2 getActionMask:触摸的动作,按下,抬起,滑动,多点按下,多点抬起
        3 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;

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

 public final int getAction() {
        return nativeGetAction(mNativePtr);
    }

    public final int getActionMasked() {
        //取低8位
        return nativeGetAction(mNativePtr) & ACTION_MASK;
    }

    public final int getActionIndex() {
        //取高8位,右移8位
        return (nativeGetAction(mNativePtr) & ACTION_POINTER_INDEX_MASK)
                >> ACTION_POINTER_INDEX_SHIFT;
    }

       getAction 和 getActionMasked

        一个MotionEvent对象中可以包含多个触摸点的事件。当MotionEvent对象只包含一个触摸点的事件时,上边两个函数的结果是相同的,但是当包含多个触摸点时,二者的结果就不同啦。
 getAction获得的int值是由pointer的index值和事件类型值组合而成的,而getActionWithMasked则只返回事件的类型值


        一般来说,getAction() & ACTION_POINTER_INDEX_MASK就获得了pointer的id,等同于getActionIndex函数;getAction()& ACTION_MASK就获得了pointer的事件类型,等同于getActionMasked函数。


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值