android Touch事件傳遞機制解析

在講正題以前咱們講一段有關任務傳遞的小故事,拋磚迎玉下:android

話說一家軟件公司,來一個任務,分派給了開發經理去完成:程序員

開發經理拿到,看了一下,感受好簡單,因而spa

開發經理:分派給了開發組長.net

開發組長:分派給了本身組員(程序員設計

程序員:分派給了本身帶的實習生日誌

實習生:好苦逼,沒法分派,怎麼辦啊?只能本身幹了code

可是實習生能不能作好,有兩種狀況了。blog

狀況一繼承

實習生:通過一段時間的研究,琢磨,熬夜,奮鬥,死敲,皇天不負有心人啊,完成了。事件

後來又來一個相似的任務,也按着這樣傳遞下去了(開發經理->開發組長->程序員->實習生),又有實習生完成了。

狀況二

實習生:通過一段時間的研究,琢磨,就是毫無頭緒,沒法完成,只能求教師傅(程序員)了。

程序員:啊,我怎麼沒留意就給實習生搞了,這任務好難啊,本身研究下,也沒有頭緒,沒辦法只能請求組長了。

開發組長:這任務不難啊,怎麼我底下的人都不會了,沒辦法,只能本身搞了,通過,一段時間,完成了,感想,之後要是又有跟這個很相似的任務,我就本身弄了,不給他們弄了。

後來又來一個相似的任務,傳遞是這樣的

開發經理:分派給開發組長

開發組長:啊,又是跟着上一個很相似的任務,我本身弄吧,沒過多久也完成了!

PS:以上就是一個任務傳遞的過程。上級一開始總會想把任務分派給本身的下屬去弄,而後任務一步一步去傳遞下去,最後由一我的去完成他,固然傳遞下去,最底下人不會,也會一步一步的回滾,又他上級去完成,若是又有一個相似的任務,那個節點不會的人就不會再傳遞給他,給他也不會弄。固然實現中,這些任務的傳遞也可能被分派人去攔截,好比說,開發組長本打算分派給程序員,忽然他不想傳遞了,就半路攔截了下來。

而在咱們android Touch事件傳遞機制跟這個很相似,思想差很少,有句話說,設計來源於生活。跟Touch事件有關的處理方法主要由三個:

//分派事件
public boolean dispatchTouchEvent(MotionEvent ev)
//攔截事件 
public boolean onInterceptTouchEvent(MotionEvent ev)
//處理事件
public boolean onTouchEvent(MotionEvent event)

用他們的時候,咱們只須要重寫一下,便可操做,這三個方法主要在三種類被調用,那三種類呢?

基類 例子類 擁有的方法
繼承Activity(activity類 MainActivity(因項目而異)
dispatchTouchEvent,onTouchEvent
繼承ViewGroup(View容器 RelativeLayout,FrameLayout,LinearLayout,AbsoluteLayout,ListView,ScrollView...
dispatchTouchEvent,onInterceptTouchEvent,onTouchEvent
繼承View(View控件 Button,EditText,TextView,ImageView....
dispatchTouchEvent,onTouchEvent

 

而這三個方法的含義是什麼呢?

事件 含義
dispatchTouchEvent
用來分派事件
其中調用了onInterceptTouchEvent()和onTouchEvent(),通常不重寫該方法
onInterceptTouchEvent
用來攔截事件
ViewGroup類中的源碼實現就是{return false;}表示不攔截該事件,
事件將向下傳遞(傳遞給其子View);
若手動重寫該方法,使其返回true則表示攔截,事件將終止向下傳遞,
事件由當前ViewGroup類來處理,就是調用該類的onTouchEvent()方法
onTouchEvent
用來處理事件
返回true則表示該View能處理該事件,事件將終止向上傳遞(傳遞給其父View);
返回false表示不能處理,則把事件傳遞給其父View的onTouchEvent()方法來處理

根據上面的小故事,咱們用代碼去實現一下:

我新建了四個類:MainActivity(開發經理),FirstFrameLayout(開發組長),SecondRelativeLayout(程序員),ThirdTextView(實習生)

在界面的層次關係以下圖:

我就比如咱們前面的故事狀況一,狀況二那麼模擬下:

狀況一

首先咱們按照上面的故事狀況一那樣,任務一級一級傳遞下去(將viewgroup的類的onInterceptTouchEvent都返回false),而後事件就會一直傳遞到,ThirdTextview,最後,咱們把它的onTouchEvent返回ture(含義是實習生處理成功了)。咱們點擊藍色區域。咱們看下日誌。

狀況二

首先咱們仍是一級級傳遞下去(將viewgroup的類的onInterceptTouchEvent都返回false),而後是傳遞到ThirdTextview,咱們將它的onTouchEvent返回false(含義是實習生處理失敗了),再講SecondRelativeLayout的onTouchEvent返回false(含義是程序員處理失敗了),最後講FirstFrameLayout的onTouchEvent返回true(含義是組長處理成功了)。咱們點擊藍色區域。咱們看下日誌,以下圖。

注:上面兩種狀況的日誌圖,紅色框表明第一個任務黃色框表明第二個相似的任務。根據上圖日誌,咱們畫下傳遞圖:

狀況一事件傳遞圖:

 狀況二事件傳遞圖:

從上面兩張事件傳遞圖咱們的出來一些結論:

1.事件是先有dispatchTouchEvent分派給下一級

2.要通過onInterceptTouchEvent是否須要攔截,不攔截傳遞給下一級,最終傳遞給view控件,

3.onTouchEvent方法中,在處理事件中,若是返回True,則表示能處理,傳遞將會終止。反着,不能,若是不能的話,這會返回上一級的onTouchEvent方法中,若是仍是false,會一直到到上一層的onTouchEvent方法中。

好奇的咱們會發現一個問題:圖二中的黃色線,沒有像紅色線那樣,先傳遞到最底層,而後再回滾回去,這是爲何呢?

答:就如咱們故事中,他都知道了,底下人都不會去作了,那麼他幹嗎還分派給他呢,他就會本身作了,直接給onTouchEvent ,這就是事件傳遞中的「記憶」功能。咱們是手指點擊藍色區域,Touch事件有兩個,第一個ACTION_DOWN,第二個ACTION_UP,第一個ACTION_DOWN事件向下傳遞到某View,它把事件繼續傳遞交給它的子View,它會記錄該事件是否被它下面的View給處理成功了,(怎麼能知道呢?若是該事件會再次被向上傳遞到我這裏來由個人onTouchEvent來處理,那就說明下面的View都沒能成功處理該事件);當第二個ACTION_UP事件向下傳遞到該View,該View的dispatchTouchEvent方法機會判斷,若上次的事件由下面的view成功處理了,那麼此次的事件就繼續交給下面的來處理,若上次的事件沒有被下面的處理成功,那麼此次的事件就不會向下傳遞了,該View直接調用本身的onTouchEvent方法來處理該事件。

PS:關於這「記憶」功能的信息只在一系列事件完成以前有效,也就是從ACTION_DOWN事件開始,直到後續事件ACTION_MOVE,ACTION_UP結束後,「記憶」的信息就會清除。也就是說若是某View處理ACTION_DOWN事件失敗了(onTouchEvent()返回false),那麼後續的ACTION_MOVE,ACTION_UP等事件就不會再傳遞到該View了,由其父View本身來處理。在下一次發生ACTION_DOWN事件的時候,仍是會傳遞到該View的。

補充說明:

-》若在向下傳遞的過程當中被攔截了,即onInterceptTouchEvent方法返回true,則事件將中止向下傳遞,直接由當前的onTouchEvent方法來處理,若處理成功則OK,若處理不成功,則事件會向上傳遞。

謝謝收看。

實例代碼:http://download.csdn.net/detail/chenjie_920/8398413

相關文章
相關標籤/搜索