android事件傳遞機制測試分析

松林小鼠 8年前發布 | 8K 次閱讀 Android開發 移動開發

來自: http://www.jcodecraeer.com//a/anzhuokaifa/androidkaifa/2016/0226/4002.html


情景: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-MOVEACTION-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 


1456477666518059.png



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   


1456477686129387.png

1456477699113423.png


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   


1456477713989731.png

1456477721977208.png


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  


1456477734964342.png


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以結束事件序列的處理 


1456477745946268.png


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

事件流程

(ACTION-DOWN)viewGroup(onInterceptTouchEvent)-childUp 

(ACTION-MOVE)viewGroup(onInterceptTouchEvent)-childUp 

(ACTION-UP)viewGroup(onInterceptTouchEvent)-childUp 

ACTION_UP事件不會被攔截(會經過onInterceptTouchEvent方法)   


1456477755749226.png

1456477765397484.png


總結: 

所有事件都是從dispatchTouchEvent開始的,不同點在于,有些view是viewgroup,有些就是view。如果該view是viewgroup,需要考慮其對事件的攔截和對子view的事件傳遞,一個view消費了事件(事件能傳遞給它),如果不考慮攔截,那么后續的事件都會傳遞給它,考慮攔截,攔截后事件處理權交給viewgroup這個view(相當于viewgroup消費了ACTION_DOWN),如果沒有view消費事件(ACTION_DOWN),activity消費之。


 本文由用戶 松林小鼠 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!