android事件传递机制测试分析

Java基础

浏览数:88

2020-6-16

情景:activity-viewGroup-|ChildViewUp(ChildUp)(叠在上面的view)

                                         |ChildViewDown(ChildDown)(叠在下面的view)

注:

1、以下事件如果不特指均为onTouchEvent

2、如果onTouchListener没有设置,onTouchEvent是事件真正处理和消费的位置

3、该情景用于描述事件传递的基本单元,更加复杂的结构都可以由该情景组成

4、以下说的’传递给XXX’值的是事件传递给该view的onTouchEvent方法中

5、所有的ACTION_DOWN事件都会经过viewgroup的onInterceptTouchEvent方法

6、如果ChildView消费了ACTION_DOWN事件,所有后续事件仍然会经过该viewgroup的onInterceptTouchEvent方法

7、如果viewgroup消费了ACTION_DOWN事件,所有后续事件不会经过该viewgroup的onInterceptTouchEvent方法

8、所有事件都是由dispatchTouchEvent方法发起传递的

 假设一、viewGroup的onInterceptTouchEvent返回false(即父布局不拦截事件)

1、如果一个View不消费ACTION_DOWN事件,那么该View最多只会接收到ACTION_DOWN事件

2、如果一个View消费了ACTION_DOWN事件,该view将处理所有事件

3、当一个ACTION_DOWN事件到来,ViewGroup会遍历其ChildView,将事件从上层ChildView依次传递给下层ChildView,当有一个ChildView消费了ACTION_DOWN事件,往后的事件都会交由该ChildView处理,同时ChildView的遍历也会结束.

4、如果该ChildView消费了ACTION_DOWN事件,剩余的事件不管该childView消费与否都会先传递给viewgrou的onInterceptTouchEvent方法,再传递给该ChildView,如果该ChildVeiw不消费剩余这些事件(ACTION_MOVE等),那么这些事件会交给activity处理,并且activity消费不消费都没有所谓

5、如果没有ChildView愿意消费ACTION_DOWN事件,那么该ACTION_DOWN事件会传递给Viewgroup,如果viewgroup消费了ACTION_DOWN事件,后续事件(ACTION_MOVE等)不管消费与否,都会传递过来,如果viewgroup不消费后续事件,同样最后会传递给activity(如果viewgroup上面还有viewgroup,后续事件同样会先经由上级viewgroup的onInterceptEvent方法)

假设二、viewGroup的onInterceptTouchEvent将返回true(即父布局要拦截事件)

1、建立在假设一的基础之上

2、如果viewgroup拦截了ACTION_DOWN事件(onInterceptTouchEvent中在ACTION_DOWN事件返回true,以下同理),但viewgroup不消费该事件,onInterceptTouchEvent方法在该后续事件中不再调用,后续事件不管消费与否都会交给上一级(这里就是activity)处理,如果viewgroup消费ACTION_DOWN事件,后续事件都会交由viewgroup处理,如果viewgroup不消费后续事件,则会交给activity处理

3、如果viewgroup不拦截ACTION_DOWN事件,且某childView消费了ACTION_DOWN事件(这意味后续事件将交给该childView处理),但是viewgroup拦截了ACTION_MOVE,该ChildView将失去处理后续事件的权利,获得一个ACTION_CANCEL事件,然后该事件的消费权转移给其viewgroup.

4、如果viewgroup不拦截ACTION_DOWN事件,但又拦截了ACTION_UP事件,虽然该事件会传递给onInterceptTouchEvent方法,但不会传递到viewgroup

测试对照:

1、都不消费事件

全部接收到action-down事件,后续事件全部由activity接收处理

事件流程  

(ACTION-DOWN)viewGroup(onInterceptTouchEvent)-childUp-childDown-viewGroup-activity(ACTION-MOVE\ACTION-UP)activity   

2、viewGroup只消费action-down事件 

除activity外全部接收到action-down事件,后续事件全部由viewgroup和activity接收处理

事件流程  

(ACTION-DOWN)viewGroup(onInterceptTouchEvent)-childUp-childDown-viewGroup-activity

(ACTION-MOVE)viewGroup-activity

(ACTION-UP)viewGroup-activity 

3、viewGroup只消费action-move事件

结果同(1)并且viewGroup没有收到action-move事件

4、viewGroup只消费action-up事件

结果同(1)并且viewGroup没有收到action-up事件

5、viewGroup同时消费action-down和action-move事件

除activity外全部接收到action-down事件,接着只有viewGroup接收到action-move事件,最后viewgroup和activity先后收到action-up事件

事件流程

(ACTION-DOWN)viewGroup(onInterceptTouchEvent)-childUp-childDown-viewGroup-activity

(ACTION-MOVE)viewGroup

(ACTION-UP)viewGroup-activity  

6、viewGroup同时消费action-down和action-up事件

除activity外全部接收到action-down事件,接着activity和viewGroup收到action-move事件,最后只有viewGroup接收到action-up事件

(ACTION-DOWN)viewGroup(onInterceptTouchEvent)-childUp-childDown-viewGroup-activity

(ACTION-MOVE)viewGroup-activity

(ACTION-UP)viewGroup

7、ChildViewUp消费actionDown事件

事件流程

(ACTION-DOWN)viewGroup(onInterceptTouchEvent)-childUp

(ACTION-MOVE)viewGroup(onInterceptTouchEvent)-childUp-activity

(ACTION-UP)viewGroup(onInterceptTouchEvent)-childUp-activity

8、ChildViewDown消费actionDown事件

事件流程

(ACTION-DOWN)viewGroup(onInterceptTouchEvent)-childUp-childDown

(ACTION-MOVE)viewGroup(onInterceptTouchEvent)-childDown-activity

(ACTION-UP)viewGroup(onInterceptTouchEvent)-childDown-activity  

9、ChildViewUp消费actionDown和actionMove事件

事件流程

(ACTION-DOWN)viewGroup(onInterceptTouchEvent)-childUp

(ACTION-MOVE)viewGroup(onInterceptTouchEvent)-childUp

(ACTION-UP)viewGroup(onInterceptTouchEvent)-childUp-activity

10、ChildViewUp消费所有事件,Viewgroup的onInterceptTouchEvent方法拦截actionDown事件

事件流程

(ACTION-DOWN)viewGroup(onInterceptTouchEvent)-viewGroup(onTouchEvent)-activity

(ACTION-MOVE)activity

(ACTION-UP)activity 

11、ChildViewUp消费所有事件,ViewGroup的onInterceptTouchEvent方法拦截actionMove事件

事件流程

(ACTION-DOWN)viewGroup(onInterceptTouchEvent)-childUp

(ACTION-CANCEL)childUp

(ACTION-MOVE)activity

后面的n个move交由viewgroup处理

(ACTION-UP)viewgroup(onTouchEvent)-activity

childUp消费了actiondown事件,因此后续的事件本来应该交由childUp处理,但其父布局将ACTION_MOVE事件拦截了,所以该事件序列交由其父布局处理,childUp被传递了一个ACTION_CANCEL以结束事件序列的处理

12、ChildViewUp消费所有事件,ViewGroup的onInterceptTouchEvent方法拦截ACTION_UP事件

事件流程

(ACTION-DOWN)viewGroup(onInterceptTouchEvent)-childUp

(ACTION-MOVE)viewGroup(onInterceptTouchEvent)-childUp

(ACTION-UP)viewGroup(onInterceptTouchEvent)-childUp

ACTION_UP事件不会被拦截(会经过onInterceptTouchEvent方法)  

总结:

所有事件都是从dispatchTouchEvent开始的,不同点在于,有些view是viewgroup,有些就是view。如果该view是viewgroup,需要考虑其对事件的拦截和对子view的事件传递,一个view消费了事件(事件能传递给它),如果不考虑拦截,那么后续的事件都会传递给它,考虑拦截,拦截后事件处理权交给viewgroup这个view(相当于viewgroup消费了ACTION_DOWN),如果没有view消费事件(ACTION_DOWN),activity消费之。

Demo下载

作者:franos