前言

  所谓的点击事件的事件分发,其实就是对MotionEvent事件的分发过程,即当一个MotionEvent产生了以后,系统需要把这个事件传递给一个具体的view,而这个过程就是分发过程。点击事件的分发过程由三个很重要的方法来完成 dispatchTouchEvent 、onInterceptTouch和onTouchEvent共同来完成。

1.public boolean dispatchTouchEvent(MotionEvent  en)

   用来进行事件的分发,如果事件能传递给当前的View,那么这个方法一定会被调用。返回结果受当前的View的onTouchEvent和下级View的dispatchTouchEvent方法的影响,表示是否消耗当前事件。

2.public boolean onInterceptTouchEvent(MontionEvent event)

主要用来判断是否拦截某个事件。如果当前View拦截了某个事件,那么在同一事件序列中,此方法不会在被调用,返回结果表示是否拦截了当前事件。

3.public boolean onTouchEvent(MontionEvent  en)

在dispatchTouchEvent方法中调用,用来处理点击事件,返回结果表示是否消耗当前事件。

上述三个方法的异同可以用一下伪代码来说明

public boolean dispatchTouchEvent(MotionEvent motionEvent) {
        boolean sume = false;
        if (onInterceptTouchEvent(motionEvent)){
            sume=onTouchEvent(motionEvent);
        }else {
            sume=child.dispatchTouchEvent(motionEvent);
        }
        return sume;
    }

   当一个view需要处理事件时,如果它设置了OnTouchL ster,那么OnTouchLisce中的onTouch方法会被回调。这时事件如何处现还要看onTouch的返回值,如果返回ale则当前View的onTouchEvent方法会被调用:如果返回tnue,那么onTouchEvent方法将不会被调用。由此可见,给View设置的OnTouchL sener其优先级比onTouchEvent要高,在onTouchEvent方法中,如果当前设置的有OnClickListener,那么它的onClick方法会核调用。可以看出,  平时我们常用的OnClickListener, 其优先级最低,即处于事件传递的尾端。
  当一个点击事件产生后,它的传递过程遵循如下顺序: Activity > Window-> View,即事件总是先传递给Activity, Activity 再传递给Window,最后Window再传递给顶级View.顶级View 接收到事件后,就会按照事件分发机制去分发事件。考虑一种情况, 如果一个View的onTouchEvent返回false,那么它的父容器的onTouchEvent 将会被调用,依此类推。如果所有的元素都不处理这个事件,那么这个事件将会最终传递给Activity处理,即Activity的onTouchEvent方法会被调用。这个过程其实也很好理解,我们可以换一种思路,假如点击事件是一个难题,这个难题最终被上级领导分给了一个程序员去处理(这是事件分发过程),结果这个程序员搞不定(onTouchEvent返回了false), 现在该怎么办呢?难题必须要解决,那只能交给水平更高的上级解决(上级的onTouchEvent被调用),如果上级再搞不定,那只能交给上级的上级去解决,就这样将难题一层层地向上抛, 这是公司内部一种很常见的处理问题的过程。从这个角度来看,View的事件传递过程还是很贴近现实的,毕竟程序员也生活在现实中。

关于事件传递机制,这里有一些结论,可以更好的去理解整个传递机制

(1).同一事件序列是以down事件开始,中间含有数量不定的move事件,最终以up事件结束

(2).正常情况下,一个事件序列只能被一个view拦截且消耗

(3).某个View一旦决定拦截,那么这一个事件序列都只能由它来处理,并且它的onInterceptTouchEvent不会再被调用。

(4).某个View一旦开始处理事件,如果它不消耗ACTION_DOWN事件(onTouchEvent返回false)那么同一事件序列中的其他事件都不会再交给它来处理,并且事件将重新交给它的父元素去处理。