Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android事件分發機制實例驗證

Android事件分發機制實例驗證

編輯:關於Android編程

我的程序是在MainActivity中有一個自定義的MyLayout布局,MyLayout布局下面有一個自定義的MyButton。


情況1

\
PS:表格中super代表返回父類中同名的方法,–代表沒有此方法,無返回值代表該方法的返回類型是void。

點擊非MyButton區域,結果如下:

點擊MyButton區域,結果如下:

通過這兩個結果我們可以發現事件是從上往下分發的Activity->ViewGroup->View。
但是這兩個結果還有一個不對應的地方,那就是第一個結果的MyLayout的onInterceptTouchEvent方法在抬起時沒有執行,而第二個結果執行了。這是因為ViewGroup中的dispatchTouchEvent方法只會在按下時或者該事件會繼續往下分發時才會調用onInterceptTouchEvent方法。

情況2

\

點擊非MyButton區域,結果如下:

點擊MyButton區域,結果如下:

情況2的輸出結果明顯比情況1少,這是因為MyLayout中onInterceptTouchEvent方法和onTouchEvent方法都是在ViewGroup中的dispatchTouchEvent方法中調用的,而情況二下面MyLayout中dispatchTouchEvent方法的返回值是false,不是super.dispatchTouchEvent(ev),沒有調用ViewGroup中的dispatchTouchEvent方法。因為返回值是false,所以會將事件返回給上級的onTouchEvent方法進行消費而不會繼續往下分發,因此MyLayout中的onTouch方法和onClick方法也不會執行。這樣就導致情況2下面點擊非MyButton區域與點擊MyButton區域的結果相同了。

情況3

\

點擊非MyButton區域,結果如下:

點擊MyButton區域,結果如下:

情況3的輸出結果明顯比情況2還少一條,這是因為情況3中MyLayout中dispatchTouchEvent方法的返回值是true,事件將由MyLayout中dispatchTouchEvent方法消費,不會向上傳遞由上級的onTouchEvent方法進行消費,所以情況3的輸出結果比情況2還少1條。

情況4

\

點擊非MyButton區域,結果如下:

點擊MyButton區域,結果如下:

情況4的輸出結果與情況1完全一樣,這是因為MyLayout中的onInterceptTouchEvent方法中的返回值一個是false,一個是super.dispatchTouchEvent(event),而ViewGroup的dispatchTouchEvent方法中什麼都沒有,就是返回值是false。

情況5

\

點擊非MyButton區域,結果如下:

點擊MyButton區域,結果如下:

情況5點擊非MyButton區域和點擊MyButton區域的結果相同,這是因為MyLayout中的onInterceptTouchEvent方法的返回值是true,表示將事件進行攔截,並將事件交給當前View的onTouchEvent進行處理,事件不會繼續往下分發了。

情況6

\

點擊非MyButton區域,結果如下:

點擊MyButton區域,結果如下:

情況6中點擊點擊非MyButton區域與情況1中點擊點擊非MyButton區域結果不同,這是因為情況6中的MyLayout中onTouchEvent方法返回值是false,表示當前View解決不了,會把事件向上傳遞交給上級的onTouchEvent方法處理。我們發現在抬起事件時,MainActivity沒有將事件分發給MyLayout,這是因為在之前的按下事件時,MainActivity將事件分發給MyLayout,而MyLayout之前沒有將事件處理成功,所以在抬起事件時,MainActivity不會將事件分發給MyLayout。但是在下次抬起事件時,MainActivity還是會將將事件分發給MyLayout,這是因為記憶MyLayout之前沒有將事件處理成功元素在每次抬起事件時,會通過父級的dispatchTouchEvent方法清空。<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxoMiBpZD0="情況7">情況7

\

點擊非MyButton區域,結果如下:

點擊MyButton區域,結果如下:

情況7中點擊點擊非MyButton區域比情況1中點擊點擊非MyButton區域的結果少1條,這是因為MyLayout中的onTouchEvent方法的返回值是true,表示當前View會接受並消費該事件,但是此時並沒有調用View中的onTouchEvent方法,不調用該方法Click事件就無法被響應。

情況8

\

點擊非MyButton區域,結果如下:

點擊MyButton區域,結果如下:

情況8中點擊點擊非MyButton區域比情況1中點擊點擊非MyButton區域的結果少,這是因為MyLayout中的onTouch方法返回值是true,若某個View的的onTouch方法返回值是true,則結束,若返回值是false則調用該View的onTouchEvent方法。

情況9

\

點擊非MyButton區域,結果如下:

點擊MyButton區域,結果如下:

情況10

\

點擊非MyButton區域,結果如下:

點擊MyButton區域,結果如下:

總結

該實例驗證剛好驗證了Android 編程下 Touch 事件的分發和消費機制裡面的Touch 事件分析。

下面將該博文的Touch 事件分析部分引用出來:

事件分發:public boolean dispatchTouchEvent(MotionEvent ev)


Touch 事件發生時 Activity 的 dispatchTouchEvent(MotionEvent ev) 方法會以隧道方式(從根元素依次往下傳遞直到最內層子元素或在中間某一元素中由於某一條件停止傳遞)將事件傳遞給最外層 View 的 dispatchTouchEvent(MotionEvent ev) 方法,並由該 View 的 dispatchTouchEvent(MotionEvent ev) 方法對事件進行分發。dispatchTouchEvent 的事件分發邏輯如下:

如果 return true,事件會分發給當前 View 並由 dispatchTouchEvent 方法進行消費,同時事件會停止向下傳遞; 如果 return false,事件分發分為兩種情況:
* 如果當前 View 獲取的事件直接來自 Activity,則會將事件返回給 Activity 的 onTouchEvent 進行消費;
* 如果當前 View 獲取的事件來自外層父控件,則會將事件返回給父 View 的 onTouchEvent 進行消費。 如果返回系統默認的 super.dispatchTouchEvent(ev),事件會自動的分發給當前 View 的 onInterceptTouchEvent 方法。

事件攔截:public boolean onInterceptTouchEvent(MotionEvent ev)


在外層 View 的 dispatchTouchEvent(MotionEvent ev) 方法返回系統默認的 super.dispatchTouchEvent(ev) 情況下,事件會自動的分發給當前 View 的 onInterceptTouchEvent 方法。onInterceptTouchEvent 的事件攔截邏輯如下:

如果 onInterceptTouchEvent 返回 true,則表示將事件進行攔截,並將攔截到的事件交由當前 View 的 onTouchEvent 進行處理; 如果 onInterceptTouchEvent 返回 false,則表示將事件放行,當前 View 上的事件會被傳遞到子 View 上,再由子 View 的 dispatchTouchEvent 來開始這個事件的分發; 如果 onInterceptTouchEvent 返回 super.onInterceptTouchEvent(ev),事件默認會被攔截,並將攔截到的事件交由當前 View 的 onTouchEvent 進行處理。

事件響應:public boolean onTouchEvent(MotionEvent ev)


在 dispatchTouchEvent 返回 super.dispatchTouchEvent(ev) 並且 onInterceptTouchEvent 返回 true 或返回 super.onInterceptTouchEvent(ev) 的情況下 onTouchEvent 會被調用。onTouchEvent 的事件響應邏輯如下:

如果事件傳遞到當前 View 的 onTouchEvent 方法,而該方法返回了 false,那麼這個事件會從當前 View 向上傳遞,並且都是由上層 View 的 onTouchEvent 來接收,如果傳遞到上面的 onTouchEvent 也返回 false,這個事件就會“消失”,而且接收不到下一次事件。 如果返回了 true 則會接收並消費該事件。 如果返回 super.onTouchEvent(ev) 默認處理事件的邏輯和返回 false 時相同。

情況6,7,8還有一些總結之外的知識點,要注意。

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