谈谈我所理解的事件分发机制

        事件分发机制基本上遵从Activity->ViewGroup->View的顺序进行事件分发,通过调用onTouchEvent()方法进行事件处理。事件分发机制中关键的三个方法就是dispatchTouchEvent()、onTouchEvent()和onInterceptTouchEvent()。其中dispatchTouchEvent()方法是负责事件分发的,onTouchEvent()是进行事件处理的,onInterceptTouchEvent()是负责事件拦截的。事实上,Android的事件分发机制也就是指Activity的事件分发机制、ViewGroup的事件分发机制和View的事件分发机制。

     

Activity的事件分发机制:

        当DOWN事件产生后,即点击事件产生后,事件首先会传给当前的Activity,这时会调用Activity的dispatchTouchEvent()方法。当DOWN事件产生时,会调用onUserInteraction()这个方法,这个方法的主要作用是实现屏保功能,并且当Activity在栈顶时,触屏、点击HOME、BACK键都会触发此方法。然后在Activity的dispatchTouchEvent()方法中有一个getWindow().superDispatchTouchEvent(ev)的判断条件,如果该条件成立,也就是说返回true,则该事件就停止传递了。也就意味着结束了本次的事件分发。否则的话便返回onTouchEvent(ev),此时事件就会继续向下分发。而这个判断条件实际上是调用了DecorView的superDispatchTrackBallEvent()方法。而DecorView是继承自FrameLayout的,FrameLayout是ViewGroup的子类,所以事实上是直接调用了ViewGroup的dispatchTouchEvent()方法。

ViewGroup的事件分发机制:

        ViewGroup的dispatchTouchEvent()方法中,定义了一个Boolean类型的变量intercept,表示是否要拦截事件。其中通过onInterceptTouchEvent(ev)方法对intercept进行赋值,大多数情况下返回的是false,但我们可以通过重写onInterceptTouchEvent(ev)来改变它的返回值,在ViewGroup的dispatchTouchEvent()方法内部做了一个for循环,通过倒序遍历ViewGroup下面的子View,然后一个一个判断点击的位置是否是该子View的布局区域。

View的是事件分发机制:

        View的dispatchTouchEvent()方法中,满足这三个条件时,才会返回true。其中第一个条件mOnTouchListener不为空,调用setOnTouchListener,第二个条件是判断当前点击的控件是否为enable,第三个条件是调用setOnTouchListener()时覆盖onTouch()方法的返回值。在View的onTouchEvent()中,只要View的CLICKABLE和LONG_CLICKABLE有一个为true,onTouchEvent()就会返回true进行事件的消耗。在UP事件发生时会调用perforclick()方法。


下面是按照自己的理解进行绘制的一个有关事件分发机制的一个图。



总结:

1、关于Android事件分发机制,相关方法的方法有三个:onTouchEvent(),dispatchTouchEvent()和onInterceptTouchEvent(),而相关的类有Activity,View,ViewGroup。时间的分发顺序是按照dispatchTouchEvent--->onInterceptTouchEvent ---> onTouchEvent的顺序执行的。

 2、事件的传递从Activity的dispatchTouchEvent()方法开始的。

 3、onTouch()方法优先级高于onTouchEvent(ev)方法。onTouch()执行总优先于onClick()。

4、Android事件分发机制中,主要有两个过程,一个是向下分发的过程,该过程主要调用dispatchTouchEvent(),还有一个是向上返回的过程,主要依靠onTouchEvent()方法。

5、Android事件是从父view向子view分发的,如果事件被拦截,则事件不会继续向下分发,而是在当前所在层被消耗/处理。此时向下分发过程会提前结束,没有被消耗的事件,从父view向子view逐级分发,最后又回到Activity,被Activity中的onTouchEvent()消耗/处理。此时向上返回的过程也就提前结束了。

        


你可能感兴趣的:(android)