摘要:今天結(jié)合流程圖和代碼來對(duì)事件分發(fā)機(jī)制做一個(gè)總結(jié),我自己起一個(gè)叫法就是個(gè)。返回就會(huì)把事件給父類的消費(fèi)。以后事件不再交給這個(gè)。到這里事件分發(fā)就說的差不多了,我們這個(gè)比較簡單,但是不影響理解原理。
今天結(jié)合流程圖和代碼來對(duì)Android事件分發(fā)機(jī)制做一個(gè)總結(jié),我自己起一個(gè)叫法就是“3個(gè)3”。
跟事件分發(fā)相關(guān)的主要有三個(gè)節(jié)點(diǎn)方法:
1.dispatchTouchEvent
2.onInterceptTouchEvent(這個(gè)只有ViewGroup有)
3.onTouchEvent
為了簡單扼要,Demo總共就三個(gè)研究對(duì)象,Activity/ViewGroup/View,從屬關(guān)系就是Activity中加載ViewGroup, ViewGroup中有一個(gè)View是Button,之所以用Button就是為了點(diǎn)擊事件。在Button點(diǎn)擊的時(shí)候看下三者事件分發(fā)的順序。
在Activity中, 主要就是添加幾個(gè)Log,在onTouchEvent中打印出MotionEvent事件,這里為了簡單主要關(guān)注
1.ACTION_DOWN 按下事件
2.ACTION_MOVE 移動(dòng)事件
3.ACTION_UP 松開事件
@Override public boolean dispatchTouchEvent(MotionEvent ev) { Log.w(Constants.TAG, "------------------------------------------"); Log.d(Constants.TAG, "MainActivity.dispatchTouchEvent"); return super.dispatchTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { String eventString; switch (event.getAction()) { case MotionEvent.ACTION_DOWN: eventString = "ACTION_DOWN"; break; case MotionEvent.ACTION_MOVE: eventString = "ACTION_MOVE"; break; case MotionEvent.ACTION_UP: eventString = "ACTION_UP"; break; default: eventString = "OTHER_EVENT"; break; } Log.d(Constants.TAG, "MainActivity.onTouchEvent: " + eventString); return super.onTouchEvent(event); }
在ViewGroup中,多了一個(gè)onInterceptTouchEvent方法。
@Override public boolean dispatchTouchEvent(MotionEvent ev) { Log.d(Constants.TAG, "ViewGroupCustom.dispatchTouchEvent"); return super.dispatchTouchEvent(ev); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { Log.d(Constants.TAG, "ViewGroupCustom.onInterceptTouchEvent"); return true; } @Override public boolean onTouchEvent(MotionEvent event) { String eventString; switch (event.getAction()) { case MotionEvent.ACTION_DOWN: eventString = "ACTION_DOWN"; break; case MotionEvent.ACTION_MOVE: eventString = "ACTION_MOVE"; break; case MotionEvent.ACTION_UP: eventString = "ACTION_UP"; break; default: eventString = "OTHER_EVENT"; break; } Log.d(Constants.TAG, "ViewGroupCustom.onTouchEvent: " + eventString); return true; }
在View中方法和Activity中一樣:
@Override public boolean dispatchTouchEvent(MotionEvent event) { Log.d(Constants.TAG, "ViewCustom.dispatchTouchEvent"); return super.dispatchTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { String eventString; switch (event.getAction()) { case MotionEvent.ACTION_DOWN: eventString = "ACTION_DOWN"; break; case MotionEvent.ACTION_MOVE: eventString = "ACTION_MOVE"; break; case MotionEvent.ACTION_UP: eventString = "ACTION_UP"; break; default: eventString = "OTHER_EVENT"; break; } Log.d(Constants.TAG, "ViewCustom.onTouchEvent: " + eventString); return super.onTouchEvent(event); }
默認(rèn)三個(gè)方法都是調(diào)用super的方法。
稍微總結(jié)下,涉及到三個(gè)3
1.第一個(gè)3就是三個(gè)研究對(duì)象:Activity/ViewGroup/View
2.第二個(gè)3就是三個(gè)方法:dispatchTouchEvent/onInterceptTouchEvent/onTouchEvent
3.第二個(gè)3就是每個(gè)方法都return3中狀態(tài)之一:super/true/false
接下來就是排列組合,事件分發(fā)就是在三個(gè)對(duì)象,三個(gè)方法,三個(gè)狀態(tài)之間進(jìn)行各種排列組合,就組合成事件分發(fā)的多種狀態(tài)。接下來上一個(gè)很重要的圖,就是整體的事件分發(fā)流程圖:
上面這張流程圖很重要,今天這個(gè)解析就是圍繞著它轉(zhuǎn)了。下面就是分別把上面不同狀態(tài)進(jìn)行詳細(xì)解釋。
先做個(gè)說明,在按鈕點(diǎn)擊的時(shí)候,我們就關(guān)注三個(gè)事件,ACTION_DOWN/ACTION_MOVE/ACTION_UP。
首先是三個(gè)對(duì)象的三個(gè)方法都不做更改,也就是都調(diào)用super,這就是默認(rèn)狀態(tài)。這樣三個(gè)事件都會(huì)到按鈕的onTouchEvent,并且調(diào)用onClick回調(diào)方法。
接下來開始做點(diǎn)手腳,在Activity的dispatchTouchEvent中返回true狀態(tài),這樣Activity就消費(fèi)掉事件,不再往下傳給另外兩個(gè)對(duì)象,甚至也不調(diào)用自己的onTouchEvent方法。
Activity的dispatchTouchEvent中返回false,也是自己消費(fèi)點(diǎn),和上面返回true是一樣的。
接下來activity兩個(gè)方法保持默認(rèn),也就是super狀態(tài),這樣事件就能傳遞到viewgroup了。然后對(duì)viewgroup動(dòng)手腳,viewgroup有三個(gè)方法,所以狀態(tài)會(huì)多一點(diǎn)。首先在第一個(gè)方法dispatchTouchEvent返回true,這樣和acticity一樣的,自己直接消費(fèi)掉,也不給自己的onTouchEvent。
如果把狀態(tài)改成false呢?這種情況也就類似于員工反了不干了,只能領(lǐng)導(dǎo)自己干,事件就會(huì)給activity的onTouchEvent消費(fèi),再之后的move和up事件不會(huì)再分發(fā)了,activity直接給自己的onTouchEvent消費(fèi)。
接下來就是viewgroup的第二個(gè)方法onInterceptTouchEvent了。如果第一個(gè)方法默認(rèn)返回super狀態(tài),那么就會(huì)把事件給這個(gè)方法,viewgroup通過這個(gè)方法來告訴系統(tǒng)攔不攔截這個(gè)時(shí)間。返回true就是攔截,事件就會(huì)給自己的第三個(gè)方法onTouchEvent消費(fèi)。如果onTouchEvent返回super或者false,那么事件就會(huì)給父類activity消費(fèi)。之后事件不再傳給viewgroup,activity自己直接消費(fèi)。這就類似于老板交給員工任務(wù),員工沒完成好,老板以后就不交給這個(gè)員工了。
如果viewgroup的第二個(gè)方法返回false,表示自己不做攔截,那么事件就會(huì)傳遞給子類,這里就是button了。button就默認(rèn)給自己的onTouchEvent消費(fèi)掉。
如果第二個(gè)方法返回true表示攔截,事件就會(huì)給自己的onTouchEvent消費(fèi),onTouchEvent返回true,事件就是viewgroup自己消費(fèi),后續(xù)的事件也會(huì)給到viewgroup。
如果onTouchEvent返回false,事件就會(huì)給父類activity消費(fèi)。之后事件不再傳給viewgroup,activity自己直接消費(fèi)。
最后就是最后一個(gè)對(duì)象view,在這里是button。view只有兩個(gè)方法,沒有onInterceptTouchEvent。首先如果dispatchTouchEvent返回true,那么事件就直接消費(fèi)掉了,不傳遞給自己的onTouchEvent方法。
dispatchTouchEvent返回false就會(huì)把事件給父類的onTouchEvent消費(fèi)。以后事件不再交給這個(gè)view。
view的onTouchEvent方法如果返回true,那么事件就會(huì)自己消費(fèi)點(diǎn),并且不會(huì)調(diào)用onClick這個(gè)回調(diào)方法。
如果onTouchEvent返回false,那么事件就會(huì)交給父類,這個(gè)系列剩下的事件就不會(huì)再交給這個(gè)view了。
到這里事件分發(fā)就說的差不多了,我們這個(gè)Demo比較簡單,但是不影響理解原理。簡單坐下總結(jié):
1.對(duì)于dispatchTouchEvent這個(gè)方法,返回true都是直接消費(fèi)掉,不做其他傳遞。返回false就有點(diǎn)區(qū)別,對(duì)于activity是和true一樣直接消費(fèi)掉,對(duì)于viewgroup和view就是把事件給父類的onTouchEvent消費(fèi)。返回super就都是進(jìn)行分發(fā)
2.onInterceptTouchEvent這個(gè)方法只有viewgroup有,返回true就是攔截,會(huì)把事件給到自己的onTouchEvent消費(fèi);返回false和返回super是一樣的,不攔截,分發(fā)給子view
3.onTouchEvent返回true就是消費(fèi)掉事件了,如果返回false就傳遞給父類。返回super有點(diǎn)區(qū)別,對(duì)于viewgroup就和false一樣,傳遞給父類;對(duì)于view就會(huì)再接著往下傳遞,比如調(diào)用點(diǎn)擊回調(diào)等。
到這里就把事件分發(fā)說的差不多了,沒有放上源碼分析,我是覺得那樣內(nèi)容就有點(diǎn)多,容易亂,如果面試的時(shí)候畫出上面的流程圖就差不多了。
如果本文對(duì)你有幫助,請(qǐng)點(diǎn)個(gè)贊哈,謝謝!
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/68881.html
摘要:事件被上層攔截時(shí)觸發(fā)。事件返回時(shí)直接指向了父的這一部分是不合理的,實(shí)際上它僅僅是給了父的一個(gè)返回值,父根據(jù)返回值來調(diào)用自身的。是根據(jù)的返回值來確定是調(diào)用子的還是自身的,并沒有將調(diào)用交給。 原文鏈接 簡簡單單講清楚android事件分發(fā)。 什么叫事件分發(fā)機(jī)制 ? 事件分發(fā)是:當(dāng)發(fā)生了一個(gè)事件時(shí),在屏幕上找到一個(gè)合適的控件來處理這個(gè)事件的過程。 因?yàn)橐粋€(gè)界面上控件如此之多,發(fā)生一個(gè)事件后總...
摘要:下事件分發(fā)和消費(fèi)事件前言中與事件相關(guān)的方法包括能夠響應(yīng)的空間包括。事件分析事件分發(fā)事件發(fā)生時(shí)的方法會(huì)以隧道方式從根元素依次往下傳遞直到最內(nèi)層子元素或在中間某一元素中由于某一條件停止傳遞將事件傳遞給最外層的 Android下Touch事件分發(fā)和消費(fèi)事件 前言 Android中與touch事件相關(guān)的方法包括:dispatchTouchEvent(MotionEvent ev)、onInte...
閱讀 1579·2021-10-25 09:44
閱讀 2945·2021-09-04 16:48
閱讀 1581·2019-08-30 15:44
閱讀 2517·2019-08-30 15:44
閱讀 1746·2019-08-30 15:44
閱讀 2835·2019-08-30 14:14
閱讀 2984·2019-08-30 13:00
閱讀 2160·2019-08-30 11:09