Android事件分发学习

jkouu 78 0

什么是事件?

事件指的是点击事件,也即用户从触摸屏幕到离开屏幕的过程。Android将事件分为了下面四种事件:

1.DOWN事件:指用户按下View的事件,是一切事件的开始。

2.MOVE事件:用户滑动View的事件

3.UP事件:用户离开View的事件

4.CANCEL事件:非人为原因致使事件结束

一个完整的事件应该包括一个DOWN事件,一个UP事件以及若干个二者之间的MOVE事件。具体见下图:

事件的分发对象

我们知道,Android的UI由Activity、ViewGroup(及其派生类)、View(及其派生类)组成。事件也正是向这三类组件进行分发。分发的顺序就是三者的包含顺序:Activity、ViewGroup、View。

事件的分发流程

首先我们先放一张图:

Android事件分发学习

这张图是我对事件分发机制的一个高度总结,什么都不标的箭头表示方法的调用,标着true或者false的箭头表示根据什么都不标的箭头表示的方法的结果来调用的方法。可以看到,事件分发涉及的主要方法就三个,下面我们以此来简单地讲解这三个方法。

dispatchTouchEvent

首先说一下返回值。对于Activity来说,方法的返回值就是下一级的dispatchTouchEvent的返回值;对于ViewGroup来说,方法的返回值取决于ViewGroup是否允许拦截事件,是的话返回值就是ViewGrou'p的onTouchEvent方法的返回值,否则就是下一级控件的dispatchTouchEvent的返回值(当然,这里的下一级控件既可以是View,也可以是ViewGroup,套娃嘛);对于View来说,方法的返回值是这个View的onTouchEvent返回值。

然后我们说一下作用对象。对于Activity来说,它只能直接接触最外层的ViewGroup,所以就无脑问这个ViewGroup就行了;对于ViewGroup来说,它可能有无数个View或者ViewGroup作为子控件,那么它就得遍历所有子控件来找到应该将事件分发给哪个控件(判断方法很简单,看事件的位置在哪个控件的矩形区域内);对于View来说,它不能再向下分发了,因此作用对象就是自己。

onInterceptTouchEvent

这个方法是专门属于ViewGroup的。如果ViewGroup允许拦截事件,那么它就不向子控件下发事件,而是直接执行自己的onTouchEvent。

onTouchEvent

先说返回值。这个方法的返回值就是控件有没有处理这个事件,处理了就是true,否则就是false。

再说工作流程。onTouchEvent其实也是一系列流程。源码的逻辑很好懂,大意就是根据事件的状态进行一个判断。比如上一个事件的DOWN事件,这次的事件是一个UP事件,那就根据两次事件的时间差决定是调用onClick还是onLongClick。

那么问题来了,如果没有收到DOWN事件呢?

首先,这种情况是存在的。我们可以重写dispatchTouchEvent,让某一个ViewGroup只下发MOVE事件和UP事件。这样就会出现问题:对于ViewGroup来说,它只能收到DOWN事件;对于它的子控件来说,子控件只能收到MOVE和UP事件。显然,这两种情况都不能构成一个完整的事件列。

为了解决这个问题,onTouchEvent又加了一条约束:除非该控件上一个处理的事件是DOWN事件,否则不处理MOVE事件和UP事件。这样一来,即使例子中的ViewGroup把事件分发了下去,子控件也不会处理这些事件。最终,这些事件还是会被ViewGroup来处理。

 

 

发表评论 取消回复
您必须 [登录] 才能发表评论!
分享