Android View事件分发与传递

    在Android中,人们主要经过手指与系统交互。Android把全部的touch事件都被封装成MotionEvent来进行处理,其中包括了手指点击的位置,时间等信息。其事件类型主要包括:ACTION_DOWN,ACTION_UP,ACTION_MOVE, ACTION_POINTER_DOWN, ACTION_POINTER_UP,ACTION_CANCEL。函数

    这些事件是有触发顺序的,下面举两个栗子:spa

  • 只有一个手指点击在view范围内,依次触发的事件:手指按下ACTION_DOWN→手指移动ACTION_MOVE→手指抬起ACTION_UP
  • 多个手指点击在view范围内,依次触发的事件:第一根手指按下ACTION_DOWN→随后的手指按下ACTION_POINTER_DOWN→有手指抬起ACTION_POINTER_UP→最后一根手指抬起ACTION_UP。

为了处理这些事件,Android定义了三种方法:blog

  1. dispatchTouchEvent()函数:负责分发传递事件,一般不把逻辑处理放在该方法中,因此通常都return super.dispatchTouchEvent().
  2. onInterceptTouchEvent()函数:负责拦截事件
  3. onTouchEvent()函数和 OnTouchListener监听:负责消费和处理事件

 

事件传递流程

        当一个事件被触发,事件的传递从Activity.dispatchTouchEvent()开始,一直从最外层的父view开始向里面的子view传递,直到被拦截。在传递过程当中,view能够经过onInterceptTouchEvent()函数进行拦截,一旦父view拦截了该事件,则再也不向下传递事件

        若是被触发的事件被传递至最内层的view,一直未被拦截消费,则会反向向外传递,这时候父view能够经过onTouchEvent函数对事件进行消费,直到activity。另外,若是被触发的ACTION_DOWN事件在某一层未被消费,那么接下来的事件是没法被传递进来的。开发

view-ignore-touch-event-example

view-process-touch-event-example

    下面咱们来看几个例子:it

Case 1  手指点击在view上,父View(ViewGroup)和View都不消费事件,最终返回给activity消费。io

view1

        以ACTION_DOWN事件为例,ACTION_DOWN事件沿着图中黑色箭头逐层传递。在开发过程当中,咱们一般会为view或者viewGroup设置监听器来捕获view事件,listener的onTouch方法会在onTouchEvent以前执行。在分发传递过程当中,不管哪一个方法返回true,都表示传递中止;若是返回false,则表示继续传递下去。event

        从图上能够看出,ACTION_DOWN事件通过activity—>ViewGroup—>View—>ViewGroup—>activity一直未被ViewGroup和View消费处理,又回到了activity中。那么随后的ACTION_MOVE和ACTION_UP事件只会沿着绿色箭头传递,再也不沿着ACTION_DOWN事件的路线传递了。List

Case 2  手指点击在父View和子View之间的空隙中,并未点击在子View上。同上一个例子同样,ViewGroup中并未消费该事件,返回给了activity。方法

view2

 

        这里用户并未点击到ViewGroup中的view,而是点击在了ViewGroup和View之间的空隙处。同上一个例子相同,ViewGroup并未处理ACTION_DOWN事件,而是返回给了activity处理。

Case 3  单击view后,在view中处理消费了ACTION_DOWN事件。

view3

        从图上能够看到,ACTION_DOWN事件沿着黑色箭头方向逐层向内部传递,直到在view的onTouchEvent中消费了该事件,并返回true表示再也不向下传递。随后的事件ACTION_MOVE和ACTION_UP将会沿着绿色箭头传递,直到到达view的onTouchEvent方法。

Case 4  单击view,可是并不在view中处理ACTION_DOWN事件,而是让它传递到ViewGroup中处理。

view4

        ACTION_DOWN事件通过ViewGroup,ViewGroup并未拦截而是传递给View。View并未消费该事件而是回传给了ViewGroup,在ViewGroup中消费该事件。

Case 5  单击view,在ViewGroup中拦截ACTION_DOWN事件并消费

view5

        ACTION_DOWN事件沿着黑色箭头分发传递,在ViewGroup中对它进行拦截(返回true),因此就再也不继续向view传递ACTION_DOWN事件了。而后在ViewGroup的onTouchEvent方法中消费了该事件,并返回true表示事件已消费。随后的ACTION_MOVE和ACTION_UP事件将沿着绿色箭头传递,直抵最后的消费方法onTouchEvent,而并不通过拦截事件。

相关文章
相关标签/搜索