天天看點

帶你根據源碼了解View的事件觸發流程,主要講解為什麼子View傳回true,ViewGroup就無法接收到事件的過程

轉載請标明出處!http://blog.csdn.net/sahadev_/article/details/23839039 ,當然一般也沒人轉載。。。

一直想徹底了解View的事件分發過程,在網上也看了很多大神的部落格,但是總有一些東西不是很明白,于是自己就根據源碼畫了一個流程草圖,思路總算是清晰了。

文章分為View和ViewGroup兩部分介紹,首先來講講View的事件分發:

打開View的源碼,順着onTouch方法向上找到dispatchPointerEvent(MotionEvent event)的這個方法,在View中再沒有其它地方調用它,估計事件就是從這裡傳過來的吧。

來貼一下這個方法的源碼:

看到在這個方法中調用了dispatchTouchEvent的這個方法,dispatchTouchEven()暫時沒找到它的相關說明,權當它傳回了true,進入dispatchTouchEvent方法:

可以看到在這個方法中調用了onTouchEvent(Event),是以可知onTouchEvent(event)是由dispatchTouchEvent觸發的。如果有人對onFilterTouchEventForSecurity這方法有疑問,API中是這麼解釋的:True if the event should be dispatched, false if the event should be dropped.這句話就不用翻譯了吧,相信大家都懂。

如果onTouchEvent傳回了true,那麼dispatchTouchEvent的傳回值也為true. 對于dispatchTouchEvent的傳回值說明是這麼解釋的:True if the event was handled by the view, false otherwise. 如果傳回true,說明這個事件就被目前的這個View消費掉了,這裡的傳回值大家一定要清楚,一會在ViewGroup的說明中需要對這塊很熟悉。

接下來說一說ViewGroup的事件分發方法:

ViewGroup的事件處理相對View相對有些複雜,ViewGroup繼承于View,在View中dispatchTouchEvent是由dispatchPointerEvent觸發的,是以ViewGroup也是由dispatchPointerEvent觸發的,這裡不重要,接着看ViewGroup的dispatchTouchEvent的源代碼:

ViewGroup的dispatchTouchEvent的方法有些長,在代碼中可以看到,ViewGroup将View的該方法徹底重寫了,沒有很明顯的看到super.dispatchTouchEvent的字樣,也就是說還沒有着急把事件交給View去處理。

前幾行和View都差不錯,往下看

在第5行中調用了onInterceptTouchEvent(ev);該方法表示當按下事件觸發的時候是否要攔截本次事件,這個方法的源碼是這樣的:

如果不對它進行重寫的話,它總是傳回false,也就是說intercepted的值恒為false,接着往下看,看到 if (!canceled && !intercepted) {這一行的時候,由于intercepted為false,是以事件可以進入if内執行,接着往下看:

看到這段代碼中dispatchTransformedTouchEvent的這個方法開始對ViewGroup的子View進行事件傳遞了:

該方法的最終傳回值是布爾值,意思為是否被處理了,請看這裡:

這裡開始對子View進行事件傳遞,調用子View的dispatchTouchEvent的方法,如果被子View消費掉了本次事件,dispatchTransformedTouchEvent就傳回true,再回到那個循環:

請注意這個方法:

這個方法中的代碼是這樣的:

注意将mFirstTouchTarget賦了值,不再是null,先記住這裡,待會有用。

好了,子View循環完成之後,代碼會執行到這裡:

注意到剛剛mFirstTouchTarget被賦了值,不再是null,不為null,就不會執行if中的語句,if中的語句都做了些什麼呢?

注意第3個參數是Null,咱們再傳回到dispatchTransformedTouchEvent中(剛才已經貼過方法内的代碼):

該方法内有3處super.dispatchTouchEvent(event);因為剛才mFirstTouchTarget的值不為null,是以沒有進入if,是以ViewGroup沒法去調用super.dispatchTouchEvent(event);是以當子View把事件消費完成之後,ViewGroup就無法接收到onTouchEvent事件,這就是為什麼子View傳回true,ViewGroup就無法處理的原因。

事件傳遞到這裡也就講完了,不知道大家有沒有聽明白,如果有什麼疑問可以在下面留言,歡迎轉載!

繼續閱讀