android觸控事件分發機制,曾困惑你我的地方

騎著小貓碼程式碼丶發表於2019-01-19

1.什麼是事件分發

做過android乃至做過UI開發的IT從業者大都接觸過這個名詞,顧名思義,即一系列事件的分發,這裡我們將細緻的探討下android端的觸控事件的分發機制。

2.為什麼要“炒冷飯”

android事件分發,度娘上一抓一大把,為什麼我還要寫這篇部落格?這是個好問題,我看過不少相關的博文,也看過相應書籍對“事件分發”的解釋,但可能入門不久,之前一直沒領悟透徹,一些文章也沒讓我細緻的體悟到個鐘緣由,疑問有:

  1. 為什麼子view若是不在MotionEvent.ACTION_DOWN事件返回true的話,之後的所有事件都無法處理了?
  2. 為什麼一旦view消耗了點選事件,那麼之後的該系列事件就都由該view消耗了?
  3. 在2的基礎上,為什麼View#requestDisallowInterptTouchEvent(false)又能將事件的處理權交出去呢?

3.分析

我帶著上面兩個問題去翻看了ViewGroup#dispatchTouchEvent(MotionEvent ev)的原始碼。

首先看下部分原始碼:

android觸控事件分發機制,曾困惑你我的地方
這段程式碼,很顯然是事件攔截onInterceptTouchEvent(ev)的觸發條件,故而,途中2507和2508兩行的條件是我們需要關注的重點,當觸控事件型別為ACTION_DOWN或者mFirstTouchTarget != null時會進入是否攔截的判斷,這裡注意如果不滿足上述條件時,第2519行程式碼intercepted = true,也就是說如果不是down事件的同時,mFirstTouchTarget == null那麼該次事件交由當前ViewGroup處理。那麼重點來了,mFirstTouchTarget是什麼?是如何賦值的?

接著看:

android觸控事件分發機制,曾困惑你我的地方
圖中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的賦值我們理出來了。

那麼有什麼用呢?接著看迴圈外面的邏輯:

android觸控事件分發機制,曾困惑你我的地方
從之前的分析,我們得知,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,其實也大都涵蓋在上述分析中,聰明的小夥伴們,可以自行總結一波

推薦

親情推薦使用阿里雲伺服器,實惠穩定 附贈優惠禮包自取: 阿里雲飛機票

android觸控事件分發機制,曾困惑你我的地方

尾聲

本人才疏學淺,若有不足,或是胡言亂語之處,望海涵並加以斧正。

相關文章