Android事件机制(三)

Android事件机制(一)从代码演示的角度整理了一下我对Android事件传递的理解;
Android事件机制(二)从源码的角度分析了一下事件传递的流程,描述了一下onTouchEvent返回false(事件没有被消费)的情况;
接下来看一下事件被消费的情况。

事件分发机制针对的其实可以看作是一系列的事件,也就是一个事件序列,由一个ACTION_DOWN开头,中间n个ACTION_MOVE,然后以ACTION_UPACTION_CANCEL结束。
如果给一个控件注册了Touch事件,每次点击它的时候都会触发一系列的ACTION_DOWN、ACTION_MOVE、ACTION_UP等事件。
需要注意的是,如果在执行ACTION_DOWN的时候dispatchTouchEvent返回了false,后面一系列其它的action就不会再得到执行了。

在代码中设置MyView.onTouchEvent返回true

Android事件机制(三)_第1张图片
MyView

运行之后打印日志如下:

Log_5

事件分发的原理跟上篇最后分析Log_1的一样,进行事件处理时,当调用到View.onTouchEvent的时候,这个方法返回了true,即MyView消费了这个事件,从而使MyView.dispatchTouchEvent、MyViewGroupB.dispatchTouchEvent、MyViewGroupA.dispatchTouchEvent这三个方法都返回了true,并且在MyViewGroupB和MyViewGroupA中,mFirstTouchTarget被赋值,导致其super.dispatchTouchEvent没有被调用,也就没有打印出MyViewGroupB和MyViewGroupA的onTouchEvent日志。

每次的Touch事件,总是从ACTION_DOWN开始,此时会重置所有状态,这从ViewGroup的源码也可以看出。

Android事件机制(三)_第2张图片
Android事件机制(三)_第3张图片
Android事件机制(三)_第4张图片
ViewGroup.dispatchTouchEvent

ACTION_DOWN开始,当MyView.onTouchEvent返回true之后,在MyViewGroupB和MyViewGroupA中,mFirstTouchTarget被赋值,接着在收到ACTION_MOVE、ACTION_UP的action之后,由于mFirstTouchTarget不为空,所以最后还是调到MyView.onTouchEvent,由于MyView消费了事件,事件处理也就不再传给MyViewGroupB和MyViewGroupA,最后打印出图Log_5的日志,这一轮的Touch事件也就结束了。

稍微对MyView.onTouchEvent改动一下:

Android事件机制(三)_第5张图片
MyView.onTouchEvent

此时再看一下打印的日志:

即,在执行ACTION_DOWN的时候,dispatchTouchEvent返回了false,所以后面一系列其它的action就没有再执行。

再对MyViewGroupB.onTouchEventMyView.onTouchEvent改动一下,都返回true,打印的日志如下:

Android事件机制(三)_第6张图片

可以看出,事件处理还是到MyView结束的。
可以简单的认为,如果父View和子View同时会对事件进行消费,那么子View的消费优先。

上面的例子都是直接修改MyView.onTouchEvent的返回值。

下面来看一下MyView.onTouchEvent的部分源码:

Android事件机制(三)_第7张图片
MyView.onTouchEvent

可以看到,在10288行会对可点击状态进行一个判断,默认返回false,如果是可点击的,就返回true

因为MyView默认是不可点击的,所以在MyView.onTouchEvent的实现中直接调用super.onTouchEvent的话,就进入了View.onTouchEvent,在执行了ACTION_DOWN的逻辑之后,跳过10288行的代码,直接返回false,导致后面其它的action都无法执行了。

如果给MyView设置成可点击状态,那么MyView.onTouchEvent就会返回true,接着就会处理后面的action,当执行到ACTION_UP时,在10323行会调用一个performClick函数,这个函数的代码如下:

Android事件机制(三)_第8张图片
performClick

如果设置的OnClickListener不为空,就会去调用它的onClick方法,
那么也就出现了Log_13所示的情况:

Log_13

好了,Android事件机制的学习和记录就到这里了,稍稍总结一下:
1、Android事件分发从ViewGroup传递给View;
2、Android事件处理从View回传给ViewGroup;
3、如果ViewGroup拦截了事件,就不会传递给View;
4、如果View消费了事件,就不会回传给ViewGroup;
5、如果哪个View消费了ACTION_DOWN事件,后续的action会继续分发到这个View;
6、如果哪个View在执行ACTION_DOWN的时候dispatchTouchEvent或者onTouchEvent返回了false,后面一系列其它的action就不会再得到执行。

撒花~

参考:
Android事件分发机制完全解析,带你从源码的角度彻底理解(上)
Android事件分发机制完全解析,带你从源码的角度彻底理解(下)
Android事件分发机制详解
Android群英传-事件拦截机制分析

你可能感兴趣的:(Android事件机制(三))