View的Touch事件分发流程

来源:互联网 发布:power shell shell编程 编辑:程序博客网 时间:2024/04/28 07:29

概述

View的Touch事件分发大致分为两个过程:

  1. 从上向下的分发过程,调用的是dispatchTouchEvent()。
  2. 从下向上的处理过程,调用的是onTouchEvent()。

相关概念

Touch事件分发涉及到几个相关概念

事件链

这里涉及到事件链的概念,事件链是指从MotionEvent.ACTION_DOWN开始,到MotionEvent.ACTION_UP之间的一系列Touch事件,ACTION_DOWNACTION_UP之间可能没有其他事件,也可能包含ACTION_MOVEACTION_CANCELACTION_POINTER_DOWNACTION_POINTER_UP等。

事件消费

如果一个View对某个Touch事件感兴趣,并且它的onTouchEvent()返回了true,则称为该View消费了此次Touch事件。并且,一次Touch事件只会被一个View消费。事件消费与ACTION_DOWN联系紧密,在一个事件链中,只有消费了ACTION_DOWN事件的View才会有机会在onTouchEvent()中响应后续的事件。


详细流程

主要关心三个函数:

/* 从最顶层的ViewGroup开始调用,发起Touch事件的分发过程,返回true表示该ViewGroup处理了此次事件 */boolean dispatchTouchEvent(MotionEvent ev);/* 判断是否拦截此次Touch,返回true表示拦截,即不再将此次事件像子View传递 */boolean onInterceptTouchEvent(MotionEvent ev);/* 对Touch事件的处理业务,返回true表示消费此次事件 */boolean onTouchEvent(MotionEvent ev);

处理流程:

  1. 所有事件链都是从ACTION_DOWN开始的,ViewGroup收到ACTION_DOWN后,会触发dispatchTouchEvent()发起分发过程。这会调用onInterceptTouchEvent(),如果后者返回值为false,即不拦截,则接下来依次调用子ViewdispatchTouchEvent()方法;如果返回值为true,则跳过遍历子View的步骤。
  2. 如果没有被拦截,dispatch会一直进行到最下面一层的View,然后沿着刚刚dispatch的顺序,反向依次调用各个ViewonTouchEvent();如果中途被拦截,即某个ViewdispatchTouchEvent()返回了false,则从拦截的View开始,沿着dispatch的顺序,反向依次调用各个ViewonTouchEvent()
  3. 依次调用onTouchEvent()的过程中, 如果某个ViewonTouchEvent()返回true,即该View对此次Touch事件感兴趣,则该View会被记录到此次事件链的mFirstTouch中,并且结束此次Touch事件的处理,不再继续调用父ViewonTouchEvent()。如果所有View的onTouchEvent()都返回了false,则结束事件处理时mFirstTouchnull
  4. 前面3步讲的都是ACTION_DOWN,下面开始处理事件链的后续Touch事件。当后续事件到来时(可能是除了ACTION_DOWN以外的任何事件),依然触发dispatchTouchEvent(),但处理逻辑不同,ViewGroup会判断mFirstTouchTarget是否为null,也就是判断以自己为根的View树中是否有人消费了之前的ACTION_DOWN,如果有人消费,则依次向下dispatch,直到找到消费了ACTION_DOWN事件的View,调用它的onTouchEvent()处理。如果没人消费,直接返回,结束此次分发。

参考文献

http://wugengxin.cn/download/pdf/android/PRE_andevcon_mastering-the-android-touch-system.pdf

0 0
原创粉丝点击