android高级Android高阶探索Android开发经验谈

也谈Android事件分发

2016-05-28  本文已影响340人  东风四幺

说到Android事件分发,想必大家都做了不少研究,读了不少博客文章。 今天抛出一块砖,也来谈谈自己对Android事件分发的理解。

其实也谈不上多么理解,在总结前人的一些博客的基础上,自己做了验证,用自己的话来描述出来,争取用最简单的话语把事件分发的逻辑表达清楚,正确。


回到正题。

事件怎么来?怎么去?

我们知道Android上的事件都是发生在View或者ViewGroup(继承于View)上并在上面进行传递的。

有几个关键的函数大家应该都知道了。

对View来说,那就是:

负责事件分发的:

public boolean dispatchTouchEvent(MotionEvent event)

负责事件处理的:

public boolean onTouchEvent(MotionEvent event)

对ViewGroup来说,那就是:

负责事件分发的:

public boolean dispatchTouchEvent(MotionEvent event)

负责事件拦截的:

public boolean onInterceptTouchEvent(MotionEvent ev)

负责事件处理的:

public boolean onTouchEvent(MotionEvent event)

还有重要的一点, 事件的根儿呢? 用户点击屏幕的各种事件(ACTION_DOWN,ACTION_MOVE,ACTION_UP等),一开始其实是由Activity来负责往下分发的, 所以Activity也有两个重要的函数,他们是:

负责事件分发的:

public boolean dispatchTouchEvent(MotionEvent event)

负责事件处理的:

public boolean onTouchEvent(MotionEvent event)

通过阅读Activity的dispatchTouchEvent方法代码,通过分析线程调用堆栈发现,最终会调用到decorView的dispatchTouchEvent方法,我们知道decorView继承自FrameLayout,也就是会调用到ViewGroup的dispatchTouchEvent方法。

即:事件从

Activity的dispatchTouchEvent  ---->  ViewGroup的dispatchTouchEvent

我们知道,所有的屏幕操作事件都是以按下(ACTION_DOWN)为前提的,接下来才会有ACTION_MOVE和ACTION_UP。

我们先来看ACTION_DOWN事件的传递:

从上面可以得知,事件传递到ViewGroup的dispatchTouchEvent之后,如何处理呢? 会调用到ViewGroup的onInterceptTouchEvent判断ViewGroup是否对事件进行拦截,如果返回true,就是要拦截,自己去处理;如果返回false(默认返回false), 就是不进行拦截,继续往下分发。

但是,每个事件传递都会调用ViewGroup的onInterceptTouchEvent吗? 不一定!!!

这就好像复杂了点, 其实说来也简单:只有当前事件是ACTION_DOWN或者上一次事件被ViewGroup底下的某个子View消费了的时候,才会调用ViewGroup的onInterceptTouchEvent.

接着刚才继续说,如果ViewGroup拦截了事件,就会调用ViewGroup的onTouchEvent方法去处理了,结果怎么样呢? 如果返回true,代表ViewGroup自己把事件给消费了,ACTION_DOWN事件就结束了。后面的事件怎么传递呢?不说了,看最后的流程图吧。 如果返回false, 代表ViewGroup自己没有把事件消费,(这就有点耍流氓了,把事件拦截了又不消费,你想干嘛? )主子Activity看不顺眼了,于是事件又回到了Activity, 让Activity的onTouchEvent去处理了。还有更严重的呢!好你个ViewGroup,ACTION_DOWN事件你不想处理,那其他事件也用不着你管了!(一边凉快去吧~),所以,后面的事件都是Activity分发给自己的onTouchEvent去处理了。

那如果ViewGroup没有拦截ACTION_DOWN呢?ViewGroup说,孩子们,这个活儿你们看着办吧!于是事件就分发给了子View, 子view调用dispatchTouchEvent方法,子View如果按照祖宗的规矩处理的话,就会调用onTouchEvent方法去处理,处理结果呢? 如果直接返回true,  就代表子View把事件消费了,ACTION_DOWN到此结束。下一步的事件还是会传递进来。 如果直接返回false, 就代表子View没消费事件,怎么办? 回传给ViewGroup的onTouchEvent去处理,如果ViewGroup的onTouchEvent消费了ACTION_DOWN事件(即返回true),那后面的事件(ACTION_MOVE,ACTION_UP)就简单了,会直接派发给ViewGroup去处理,没孩子的事儿了! 那如果ViewGroup也没有消费ACTION_DOWN事件(即onTouchEvent返回false), 那只能主人Activity自己去处理了,回传给Activity的onTouchEvent处理,并且后面的事件也是Activity自己去处理了,奴才们都一边玩蛋去吧!

ACTION_MOVE,ACTION_UP如何传递?

看看流程图就明白了。

最后附事件分发流程图:

事件分发流程图

其实还有一些特殊情况,比如说事件丢弃,以后再加以说明。

上一篇下一篇

猜你喜欢

热点阅读