如上圖所示获三,這是事件ACTION_DOWN
的流程圖认轨,而ACTION_MOVE
和ACTION_UP
則是根據ACTION_DOWN
的消費來定随夸。
- 如果
ViewGroupA
和View
都沒有對ACTION_DOWN
事件進行消費旁赊,則ACTION_MOVE
的流程就是Activity.dispatch
->Activity.onTouch
- 如果
View
的onTouch
返回了true
拥诡,對ACTION_DOWN
進行了消費绷跑,則ACTION_MOVE
的流程是Activity.dispath
->ViewGroupA.dispatch
->ViewGroupA.onIntercept
->View.dispatch
->View.onTouch
下面分析一下源碼:
如
MainActivity
繼承Activity
且重寫dispatchTouchEvent
,不調用super.dispatchTouchEvent
,則事件不再繼續(xù).當點擊事件觸發(fā),先調用Activity中的
dispatchTouchEvent
方法,然后調用的getWindow().superDispatchTouchEvent(ev)
,再看if條件,如果getWindow().superDispatchTouchEvent(ev)
返回true,則直接return,如果返回false才走onTouchEvent
.看看
getWindow().superDispatchTouchEvent(ev)
,這邊直接調用了Window
的superDispatchTouchEvent
,Window
是一個虛類,所以該方法在子類中實現,根據Window
類上面的注釋The only existing implementation of this abstract class is android.view.PhoneWindow,找到PhoneWindow
.
,再看mDecor
,
注釋也得很清楚了,top-level view of the window.并且從代碼中可以知道,DecorView
繼承了FragmeLayout
,FrameLayout
繼承自ViewGroup
.
所以調用了ViewGroup
的dispatchTouchEvent
方法.
- 那來看看
ViewGroup
的dispatchTouchEvent
方法,一看源碼,好長一段,一步步看吧.
這個標著紅色的,不在ViewGroup
里面,因為ViewGroup
繼承View
,就去View中了下
看不懂只能看注釋了,注釋還是寫的很清楚的,用于調試的一致性驗證器
,這是用于調試的,跟我們沒多大關系,然后接著往下看,
解釋一下這堆代碼,第一個條件ev.isTargetAccessibilityFocus():是否應該被有焦點的控件先處理
,第二個條件isAccessibilityFocusedViewOrHost():沒有焦點, 不處理這個事件
,結果ev.setTargetAccessibilityFocus(false);:目標View已經處理過了來, 接著用正常邏輯分發(fā)
,這部分解釋是網絡上抄來的.繼續(xù)看源碼if (onFilterTouchEventForSecurity(ev))
這個方法有注釋,是用來過濾事件以應用安全策略.
直接看一下cancelAndClearTouchTargets
方法,點擊看注釋Cancels and clears all touch targets.:取消和清除所有觸摸目標
,再看resetTouchState
方法,繼續(xù)看注釋Resets all touch state in preparation for a new cycle.:重置所有的觸摸狀態(tài)以準備一個新的周期
,我的理解,Action_Down作為新一輪事件的開始,就摒棄之前觸摸事件的狀態(tài),重新進入周期.
關于resetTouchState
還得講一下,方法里面有一個mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT;
后面需要用到.接著往下看
先看if里面的條件,條件一actionMasked == MotionEvent.ACTION_DOWN
當為Action_down事件的時候,if成立,此時第二個條件mFirstTouchTarget != null
是不成立的,代碼在resetTouchState
方法里的clearTouchTargets
,就不多解釋了,反過來,第一個條件不成立時,就不會重新清楚狀態(tài),上面講了,只有action_down時,才會清除狀態(tài),所以第一個條件不成立時,第二個條件是成立的.那就是不管咋樣,if都是成立的,那要else干啥,只能看注釋了:沒有觸摸目標拳恋,這個動作不是最初的,因此這個視圖組繼續(xù)攔截觸摸
.這就可以理解了.接著看下一個條件final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
上面在clearTouchTargets
中提到mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT;
,這兩個一看就是0.所以disallowIntercept = flase
,下面的if條件成立,進而會調用onInterceptTouchEvent(ev);
攔截方法.
接著往下看:
在紅線標注的這兩個地方調用了dispatchTransformedTouchEvent
從源碼中看出,當該ViewGroup
的child
為View
的時候砸捏,就調用super.dispatchTouchEvent
,如果還是ViewGroup
,則繼續(xù)調用child.dispatchTouchEvent