Android事件机制(一)从代码演示的角度整理了一下我对Android事件传递的理解;
Android事件机制(二)从源码的角度分析了一下事件传递的流程,描述了一下onTouchEvent
返回false
(事件没有被消费)的情况;
接下来看一下事件被消费的情况。
事件分发机制针对的其实可以看作是一系列的事件,也就是一个事件序列,由一个ACTION_DOWN
开头,中间n个ACTION_MOVE
,然后以ACTION_UP
或ACTION_CANCEL
结束。
如果给一个控件注册了Touch事件,每次点击它的时候都会触发一系列的ACTION_DOWN、ACTION_MOVE、ACTION_UP
等事件。
需要注意的是,如果在执行ACTION_DOWN
的时候dispatchTouchEvent
返回了false
,后面一系列其它的action就不会再得到执行了。
在代码中设置MyView.onTouchEvent
返回true
:
运行之后打印日志如下:
事件分发的原理跟上篇最后分析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的源码也可以看出。
从ACTION_DOWN
开始,当MyView.onTouchEvent
返回true
之后,在MyViewGroupB和MyViewGroupA中,mFirstTouchTarget被赋值,接着在收到ACTION_MOVE、ACTION_UP
的action之后,由于mFirstTouchTarget不为空,所以最后还是调到MyView.onTouchEvent
,由于MyView消费了事件,事件处理也就不再传给MyViewGroupB和MyViewGroupA,最后打印出图Log_5的日志,这一轮的Touch事件也就结束了。
稍微对MyView.onTouchEvent
改动一下:
此时再看一下打印的日志:
即,在执行ACTION_DOWN
的时候,dispatchTouchEvent
返回了false
,所以后面一系列其它的action就没有再执行。
再对MyViewGroupB.onTouchEvent
和MyView.onTouchEvent
改动一下,都返回true
,打印的日志如下:
可以看出,事件处理还是到MyView结束的。
可以简单的认为,如果父View和子View同时会对事件进行消费,那么子View的消费优先。
上面的例子都是直接修改MyView.onTouchEvent
的返回值。
下面来看一下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
函数,这个函数的代码如下:
如果设置的OnClickListener不为空,就会去调用它的onClick方法,
那么也就出现了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群英传-事件拦截机制分析