1.什麼是事件分發
做過android乃至做過UI開發的IT從業者大都接觸過這個名詞,顧名思義,即一系列事件的分發,這裡我們將細緻的探討下android端的觸控事件的分發機制。
2.為什麼要“炒冷飯”
android事件分發,度娘上一抓一大把,為什麼我還要寫這篇部落格?這是個好問題,我看過不少相關的博文,也看過相應書籍對“事件分發”的解釋,但可能入門不久,之前一直沒領悟透徹,一些文章也沒讓我細緻的體悟到個鐘緣由,疑問有:
- 為什麼子view若是不在
MotionEvent.ACTION_DOWN
事件返回true的話,之後的所有事件都無法處理了? - 為什麼一旦
view
消耗了點選事件,那麼之後的該系列事件就都由該view
消耗了? - 在2的基礎上,為什麼
View#requestDisallowInterptTouchEvent(false)
又能將事件的處理權交出去呢?
3.分析
我帶著上面兩個問題去翻看了ViewGroup#dispatchTouchEvent(MotionEvent ev)
的原始碼。
首先看下部分原始碼:
這段程式碼,很顯然是事件攔截onInterceptTouchEvent(ev)
的觸發條件,故而,途中2507和2508兩行的條件是我們需要關注的重點,當觸控事件型別為ACTION_DOWN
或者mFirstTouchTarget != null
時會進入是否攔截的判斷,這裡注意如果不滿足上述條件時,第2519行程式碼intercepted = true
,也就是說如果不是down事件的同時,mFirstTouchTarget == null
那麼該次事件交由當前ViewGroup處理。那麼重點來了,mFirstTouchTarget
是什麼?是如何賦值的?
接著看:
圖中3-28行為接著上圖的程式碼,這裡不難看出,3-7行,當事件沒取消不攔截的同時為MotionEvent.ACTION_DOWN,MotionEvent.ACTION_POINTER_DOWN, MotionEvent.ACTION_HOVER_MOVE
事件的時候dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign)
將事件分發給子view處理,若是子view的處理結果返回true則進入8-28行的邏輯並會break
跳出for迴圈
,(敲黑板)重點來了,26行newTouchTarget = addTouchTarget(child, idBitsToAssign);
進入addTouchTarget
方法,即圖中39-44行,至此mFirstTouchTarget
的賦值我們理出來了。
那麼有什麼用呢?接著看迴圈外面的邏輯:
從之前的分析,我們得知,mFirstTouchTarget只有在存在子view消費了事件後,才會!=null
,因此若是子view沒有消耗事件,則進入2643行,當前view去處理該事件。並最終在函式末尾return handled
。
4 總結
至此可以對問題1,做出合理的解釋了。當子view不消費MotionEvent.ACTION_DOWN
事件的時候,那麼在MotionEvent.ACTION_DOWN處理結束後mFirstTouchTarget是為null的
,然後該系列事件的move
等事件進入分發階段的時候,便會在圖一的2507和2508行的if校驗中進入2519行intercepted = true
始終攔截事件不再分發出去。至於問題2,問題3,其實也大都涵蓋在上述分析中,聰明的小夥伴們,可以自行總結一波
推薦
親情推薦使用阿里雲伺服器,實惠穩定 附贈優惠禮包自取: 阿里雲飛機票
尾聲
本人才疏學淺,若有不足,或是胡言亂語之處,望海涵並加以斧正。