Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android-----事件分發機制測試系列(二)

android-----事件分發機制測試系列(二)

編輯:關於Android編程

接下來的幾篇博客將通過小Demo來測試下事件分發機制,進而能更好的理解源碼,至於源碼的分析,網上有很多帖子了,大家可以自行查看啦!

注意本篇博客是默認在你理解了ViewGroup和View事件分發源碼的基礎上講解的,請先了解源碼之後再來照著裡面的測試進行理解!!

好了,我們開始吧!

我們采用的布局文件:

 


    
         
    

 

也即布局文件圖是醬紫的:

\

測試1:(默認處理方式)

也就是我們不對整個分發過程進行任何人為干預處理,不對上面的測試代碼進行修改;

點擊MyButton按鈕之後查看Logcat輸出:

 

06-28 21:26:54.537: I/System.out(941): MainActivity--->dispatchTouchEvent--->ACTION_DOWN
06-28 21:26:54.537: I/System.out(941): MyRelativeLayout--->dispatchTouchEvent--->ACTION_DOWN
06-28 21:26:54.537: I/System.out(941): MyRelativeLayout--->onInterceptTouchEvent--->ACTION_DOWN
06-28 21:26:54.537: I/System.out(941): MyRelativeLayout--->onInterceptTouchEvent--->ACTION_DOWN--->false
06-28 21:26:54.537: I/System.out(941): MyLinearLayout--->dispatchTouchEvent--->ACTION_DOWN
06-28 21:26:54.537: I/System.out(941): MyLinearLayout--->onInterceptTouchEvent--->ACTION_DOWN
06-28 21:26:54.547: I/System.out(941): MyLinearLayout--->onInterceptTouchEvent--->ACTION_DOWN--->false
06-28 21:26:54.547: I/System.out(941): MyButton--->dispatchTouchEvent--->ACTION_DOWN
06-28 21:26:54.547: I/System.out(941): MyButton--->onTouchEvent--->ACTION_DOWN
06-28 21:26:54.567: I/System.out(941): MyButton--->onTouchEvent--->ACTION_DOWN--->true
06-28 21:26:54.567: I/System.out(941): MyButton--->dispatchTouchEvent--->ACTION_DOWN--->true
06-28 21:26:54.577: I/System.out(941): MyLinearLayout--->dispatchTouchEvent--->ACTION_DOWN--->true
06-28 21:26:54.577: I/System.out(941): MyRelativeLayout--->dispatchTouchEvent--->ACTION_DOWN--->true
06-28 21:26:54.577: I/System.out(941): MainActivity--->dispatchTouchEvent--->ACTION_DOWN--->true
06-28 21:26:54.577: I/System.out(941): MainActivity--->dispatchTouchEvent--->ACTION_MOVE
06-28 21:26:54.577: I/System.out(941): MyRelativeLayout--->dispatchTouchEvent--->ACTION_MOVE
06-28 21:26:54.577: I/System.out(941): MyRelativeLayout--->onInterceptTouchEvent--->ACTION_MOVE
06-28 21:26:54.588: I/System.out(941): MyRelativeLayout--->onInterceptTouchEvent--->ACTION_MOVE--->false
06-28 21:26:54.588: I/System.out(941): MyLinearLayout--->dispatchTouchEvent--->ACTION_MOVE
06-28 21:26:54.588: I/System.out(941): MyLinearLayout--->onInterceptTouchEvent--->ACTION_MOVE
06-28 21:26:54.588: I/System.out(941): MyLinearLayout--->onInterceptTouchEvent--->ACTION_MOVE--->false
06-28 21:26:54.588: I/System.out(941): MyButton--->dispatchTouchEvent--->ACTION_MOVE
06-28 21:26:54.598: I/System.out(941): MyButton--->onTouchEvent--->ACTION_MOVE
06-28 21:26:54.598: I/System.out(941): MyButton--->onTouchEvent--->ACTION_MOVE--->true
06-28 21:26:54.598: I/System.out(941): MyButton--->dispatchTouchEvent--->ACTION_MOVE--->true
06-28 21:26:54.598: I/System.out(941): MyLinearLayout--->dispatchTouchEvent--->ACTION_MOVE--->true
06-28 21:26:54.598: I/System.out(941): MyRelativeLayout--->dispatchTouchEvent--->ACTION_MOVE--->true
06-28 21:26:54.598: I/System.out(941): MainActivity--->dispatchTouchEvent--->ACTION_MOVE--->true
06-28 21:26:54.639: I/System.out(941): MainActivity--->dispatchTouchEvent--->ACTION_MOVE
06-28 21:26:54.639: I/System.out(941): MyRelativeLayout--->dispatchTouchEvent--->ACTION_MOVE
06-28 21:26:54.657: I/System.out(941): MyRelativeLayout--->onInterceptTouchEvent--->ACTION_MOVE
06-28 21:26:54.657: I/System.out(941): MyRelativeLayout--->onInterceptTouchEvent--->ACTION_MOVE--->false
06-28 21:26:54.668: I/System.out(941): MyLinearLayout--->dispatchTouchEvent--->ACTION_MOVE
06-28 21:26:54.668: I/System.out(941): MyLinearLayout--->onInterceptTouchEvent--->ACTION_MOVE
06-28 21:26:54.668: I/System.out(941): MyLinearLayout--->onInterceptTouchEvent--->ACTION_MOVE--->false
06-28 21:26:54.668: I/System.out(941): MyButton--->dispatchTouchEvent--->ACTION_MOVE
06-28 21:26:54.668: I/System.out(941): MyButton--->onTouchEvent--->ACTION_MOVE
06-28 21:26:54.668: I/System.out(941): MyButton--->onTouchEvent--->ACTION_MOVE--->true
06-28 21:26:54.668: I/System.out(941): MyButton--->dispatchTouchEvent--->ACTION_MOVE--->true
06-28 21:26:54.668: I/System.out(941): MyLinearLayout--->dispatchTouchEvent--->ACTION_MOVE--->true
06-28 21:26:54.668: I/System.out(941): MyRelativeLayout--->dispatchTouchEvent--->ACTION_MOVE--->true
06-28 21:26:54.668: I/System.out(941): MainActivity--->dispatchTouchEvent--->ACTION_MOVE--->true
06-28 21:26:54.677: I/System.out(941): MainActivity--->dispatchTouchEvent--->ACTION_UP
06-28 21:26:54.677: I/System.out(941): MyRelativeLayout--->dispatchTouchEvent--->ACTION_UP
06-28 21:26:54.677: I/System.out(941): MyRelativeLayout--->onInterceptTouchEvent--->ACTION_UP
06-28 21:26:54.677: I/System.out(941): MyRelativeLayout--->onInterceptTouchEvent--->ACTION_UP--->false
06-28 21:26:54.677: I/System.out(941): MyLinearLayout--->dispatchTouchEvent--->ACTION_UP
06-28 21:26:54.677: I/System.out(941): MyLinearLayout--->onInterceptTouchEvent--->ACTION_UP
06-28 21:26:54.677: I/System.out(941): MyLinearLayout--->onInterceptTouchEvent--->ACTION_UP--->false
06-28 21:26:54.677: I/System.out(941): MyButton--->dispatchTouchEvent--->ACTION_UP
06-28 21:26:54.677: I/System.out(941): MyButton--->onTouchEvent--->ACTION_UP
06-28 21:26:54.687: I/System.out(941): MyButton--->onTouchEvent--->ACTION_UP--->true
06-28 21:26:54.687: I/System.out(941): MyButton--->dispatchTouchEvent--->ACTION_UP--->true
06-28 21:26:54.687: I/System.out(941): MyLinearLayout--->dispatchTouchEvent--->ACTION_UP--->true
06-28 21:26:54.687: I/System.out(941): MyRelativeLayout--->dispatchTouchEvent--->ACTION_UP--->true
06-28 21:26:54.687: I/System.out(941): MainActivity--->dispatchTouchEvent--->ACTION_UP--->true

先來看看DOWN事件:
分發首先從MainActivity開始,執行他的dispatchTouchEvent方法,這個方法最終會通過DecorView裡面的superDispatchTouchEvent來調用ViewGroup的dispatchTouchEvent方法,而這個方法呢就開始整個View樹的分發過程了,首先分發到MyRelativeLayout上面,調用它的dispatchTouchEvent方法,接著調用它的onInterceptTouchEvent方法來查看是否攔截DOWN事件,這裡是默認情況,所以返回false不攔截,接著繼續分發到MyLinearLayout上面,調用它的dispatchTouchEvent,因為MyLinearLayout也是ViewGroup,所以會調用它的onInterceptTouchEvent來進行判斷是否攔截的判斷,這裡仍然默認,所以返回false,接著事件分發到了MyButton上面,他是一個View所以沒有onInterceptEvent事件攔截方法,因為我們沒有為他設置Touch事件監聽器,所以直接執行他的onTouchEvent方法,這個方法的默認返回值是true,因而DOWN事件在MyButton中被消費了,接下來的第11--14行輸出就是遞歸的返回過程了,因為事件已經得到消費,所以不再會執行MyLinearLayout、MyRelativeLayout、MainActivity的onTouchEvent方法了;
接下來的MOVE和UP事件的分發過程和DOWN事件是一致的,輸出也是一樣的,需要注意的是第17和20行為什麼還是會執行MyRelativeLayout和MyLinearLayout的onInterceptTouchEvent方法呢?這個需要查看下ViewGroup的源碼了,源碼在我的上篇博客有貼出來,在ViewGroup$dispatchTouchEvent源碼的第23行if語句中mFirstTouchTarget是不為null的,所以它會執行裡面的第27行onInterceptTouchEvent方法,具體來說這裡的mFirstTouchTarget其實就是封裝有MyButton的TouchTarget對象啦!

測試2:(默認處理方式)

同樣我們也不對鏈接中的測試代碼進行任何修改;

但是這次我們點擊的是除MyButton之外的空白部分,查看Logcat輸出:

 

06-29 00:09:56.982: I/System.out(1343): MainActivity--->dispatchTouchEvent--->ACTION_DOWN
06-29 00:09:56.988: I/System.out(1343): MyRelativeLayout--->dispatchTouchEvent--->ACTION_DOWN
06-29 00:09:56.988: I/System.out(1343): MyRelativeLayout--->onInterceptTouchEvent--->ACTION_DOWN
06-29 00:09:56.988: I/System.out(1343): MyRelativeLayout--->onInterceptTouchEvent--->ACTION_DOWN--->false
06-29 00:09:56.997: I/System.out(1343): MyLinearLayout--->dispatchTouchEvent--->ACTION_DOWN
06-29 00:09:56.997: I/System.out(1343): MyLinearLayout--->onInterceptTouchEvent--->ACTION_DOWN
06-29 00:09:56.997: I/System.out(1343): MyLinearLayout--->onInterceptTouchEvent--->ACTION_DOWN--->false
06-29 00:09:57.007: I/System.out(1343): MyLinearLayout--->onTouchEvent--->ACTION_DOWN
06-29 00:09:57.007: I/System.out(1343): MyLinearLayout--->onTouchEvent--->ACTION_DOWN--->false
06-29 00:09:57.007: I/System.out(1343): MyLinearLayout--->dispatchTouchEvent--->ACTION_DOWN--->false
06-29 00:09:57.007: I/System.out(1343): MyRelativeLayout--->onTouchEvent--->ACTION_DOWN
06-29 00:09:57.007: I/System.out(1343): MyRelativeLayout--->onTouchEvent--->ACTION_DOWN--->false
06-29 00:09:57.018: I/System.out(1343): MyRelativeLayout--->dispatchTouchEvent--->ACTION_DOWN--->false
06-29 00:09:57.018: I/System.out(1343): MainActivity--->onTouchEvent--->ACTION_DOWN
06-29 00:09:57.018: I/System.out(1343): MainActivity--->onTouchEvent--->ACTION_DOWN--->false
06-29 00:09:57.018: I/System.out(1343): MainActivity--->dispatchTouchEvent--->ACTION_DOWN--->false
06-29 00:09:57.098: I/System.out(1343): MainActivity--->dispatchTouchEvent--->ACTION_MOVE
06-29 00:09:57.098: I/System.out(1343): MainActivity--->onTouchEvent--->ACTION_MOVE
06-29 00:09:57.098: I/System.out(1343): MainActivity--->onTouchEvent--->ACTION_MOVE--->false
06-29 00:09:57.098: I/System.out(1343): MainActivity--->dispatchTouchEvent--->ACTION_MOVE--->false
06-29 00:09:57.107: I/System.out(1343): MainActivity--->dispatchTouchEvent--->ACTION_UP
06-29 00:09:57.107: I/System.out(1343): MainActivity--->onTouchEvent--->ACTION_UP
06-29 00:09:57.107: I/System.out(1343): MainActivity--->onTouchEvent--->ACTION_UP--->false
06-29 00:09:57.107: I/System.out(1343): MainActivity--->dispatchTouchEvent--->ACTION_UP--->false
可以看到1--7行的輸出和測試1是一樣的,第8行開始進入的是MyLinearLayout的onTouchEvent方法,這個是什麼原因呢?原因在於我們點擊的區域並不包含有MyButton,那麼事件就不會傳遞到他了,雖然我們在MyLinearLayout中沒有攔截DOWN方法,但是仍然會執行他的onTouchEvent方法,查看ViewGroup$dispatchEvent源碼(見上篇博客)的第71行if語句中的isTransformedTouchPointInView方法,我們這裡點擊的是MyButton以外的部分,那麼該方法的返回值將是false滿足if語句判斷條件,結束本次循環,又因為MyLinearLayout之後不存在別的子View了,所以執行第111行代碼進行判斷查看mFirstTouchTarget的值,當事件由ViewGroup的子元素成功處理時,mFirstTouchTarget才會被賦值指向子元素,因為現在DOWN事件沒有被任何View處理,那麼mFirstTouchTarget的值將是null,滿足第111行的if判斷語句,執行112行代碼,具體就會執行MyLinearLayout的onTouchEvent方法;了,因為MyLinearLayout並沒有消費DOWN事件,那麼他會傳遞給MyRelativeLayout來進行處理,所以出現了第11行的輸出,調用了MyRelativeLayout的onTouchEvent方法,又因為他也沒有消費DOWN事件,那麼將事件傳遞給了MainActivity,調用他的onTouchEvent方法,所以有了第14行的輸出,從第17行開始是對DOWN和UP事件的處理,可以看到此後的事件不再會傳遞到MainActivity的子View了,都是由MainActivity進行處理的,原因就在於仍然是查看上篇博客的ViewGroup$dispatchEvent源碼,在DOWN事件處理結束之後,MOVE事件還是首先分發到MainActivity上面,執行他的dispatchTouchEvent方法,也就是ViewGroup的dispatchTouchEvent方法了,在該方法中mFirstTouchTarget是為null的,因為DOWN事件並不是由MainActivity的子View處理的,只有被MainActivity的子View處理了mFirstTouchTarget才不為null,所以也就執行的是dispatchTouchEvent源碼的第112行代碼了,和上面一樣會執行super.dispatchTouchEvent了,也就是View的dispatchTouchEvent了,在這個方法裡面會執行MainActivity的onTouchEvent方法的,所以有了MianActivity直接來處理MOVE和UP事件的情況,不再將事件分發下去;

 

測試3:(MyLinearLayout僅攔截DOWN事件,但是不消費該事件)

也就是我們僅僅修改MyLinearLayout$onInterceptTouchEvent方法的case條件值為DOWN語句部分,讓他的result=true即可;

點擊MyButton按鈕之後查看Logcat輸出:

06-28 23:34:51.499: I/System.out(1203): MainActivity--->dispatchTouchEvent--->ACTION_DOWN
06-28 23:34:51.499: I/System.out(1203): MyRelativeLayout--->dispatchTouchEvent--->ACTION_DOWN
06-28 23:34:51.508: I/System.out(1203): MyRelativeLayout--->onInterceptTouchEvent--->ACTION_DOWN
06-28 23:34:51.508: I/System.out(1203): MyRelativeLayout--->onInterceptTouchEvent--->ACTION_DOWN--->false
06-28 23:34:51.508: I/System.out(1203): MyLinearLayout--->dispatchTouchEvent--->ACTION_DOWN
06-28 23:34:51.508: I/System.out(1203): MyLinearLayout--->onInterceptTouchEvent--->ACTION_DOWN
06-28 23:34:51.508: I/System.out(1203): MyLinearLayout--->onInterceptTouchEvent--->ACTION_DOWN--->true
06-28 23:34:51.517: I/System.out(1203): MyLinearLayout--->onTouchEvent--->ACTION_DOWN
06-28 23:34:51.517: I/System.out(1203): MyLinearLayout--->onTouchEvent--->ACTION_DOWN--->false
06-28 23:34:51.517: I/System.out(1203): MyLinearLayout--->dispatchTouchEvent--->ACTION_DOWN--->false
06-28 23:34:51.517: I/System.out(1203): MyRelativeLayout--->onTouchEvent--->ACTION_DOWN
06-28 23:34:51.517: I/System.out(1203): MyRelativeLayout--->onTouchEvent--->ACTION_DOWN--->false
06-28 23:34:51.517: I/System.out(1203): MyRelativeLayout--->dispatchTouchEvent--->ACTION_DOWN--->false
06-28 23:34:51.517: I/System.out(1203): MainActivity--->onTouchEvent--->ACTION_DOWN
06-28 23:34:51.517: I/System.out(1203): MainActivity--->onTouchEvent--->ACTION_DOWN--->false
06-28 23:34:51.527: I/System.out(1203): MainActivity--->dispatchTouchEvent--->ACTION_DOWN--->false
06-28 23:34:51.669: I/System.out(1203): MainActivity--->dispatchTouchEvent--->ACTION_MOVE
06-28 23:34:51.669: I/System.out(1203): MainActivity--->onTouchEvent--->ACTION_MOVE
06-28 23:34:51.669: I/System.out(1203): MainActivity--->onTouchEvent--->ACTION_MOVE--->false
06-28 23:34:51.669: I/System.out(1203): MainActivity--->dispatchTouchEvent--->ACTION_MOVE--->false
06-28 23:34:51.677: I/System.out(1203): MainActivity--->dispatchTouchEvent--->ACTION_MOVE
06-28 23:34:51.677: I/System.out(1203): MainActivity--->onTouchEvent--->ACTION_MOVE
06-28 23:34:51.677: I/System.out(1203): MainActivity--->onTouchEvent--->ACTION_MOVE--->false
06-28 23:34:51.677: I/System.out(1203): MainActivity--->dispatchTouchEvent--->ACTION_MOVE--->false
06-28 23:34:51.748: I/System.out(1203): MainActivity--->dispatchTouchEvent--->ACTION_UP
06-28 23:34:51.748: I/System.out(1203): MainActivity--->onTouchEvent--->ACTION_UP
06-28 23:34:51.748: I/System.out(1203): MainActivity--->onTouchEvent--->ACTION_UP--->false
06-28 23:34:51.748: I/System.out(1203): MainActivity--->dispatchTouchEvent--->ACTION_UP--->false
輸出中的第1--6行和測試1的結果一樣,我們直接從第7行開始分析,因為我們在MyLinearLayout中攔截了DOWN事件,所以onInterceptTouchEvent方法的返回值是true,接下來就是執行MyLinearLayout的onTouchEvent方法了,因為我們在MyLinearLayout中並沒有消費該事件,所以onTouchEvent方法返回false,相應的該事件將會交給MyLinearLayout的上一級MyRelativeLayout來處理了,所以第11行輸出調用了MyRelativeLayout的onTouchEvent方法,同樣我們沒有在MyRelativeLayout中消費DOWN事件,那麼onTouchEvent返回false,接下來該事件會交給MyRelativeLayout的上一級MainActivity來處理了,調用他的onTouchEvent方法,所以第14行輸出調用了MainActivity的onTouchEvent方法,接下來MainActivity的disPathchTouchEvent返回false,那麼到這裡DOWN事件分發就結束了,MainActivity處理了DOWN事件;接下來就是MOVE事件的分發了,剛開始當然是調用MainActivity的dispatchTouchEvent了,因為DOWN事件是MainActivity處理的,所以接下來的MOVE和UP事件不會向下分發了,直接調用MainActivity的onTouchEvent進行處理啦!

 

測試4:(MyLinearLayout僅消費DOWN事件,但是不攔截DOWN事件)

也就是僅修改MyLinearLayout的onTouchEvent方法的case條件為DOWN的部分,將此條件下的result值修改為true;

點擊MyButton查看Logcat輸出:

 

06-29 03:05:34.841: I/System.out(1406): MainActivity--->dispatchTouchEvent--->ACTION_DOWN
06-29 03:05:34.841: I/System.out(1406): MyRelativeLayout--->dispatchTouchEvent--->ACTION_DOWN
06-29 03:05:34.841: I/System.out(1406): MyRelativeLayout--->onInterceptTouchEvent--->ACTION_DOWN
06-29 03:05:34.848: I/System.out(1406): MyRelativeLayout--->onInterceptTouchEvent--->ACTION_DOWN--->false
06-29 03:05:34.848: I/System.out(1406): MyLinearLayout--->dispatchTouchEvent--->ACTION_DOWN
06-29 03:05:34.848: I/System.out(1406): MyLinearLayout--->onInterceptTouchEvent--->ACTION_DOWN
06-29 03:05:34.848: I/System.out(1406): MyLinearLayout--->onInterceptTouchEvent--->ACTION_DOWN--->false
06-29 03:05:34.848: I/System.out(1406): MyButton--->dispatchTouchEvent--->ACTION_DOWN
06-29 03:05:34.858: I/System.out(1406): MyButton--->onTouchEvent--->ACTION_DOWN
06-29 03:05:34.858: I/System.out(1406): MyButton--->onTouchEvent--->ACTION_DOWN--->true
06-29 03:05:34.858: I/System.out(1406): MyButton--->dispatchTouchEvent--->ACTION_DOWN--->true
06-29 03:05:34.858: I/System.out(1406): MyLinearLayout--->dispatchTouchEvent--->ACTION_DOWN--->true
06-29 03:05:34.858: I/System.out(1406): MyRelativeLayout--->dispatchTouchEvent--->ACTION_DOWN--->true
06-29 03:05:34.858: I/System.out(1406): MainActivity--->dispatchTouchEvent--->ACTION_DOWN--->true
06-29 03:05:34.947: I/System.out(1406): MainActivity--->dispatchTouchEvent--->ACTION_MOVE
06-29 03:05:34.947: I/System.out(1406): MyRelativeLayout--->dispatchTouchEvent--->ACTION_MOVE
06-29 03:05:34.947: I/System.out(1406): MyRelativeLayout--->onInterceptTouchEvent--->ACTION_MOVE
06-29 03:05:34.947: I/System.out(1406): MyRelativeLayout--->onInterceptTouchEvent--->ACTION_MOVE--->false
06-29 03:05:34.947: I/System.out(1406): MyLinearLayout--->dispatchTouchEvent--->ACTION_MOVE
06-29 03:05:34.947: I/System.out(1406): MyLinearLayout--->onInterceptTouchEvent--->ACTION_MOVE
06-29 03:05:34.947: I/System.out(1406): MyLinearLayout--->onInterceptTouchEvent--->ACTION_MOVE--->false
06-29 03:05:34.947: I/System.out(1406): MyButton--->dispatchTouchEvent--->ACTION_MOVE
06-29 03:05:34.947: I/System.out(1406): MyButton--->onTouchEvent--->ACTION_MOVE
06-29 03:05:34.947: I/System.out(1406): MyButton--->onTouchEvent--->ACTION_MOVE--->true
06-29 03:05:34.947: I/System.out(1406): MyButton--->dispatchTouchEvent--->ACTION_MOVE--->true
06-29 03:05:34.957: I/System.out(1406): MyLinearLayout--->dispatchTouchEvent--->ACTION_MOVE--->true
06-29 03:05:34.957: I/System.out(1406): MyRelativeLayout--->dispatchTouchEvent--->ACTION_MOVE--->true
06-29 03:05:34.957: I/System.out(1406): MainActivity--->dispatchTouchEvent--->ACTION_MOVE--->true
06-29 03:05:34.957: I/System.out(1406): MainActivity--->dispatchTouchEvent--->ACTION_UP
06-29 03:05:34.957: I/System.out(1406): MyRelativeLayout--->dispatchTouchEvent--->ACTION_UP
06-29 03:05:34.957: I/System.out(1406): MyRelativeLayout--->onInterceptTouchEvent--->ACTION_UP
06-29 03:05:34.957: I/System.out(1406): MyRelativeLayout--->onInterceptTouchEvent--->ACTION_UP--->false
06-29 03:05:34.968: I/System.out(1406): MyLinearLayout--->dispatchTouchEvent--->ACTION_UP
06-29 03:05:34.968: I/System.out(1406): MyLinearLayout--->onInterceptTouchEvent--->ACTION_UP
06-29 03:05:34.968: I/System.out(1406): MyLinearLayout--->onInterceptTouchEvent--->ACTION_UP--->false
06-29 03:05:34.968: I/System.out(1406): MyButton--->dispatchTouchEvent--->ACTION_UP
06-29 03:05:34.968: I/System.out(1406): MyButton--->onTouchEvent--->ACTION_UP
06-29 03:05:34.968: I/System.out(1406): MyButton--->onTouchEvent--->ACTION_UP--->true
06-29 03:05:34.968: I/System.out(1406): MyButton--->dispatchTouchEvent--->ACTION_UP--->true
06-29 03:05:34.968: I/System.out(1406): MyLinearLayout--->dispatchTouchEvent--->ACTION_UP--->true
06-29 03:05:34.968: I/System.out(1406): MyRelativeLayout--->dispatchTouchEvent--->ACTION_UP--->true
06-29 03:05:34.968: I/System.out(1406): MainActivity--->dispatchTouchEvent--->ACTION_UP--->true
你會發現這個測試的Logcat輸出和測試1的輸出是一模一樣的,原因在於,我們在MyLinearLayout僅僅是消費了DOWN事件,但是沒有攔截他,那麼該事件還是會分發到MyButton上面的,而MyButton作為View,在執行他的onTouchEvent方法的時候默認是消費DOWN事件的,也就是說DOWN事件在MyButton已經被消費了,所以11--14行只是遞歸的退出過程,並沒有執行MyLinearLayout、MyRelativeLayout、MainActivity的任何方法的,以後的MOVE事件和UP事件處理方法和DOWN事件是一致的;

測試5:(那麼我們在測試4的基礎上修改MyButton的onTouchEvent方法case條件為DOWN部分,讓他返回false看看會有什麼情況發生吧)

也就是我們這裡是在鏈接測試代碼的基礎上修改了MyLinearLayout的onTouchEvent方法的case條件為DOWN的部分,將此條件下的result值修改為true;同時修改MyButton的onTouchEvent方法case條件為DOWN部分,讓他返回false;

點擊MyButton查看Logcat輸出:

 

06-29 03:24:15.534: I/System.out(1450): MainActivity--->dispatchTouchEvent--->ACTION_DOWN
06-29 03:24:15.537: I/System.out(1450): MyRelativeLayout--->dispatchTouchEvent--->ACTION_DOWN
06-29 03:24:15.537: I/System.out(1450): MyRelativeLayout--->onInterceptTouchEvent--->ACTION_DOWN
06-29 03:24:15.537: I/System.out(1450): MyRelativeLayout--->onInterceptTouchEvent--->ACTION_DOWN--->false
06-29 03:24:15.537: I/System.out(1450): MyLinearLayout--->dispatchTouchEvent--->ACTION_DOWN
06-29 03:24:15.547: I/System.out(1450): MyLinearLayout--->onInterceptTouchEvent--->ACTION_DOWN
06-29 03:24:15.547: I/System.out(1450): MyLinearLayout--->onInterceptTouchEvent--->ACTION_DOWN--->false
06-29 03:24:15.557: I/System.out(1450): MyButton--->dispatchTouchEvent--->ACTION_DOWN
06-29 03:24:15.557: I/System.out(1450): MyButton--->onTouchEvent--->ACTION_DOWN
06-29 03:24:15.557: I/System.out(1450): MyButton--->onTouchEvent--->ACTION_DOWN--->false
06-29 03:24:15.557: I/System.out(1450): MyButton--->dispatchTouchEvent--->ACTION_DOWN--->false
06-29 03:24:15.577: I/System.out(1450): MyLinearLayout--->onTouchEvent--->ACTION_DOWN
06-29 03:24:15.577: I/System.out(1450): MyLinearLayout--->onTouchEvent--->ACTION_DOWN--->true
06-29 03:24:15.577: I/System.out(1450): MyLinearLayout--->dispatchTouchEvent--->ACTION_DOWN--->true
06-29 03:24:15.577: I/System.out(1450): MyRelativeLayout--->dispatchTouchEvent--->ACTION_DOWN--->true
06-29 03:24:15.577: I/System.out(1450): MainActivity--->dispatchTouchEvent--->ACTION_DOWN--->true
06-29 03:24:15.650: I/System.out(1450): MainActivity--->dispatchTouchEvent--->ACTION_MOVE
06-29 03:24:15.650: I/System.out(1450): MyRelativeLayout--->dispatchTouchEvent--->ACTION_MOVE
06-29 03:24:15.650: I/System.out(1450): MyRelativeLayout--->onInterceptTouchEvent--->ACTION_MOVE
06-29 03:24:15.657: I/System.out(1450): MyRelativeLayout--->onInterceptTouchEvent--->ACTION_MOVE--->false
06-29 03:24:15.657: I/System.out(1450): MyLinearLayout--->dispatchTouchEvent--->ACTION_MOVE
06-29 03:24:15.657: I/System.out(1450): MyLinearLayout--->onTouchEvent--->ACTION_MOVE
06-29 03:24:15.657: I/System.out(1450): MyLinearLayout--->onTouchEvent--->ACTION_MOVE--->false
06-29 03:24:15.657: I/System.out(1450): MyLinearLayout--->dispatchTouchEvent--->ACTION_MOVE--->false
06-29 03:24:15.657: I/System.out(1450): MyRelativeLayout--->dispatchTouchEvent--->ACTION_MOVE--->false
06-29 03:24:15.657: I/System.out(1450): MainActivity--->onTouchEvent--->ACTION_MOVE
06-29 03:24:15.657: I/System.out(1450): MainActivity--->onTouchEvent--->ACTION_MOVE--->false
06-29 03:24:15.657: I/System.out(1450): MainActivity--->dispatchTouchEvent--->ACTION_MOVE--->false
06-29 03:24:15.657: I/System.out(1450): MainActivity--->dispatchTouchEvent--->ACTION_UP
06-29 03:24:15.667: I/System.out(1450): MyRelativeLayout--->dispatchTouchEvent--->ACTION_UP
06-29 03:24:15.667: I/System.out(1450): MyRelativeLayout--->onInterceptTouchEvent--->ACTION_UP
06-29 03:24:15.667: I/System.out(1450): MyRelativeLayout--->onInterceptTouchEvent--->ACTION_UP--->false
06-29 03:24:15.667: I/System.out(1450): MyLinearLayout--->dispatchTouchEvent--->ACTION_UP
06-29 03:24:15.667: I/System.out(1450): MyLinearLayout--->onTouchEvent--->ACTION_UP
06-29 03:24:15.667: I/System.out(1450): MyLinearLayout--->onTouchEvent--->ACTION_UP--->false
06-29 03:24:15.667: I/System.out(1450): MyLinearLayout--->dispatchTouchEvent--->ACTION_UP--->false
06-29 03:24:15.667: I/System.out(1450): MyRelativeLayout--->dispatchTouchEvent--->ACTION_UP--->false
06-29 03:24:15.667: I/System.out(1450): MainActivity--->onTouchEvent--->ACTION_UP
06-29 03:24:15.667: I/System.out(1450): MainActivity--->onTouchEvent--->ACTION_UP--->false
06-29 03:24:15.667: I/System.out(1450): MainActivity--->dispatchTouchEvent--->ACTION_UP--->false
沒錯,我相信這樣的輸出結果一定會讓你大跌眼鏡,1--9行和測試4的輸出一致,第10行發現MyButton的onTouchEvent的返回是false,也就是他沒有消費了DOWN事件,那麼他會將DOWN事件傳遞給他的上一級也就是MyRelativeLayout了,執行他的onTouchEvent方法,因為我們在MyRelativeLayout中消費了DOWN事件,所以第13行返回了true,接下來的14--16行就是遞歸的退出過程了,實質上沒有執行任何方法的;繼續查看對於MOVE事件的輸出,剛開始的17--21行的分發過程是正常過程,發現第22行直接就去執行MyLinearLayout的onTouchEvent方法了,原因在於分發到MyLinearLayout的時候,mFirstTouchTarget(當事件由ViewGroup的子元素成功處理時,mFirstTouchTarget會被賦值指向子元素,因為上面的DOWN事件是由MyLinearLayout處理的,不是他的子元素,所以mFirstTouchTarget的值是等於null的,這也就解釋了為什麼MyRelativeLayout會執行onInterceptTouchEvent而MyLinearLayout不會執行onInterceptTouchEvent,如果你對這裡不太明白,建議你還是先去看看ViewGroup$dispatchTouchEvent源碼部分mFirstTouchTarget的作用到底是什麼吧),因為我們沒有在MyLinearLayout中消費MOVE事件,所以第23行onTouchEvent方法返回的是false,接下來就只好把MOVE事件傳遞給MainActivity來處理了,很多人在想,為什麼不把時間傳遞給MyRelativeLayout來處理呢?原因在於在事件分發機制中有一個用來存儲可以處理DOWN事件的鏈表,如果某個View可以處理DOWN事件的話那麼會將該View加入到這個鏈表中,從上面的DOWN事件處理過程中發現MyLinearLayout將事件消費掉之後,MyRelativeLayout不可能有資格處理DOWN事件的,所以他不會在這個鏈表中,那麼MOVE事件就只能給MainActivity處理了,他就像是一個母親一樣,兒子們解決不了的問題最後都無條件的交給她來處理了;隨後的MOVE事件以及UP事件的處理過程就和第一次的MOVE事件處理過程一樣啦!

測試6:(MyLinearLayout既攔截DOWN事件,同時也消費DOWN事件)

也就是我們修改MyLinearLayout$onInterceptTouchEvent方法的case條件值為DOWN語句部分,讓他的result=true,同時修改MyLinearLayout的onTouchEvent方法的case條件為DOWN的部分,將此條件下的result值修改為true;

點擊MyButton查看Logcat輸出:

 

06-29 03:52:57.487: I/System.out(1508): MainActivity--->dispatchTouchEvent--->ACTION_DOWN
06-29 03:52:57.487: I/System.out(1508): MyRelativeLayout--->dispatchTouchEvent--->ACTION_DOWN
06-29 03:52:57.487: I/System.out(1508): MyRelativeLayout--->onInterceptTouchEvent--->ACTION_DOWN
06-29 03:52:57.487: I/System.out(1508): MyRelativeLayout--->onInterceptTouchEvent--->ACTION_DOWN--->false
06-29 03:52:57.497: I/System.out(1508): MyLinearLayout--->dispatchTouchEvent--->ACTION_DOWN
06-29 03:52:57.497: I/System.out(1508): MyLinearLayout--->onInterceptTouchEvent--->ACTION_DOWN
06-29 03:52:57.507: I/System.out(1508): MyLinearLayout--->onInterceptTouchEvent--->ACTION_DOWN--->true
06-29 03:52:57.507: I/System.out(1508): MyLinearLayout--->onTouchEvent--->ACTION_DOWN
06-29 03:52:57.507: I/System.out(1508): MyLinearLayout--->onTouchEvent--->ACTION_DOWN--->true
06-29 03:52:57.507: I/System.out(1508): MyLinearLayout--->dispatchTouchEvent--->ACTION_DOWN--->true
06-29 03:52:57.507: I/System.out(1508): MyRelativeLayout--->dispatchTouchEvent--->ACTION_DOWN--->true
06-29 03:52:57.507: I/System.out(1508): MainActivity--->dispatchTouchEvent--->ACTION_DOWN--->true
06-29 03:52:57.593: I/System.out(1508): MainActivity--->dispatchTouchEvent--->ACTION_MOVE
06-29 03:52:57.593: I/System.out(1508): MyRelativeLayout--->dispatchTouchEvent--->ACTION_MOVE
06-29 03:52:57.598: I/System.out(1508): MyRelativeLayout--->onInterceptTouchEvent--->ACTION_MOVE
06-29 03:52:57.598: I/System.out(1508): MyRelativeLayout--->onInterceptTouchEvent--->ACTION_MOVE--->false
06-29 03:52:57.598: I/System.out(1508): MyLinearLayout--->dispatchTouchEvent--->ACTION_MOVE
06-29 03:52:57.598: I/System.out(1508): MyLinearLayout--->onTouchEvent--->ACTION_MOVE
06-29 03:52:57.598: I/System.out(1508): MyLinearLayout--->onTouchEvent--->ACTION_MOVE--->false
06-29 03:52:57.598: I/System.out(1508): MyLinearLayout--->dispatchTouchEvent--->ACTION_MOVE--->false
06-29 03:52:57.598: I/System.out(1508): MyRelativeLayout--->dispatchTouchEvent--->ACTION_MOVE--->false
06-29 03:52:57.598: I/System.out(1508): MainActivity--->onTouchEvent--->ACTION_MOVE
06-29 03:52:57.598: I/System.out(1508): MainActivity--->onTouchEvent--->ACTION_MOVE--->false
06-29 03:52:57.598: I/System.out(1508): MainActivity--->dispatchTouchEvent--->ACTION_MOVE--->false
06-29 03:52:57.598: I/System.out(1508): MainActivity--->dispatchTouchEvent--->ACTION_UP
06-29 03:52:57.598: I/System.out(1508): MyRelativeLayout--->dispatchTouchEvent--->ACTION_UP
06-29 03:52:57.598: I/System.out(1508): MyRelativeLayout--->onInterceptTouchEvent--->ACTION_UP
06-29 03:52:57.608: I/System.out(1508): MyRelativeLayout--->onInterceptTouchEvent--->ACTION_UP--->false
06-29 03:52:57.608: I/System.out(1508): MyLinearLayout--->dispatchTouchEvent--->ACTION_UP
06-29 03:52:57.608: I/System.out(1508): MyLinearLayout--->onTouchEvent--->ACTION_UP
06-29 03:52:57.608: I/System.out(1508): MyLinearLayout--->onTouchEvent--->ACTION_UP--->false
06-29 03:52:57.608: I/System.out(1508): MyLinearLayout--->dispatchTouchEvent--->ACTION_UP--->false
06-29 03:52:57.608: I/System.out(1508): MyRelativeLayout--->dispatchTouchEvent--->ACTION_UP--->false
06-29 03:52:57.608: I/System.out(1508): MainActivity--->onTouchEvent--->ACTION_UP
06-29 03:52:57.608: I/System.out(1508): MainActivity--->onTouchEvent--->ACTION_UP--->false
06-29 03:52:57.608: I/System.out(1508): MainActivity--->dispatchTouchEvent--->ACTION_UP--->false
可以看出1--6行的輸出和測試1是一樣的,第7行因為我們在MyLinearLayout中攔截了DOWN事件,所以執行他的onInterceptTouchEvent方法時返回的是true,接下來就是執行他自身的onTouchEvent方法了,同樣我們在MyLinearLayout中消費了DOWN事件,所以第9行MyLinearLayout的onTouchEvent方法返回true,這樣的話DOWN事件處理結束,10--12行是遞歸退出過程,第13行開始進行MOVE事件的分發,首先當然是執行MainActivity的dispatchTouchEvent方法了,接著將其分發到了MyRelativeLayout上面,執行他的dispatchTouchEvent方法,也就是執行ViewGroup的dispatchTouchEvent方法了,這個方法中的mFirstTouchTarget不為null,所以會執行MyRelativeLayout的onInterceptTouchEvent方法,因為MyRelativeLayout沒有攔截MOVE事件,因而該方法返回false,那麼就將事件分發到了MyLinearLayout上面了,執行他的dispatchTouchEvent方法,此時這個方法裡面的mFirstTouchTarget是等於null的,原因在於前面的DOWN事件是當前View執行的,所以不會執行他的onInterceptTouchEvent方法,同樣因為mFirstTouchTarget為null,接下來就會執行MyLinearLayout的onTouchEvent方法,因為我們沒有在MyLinearLayout中消費MOVE事件,那麼該事件會進行回傳,但是之前能處理DOWN事件的View只有MyLinearLayout,而此時他又沒有消費MOVE事件,那麼接下來只能交給MainActivity來處理了;之後的MOVE事件以及UP事件的處理過程和第一次MOVE的過程是一致;

從上面的6個測試代碼我們可以得出以下結論:

(1)如果一個View沒有處理過DOWN事件,即沒有通過調用該View的onTouchEvent方法來處理DOWN事件,那麼他就沒有權利執行隨後的MOVE以及UP事件,注意這裡所說的View是包括ViewGroup的,並且這裡所說的處理DOWN事件意思只是處理,沒有說非要消費掉DOWN事件;

(2)如果一個View(當然這裡指的是ViewGroup)的DOWN事件是由當前View自己處理的,那麼接下來的MOVE或者UP事件如果能夠傳遞到當前View的話,是不再會執行當前View的onInterceptTouchEvent方法的,直接會去執行他的onTouchEvent方法的;

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved