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

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)的源碼。

首先看下部分源碼:


這段代碼,很顯然是事件攔截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,其實也大都涵蓋在上述分析中,聰明的小夥伴們,可以自行總結一波

尾聲

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章