Android事件分發(fā)機制實例驗證

Android事件分發(fā)機制實例驗證


歡迎轉載烟零,轉載請注明原文出處http://blog.csdn.net/lavor_zl/article/details/51198634,謝謝。

事件分發(fā)機制的學習主要來自下面兩篇博文:

  • Android事件傳遞機制

  • Android 編程下 Touch 事件的分發(fā)和消費機制

    這兩篇博文寫的非常好州既,但是看完了這兩篇博文還是有一些不理解的地方,缺少一絲明悟萝映。于是親自寫下幾種情況的代碼吴叶,來看事件分發(fā)的結果,從而驗證事件分發(fā)機制序臂。驗證完后瞬間有了一種明悟蚌卤,感覺豁然開朗实束。紙上學來終覺淺,絕知此事要躬行逊彭。

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


情況1


PS:表格中super代表返回父類中同名的方法侮叮,--代表沒有此方法避矢,無返回值代表該方法的返回類型是void。

點擊非MyButton區(qū)域囊榜,結果如下:

點擊MyButton區(qū)域审胸,結果如下:

通過這兩個結果我們可以發(fā)現(xiàn)事件是從上往下分發(fā)的Activity->ViewGroup->View。
但是這兩個結果還有一個不對應的地方锦聊,那就是第一個結果的MyLayout的onInterceptTouchEvent方法在抬起時沒有執(zhí)行歹嘹,而第二個結果執(zhí)行了。這是因為ViewGroup中的dispatchTouchEvent方法只會在按下時或者該事件會繼續(xù)往下分發(fā)時才會調(diào)用onInterceptTouchEvent方法孔庭。

情況2

點擊非MyButton區(qū)域尺上,結果如下:

點擊MyButton區(qū)域,結果如下:

情況2的輸出結果明顯比情況1少圆到,這是因為MyLayout中onInterceptTouchEvent方法和onTouchEvent方法都是在ViewGroup中的dispatchTouchEvent方法中調(diào)用的怎抛,而情況二下面MyLayout中dispatchTouchEvent方法的返回值是false,不是super.dispatchTouchEvent(ev)芽淡,沒有調(diào)用ViewGroup中的dispatchTouchEvent方法马绝。因為返回值是false,所以會將事件返回給上級的onTouchEvent方法進行消費而不會繼續(xù)往下分發(fā),因此MyLayout中的onTouch方法和onClick方法也不會執(zhí)行挣菲。這樣就導致情況2下面點擊非MyButton區(qū)域與點擊MyButton區(qū)域的結果相同了富稻。

情況3

點擊非MyButton區(qū)域,結果如下:

點擊MyButton區(qū)域白胀,結果如下:

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

情況4

點擊非MyButton區(qū)域向抢,結果如下:

點擊MyButton區(qū)域认境,結果如下:

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

情況5

點擊非MyButton區(qū)域茉盏,結果如下:

點擊MyButton區(qū)域鉴未,結果如下:

情況5點擊非MyButton區(qū)域和點擊MyButton區(qū)域的結果相同,這是因為MyLayout中的onInterceptTouchEvent方法的返回值是true鸠姨,表示將事件進行攔截铜秆,并將事件交給當前View的onTouchEvent進行處理,事件不會繼續(xù)往下分發(fā)了讶迁。

情況6

點擊非MyButton區(qū)域连茧,結果如下:

點擊MyButton區(qū)域,結果如下:

情況6中點擊點擊非MyButton區(qū)域與情況1中點擊點擊非MyButton區(qū)域結果不同巍糯,這是因為情況6中的MyLayout中onTouchEvent方法返回值是false啸驯,表示當前View解決不了,會把事件向上傳遞交給上級的onTouchEvent方法處理祟峦。我們發(fā)現(xiàn)在抬起事件時罚斗,MainActivity沒有將事件分發(fā)給MyLayout,這是因為在之前的按下事件時宅楞,MainActivity將事件分發(fā)給MyLayout针姿,而MyLayout之前沒有將事件處理成功,所以在抬起事件時厌衙,MainActivity不會將事件分發(fā)給MyLayout距淫。但是在下次抬起事件時,MainActivity還是會將將事件分發(fā)給MyLayout婶希,這是因為記憶MyLayout之前沒有將事件處理成功元素在每次抬起事件時榕暇,會通過父級的dispatchTouchEvent方法清空。

情況7

點擊非MyButton區(qū)域喻杈,結果如下:

點擊MyButton區(qū)域彤枢,結果如下:

情況7中點擊點擊非MyButton區(qū)域比情況1中點擊點擊非MyButton區(qū)域的結果少1條,這是因為MyLayout中的onTouchEvent方法的返回值是true筒饰,表示當前View會接受并消費該事件缴啡,但是此時并沒有調(diào)用View中的onTouchEvent方法,不調(diào)用該方法Click事件就無法被響應龄砰。

情況8

點擊非MyButton區(qū)域,結果如下:

點擊MyButton區(qū)域讨衣,結果如下:

情況8中點擊點擊非MyButton區(qū)域比情況1中點擊點擊非MyButton區(qū)域的結果少换棚,這是因為MyLayout中的onTouch方法返回值是true,若某個View的的onTouch方法返回值是true反镇,則結束固蚤,若返回值是false則調(diào)用該View的onTouchEvent方法。

情況9

點擊非MyButton區(qū)域歹茶,結果如下:

點擊MyButton區(qū)域夕玩,結果如下:

情況10

點擊非MyButton區(qū)域你弦,結果如下:

點擊MyButton區(qū)域,結果如下:

總結

該實例驗證剛好驗證了Android 編程下 Touch 事件的分發(fā)和消費機制里面的Touch 事件分析燎孟。

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

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


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

  • 如果 return true揩页,事件會分發(fā)給當前 View 并由 dispatchTouchEvent 方法進行消費旷偿,同時事件會停止向下傳遞;
  • 如果 return false爆侣,事件分發(fā)分為兩種情況:
    * 如果當前 View 獲取的事件直接來自 Activity萍程,則會將事件返回給 Activity 的 onTouchEvent 進行消費;
    * 如果當前 View 獲取的事件來自外層父控件兔仰,則會將事件返回給父 View 的 onTouchEvent 進行消費茫负。
  • 如果返回系統(tǒng)默認的 super.dispatchTouchEvent(ev),事件會自動的分發(fā)給當前 View 的 onInterceptTouchEvent 方法乎赴。

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


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

  • 如果 onInterceptTouchEvent 返回 true无虚,則表示將事件進行攔截缔赠,并將攔截到的事件交由當前 View 的 onTouchEvent 進行處理;
  • 如果 onInterceptTouchEvent 返回 false友题,則表示將事件放行嗤堰,當前 View 上的事件會被傳遞到子 View 上,再由子 View 的 dispatchTouchEvent 來開始這個事件的分發(fā)度宦;
  • 如果 onInterceptTouchEvent 返回 super.onInterceptTouchEvent(ev)踢匣,事件默認會被攔截,并將攔截到的事件交由當前 View 的 onTouchEvent 進行處理戈抄。

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


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

  • 如果事件傳遞到當前 View 的 onTouchEvent 方法,而該方法返回了 false划鸽,那么這個事件會從當前 View 向上傳遞输莺,并且都是由上層 View 的 onTouchEvent 來接收,如果傳遞到上面的 onTouchEvent 也返回 false裸诽,這個事件就會“消失”嫂用,而且接收不到下一次事件。
  • 如果返回了 true 則會接收并消費該事件丈冬。
  • 如果返回 super.onTouchEvent(ev) 默認處理事件的邏輯和返回 false 時相同嘱函。

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

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末往弓,一起剝皮案震驚了整個濱河市疏唾,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌函似,老刑警劉巖槐脏,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異缴淋,居然都是意外死亡准给,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進店門重抖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來露氮,“玉大人,你說我怎么就攤上這事钟沛∨瞎妫” “怎么了?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵恨统,是天一觀的道長叁扫。 經(jīng)常有香客問我,道長畜埋,這世上最難降的妖魔是什么莫绣? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮悠鞍,結果婚禮上对室,老公的妹妹穿的比我還像新娘。我一直安慰自己咖祭,他們只是感情好掩宜,可當我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著么翰,像睡著了一般牺汤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上浩嫌,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天檐迟,我揣著相機與錄音,去河邊找鬼码耐。 笑死追迟,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的伐坏。 我是一名探鬼主播怔匣,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼握联,長吁一口氣:“原來是場噩夢啊……” “哼桦沉!你這毒婦竟也來了每瞒?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤纯露,失蹤者是張志新(化名)和其女友劉穎剿骨,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體埠褪,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡浓利,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了钞速。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贷掖。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖渴语,靈堂內(nèi)的尸體忽然破棺而出苹威,到底是詐尸還是另有隱情,我是刑警寧澤驾凶,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布牙甫,位于F島的核電站,受9級特大地震影響调违,放射性物質(zhì)發(fā)生泄漏窟哺。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一技肩、第九天 我趴在偏房一處隱蔽的房頂上張望且轨。 院中可真熱鬧,春花似錦亩鬼、人聲如沸殖告。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽黄绩。三九已至,卻和暖如春玷过,著一層夾襖步出監(jiān)牢的瞬間爽丹,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工辛蚊, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留粤蝎,地道東北人。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓袋马,卻偏偏與公主長得像初澎,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,611評論 2 353

推薦閱讀更多精彩內(nèi)容