Android 事件分發(fā)機(jī)制

Start

前言

轉(zhuǎn)載

1. Android 事件分發(fā)流

圖1

??:圖分為三層藻茂,從上到下依次是 Activity、ViewGroup、View

  • 事件從左上角那個(gè)白色箭頭開始骗灶,由 Activity 的 dispatchTouchEvent 做分發(fā)

  • 箭頭的上面字代表方法返回值(return false、return true啥么、return super.xxxx()),super 的意思是調(diào)用父類實(shí)現(xiàn)驻啤。

  • dispatchTouchEvent 和 onTouchEvent的框里有個(gè)【true---->消費(fèi)】的字,表示的意思是如果方法返回true道批,那么代表事件就此消費(fèi)错英,不會(huì)繼續(xù)往別的地方傳了,事件終止隆豹。

  • 目前所有的圖說明的事件是針對(duì) ACTION_DOWN 的椭岩,對(duì)于 ACTION_MOVEACTION_UP ,當(dāng)dispatchTouchEvent在進(jìn)行事件分發(fā)的時(shí)候璃赡,只有前一個(gè)事件(如ACTION_DOWN)返回true判哥,才會(huì)收到ACTION_MOVE和ACTION_UP的事件。

仔細(xì)看整個(gè)圖碉考,我們得出事件流 走向的幾個(gè)結(jié)論:

  1. 如果事件不被中斷塌计,整個(gè)事件流向是一個(gè)類U型圖,我們來看下這張圖侯谁,可能更能理解U型圖的意思锌仅。
圖2

所以如果我們沒有對(duì)控件里面的方法進(jìn)行重寫或更改返回值,而直接用 super 調(diào)用父類的默認(rèn)實(shí)現(xiàn)墙贱,那么整個(gè)事件流向應(yīng)該是從Activity---->ViewGroup--->View 從上往下調(diào)用 dispatchTouchEvent 方法技扼,一直到葉子節(jié)點(diǎn)(View)的時(shí)候,再由 View--->ViewGroup--->Activity 從下往上調(diào)用 onTouchEvent 方法嫩痰。

  1. dispatchTouchEvent 和 onTouchEvent 一旦return true剿吻,事件就停止傳遞了(到達(dá)終點(diǎn))〈模看下圖中只要 return true 事件就沒再繼續(xù)傳下去了丽旅,對(duì)于 return true 我們經(jīng)常說事件被消費(fèi)了椰棘,消費(fèi)了的意思就是事件走到這里就是終點(diǎn),不會(huì)往下傳榄笙,沒有誰能再收到這個(gè)事件了邪狞。
圖3
  1. dispatchTouchEvent 和 onTouchEvent return false 的時(shí)候事件都回傳給父控件的 onTouchEvent 處理。
圖4

看上圖深藍(lán)色的線茅撞,對(duì)于返回 false 的情況帆卓,事件都是傳給父控件 onTouchEvent 處理。

??:對(duì)于 dispatchTouchEvent 返回 false 的含義應(yīng)該是:事件停止往子 View 傳遞和分發(fā)同時(shí)開始往父控件回溯(父控件的 onTouchEvent 開始從下往上回傳直到某個(gè) onTouchEvent return true)米丘,事件分發(fā)機(jī)制就像遞歸剑令,return false 的意義就是遞歸停止然后開始回溯。

對(duì)于 onTouchEvent return false 就比較簡(jiǎn)單了拄查,它就是不消費(fèi)事件吁津,并讓事件繼續(xù)往父控件的方向從下往上流動(dòng)。

  1. dispatchTouchEvent堕扶、onTouchEvent碍脏、onInterceptTouchEvent

ViewGroup 和 View 的這些方法的默認(rèn)實(shí)現(xiàn)就是會(huì)讓整個(gè)事件安裝 U 型完整走完,所以 return super.xxxxxx() 就會(huì)讓事件依照U型的方向的完整走完整個(gè)事件流動(dòng)路徑)稍算,中間不做任何改動(dòng)典尾,不回溯、不終止糊探,每個(gè)環(huán)節(jié)都走到急黎。

圖 5

所以如果看到方法 return super.xxxxx() 那么事件的下一個(gè)流向就是走 U 型下一個(gè)目標(biāo),稍微記住上面這張圖侧到,你就能很快判斷出下一個(gè)走向是哪個(gè)控件的哪個(gè)函數(shù)。

  1. onInterceptTouchEvent 的作用
圖 6

Intercept 的意思就攔截淤击,每個(gè) ViewGroup 每次在做分發(fā)的時(shí)候匠抗,問一問攔截器要不要攔截(也就是問問自己這個(gè)事件要不要自己來處理)如果要自己處理那就在 onInterceptTouchEvent 方法中 return true 就會(huì)交給自己的 onTouchEvent 的處理,如果不攔截就是繼續(xù)往子控件往下傳污抬。默認(rèn)是不會(huì)去攔截的汞贸,因?yàn)樽?View 也需要這個(gè)事件,所以 onInterceptTouchEvent 攔截器 return super.onInterceptTouchEvent() 和 return false 是一樣的印机,是不會(huì)攔截的矢腻,事件會(huì)繼續(xù)往子 View 的 dispatchTouchEvent 傳遞。

  1. ViewGroup 和 View 的 dispatchTouchEvent 方法返回 super.dispatchTouchEvent() 的時(shí)候事件流走向射赛。
圖 7

首先看下 ViewGroup 的 dispatchTouchEvent多柑,之前說的 return true 是終結(jié)傳遞。return false 是回溯到父 View 的 onTouchEvent楣责,然后 ViewGroup 怎樣通過 dispatchTouchEvent 方法能把事件分發(fā)到自己的onTouchEvent處理呢竣灌?

return true 和 false 都不行聂沙,那么只能通過 Interceptor 把事件攔截下來給自己的 onTouchEvent,所以 ViewGroup dispatchTouchEvent 方法的 super 默認(rèn)實(shí)現(xiàn)就是去調(diào)用 onInterceptTouchEvent初嘹,記住這一點(diǎn)及汉。

那么對(duì)于 View 的 dispatchTouchEvent return super.dispatchTouchEvent() 的時(shí)候呢事件會(huì)傳到哪里呢?

很遺憾 View 沒有攔截器屯烦。但是同樣的道理 return true 是終結(jié)坷随。return false 是回溯會(huì)父類的 onTouchEvent,怎樣把事件分發(fā)給自己的 onTouchEvent 處理呢驻龟,那只能return super.dispatchTouchEvent温眉,View 類的 dispatchTouchEvent() 方法默認(rèn)實(shí)現(xiàn)就是能幫你調(diào)用 View 自己的 onTouchEvent 方法的。

說了這么多迅脐,不知道有說清楚沒有芍殖,我這邊最后總結(jié)一下:

  • 對(duì)于 dispatchTouchEvent,onTouchEvent谴蔑,return true 是終結(jié)事件傳遞豌骏。return false 是回溯到父 View 的 onTouchEvent 方法。

  • ViewGroup 想把自己分發(fā)給自己的 onTouchEvent隐锭,需要攔截器 onInterceptTouchEvent 方法 return true 把事件攔截下來窃躲。

  • ViewGroup 的攔截器 onInterceptTouchEvent 默認(rèn)是不攔截的,所以 return super.onInterceptTouchEvent() = return false钦睡;

  • View 沒有攔截器蒂窒,為了讓 View 可以把事件分發(fā)給自己的 onTouchEvent,View的dispatchTouchEvent 默認(rèn)實(shí)現(xiàn)(super)就是把事件分發(fā)給自己的 onTouchEvent荞怒。

ViewGroup 和 View 的 dispatchTouchEvent 是做事件分發(fā)洒琢,那么這個(gè)事件可能分發(fā)出去的四個(gè)目標(biāo):

  1. 自己消費(fèi),終結(jié)傳遞褐桌。------->return true 衰抑;
  2. 給自己的 onTouchEvent 處理-------> 調(diào)用 super.dispatchTouchEvent() 系統(tǒng)默認(rèn)會(huì)去調(diào)用 onInterceptTouchEvent,在 onInterceptTouchEvent return true 就會(huì)去把事件分給自己的 onTouchEvent 處理荧嵌。
  3. 傳給子 View------> 調(diào)用 super.dispatchTouchEvent() 默認(rèn)實(shí)現(xiàn)會(huì)去調(diào)用 onInterceptTouchEvent 在 onInterceptTouchEvent return false呛踊,就會(huì)把事件傳給子類。
  4. 不傳給子 View啦撮,事件終止往下傳遞谭网,事件開始回溯,從父 View 的 onTouchEvent 開始事件從下到上回歸執(zhí)行每個(gè)控件的 onTouchEvent------->return false赃春;

?? 注: 由于 View 沒有子 View 所以不需要 onInterceptTouchEvent 來控件是否把事件傳遞給子 View 還是攔截愉择,所以 View 的事件分發(fā)調(diào)用 super.dispatchTouchEvent() 的時(shí)候默認(rèn)把事件傳給自己的 onTouchEvent 處理(相當(dāng)于攔截),對(duì)比 ViewGroup 的 dispatchTouchEvent 事件分發(fā),View 的事件分發(fā)沒有上面提到的 4 個(gè)目標(biāo)的第 3 點(diǎn)薄辅。

申明:開始的圖片來源網(wǎng)絡(luò)要拂,侵刪

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市站楚,隨后出現(xiàn)的幾起案子脱惰,更是在濱河造成了極大的恐慌,老刑警劉巖窿春,帶你破解...
    沈念sama閱讀 216,651評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拉一,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡旧乞,警方通過查閱死者的電腦和手機(jī)蔚润,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來尺栖,“玉大人嫡纠,你說我怎么就攤上這事⊙佣模” “怎么了除盏?”我有些...
    開封第一講書人閱讀 162,931評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)挫以。 經(jīng)常有香客問我者蠕,道長(zhǎng),這世上最難降的妖魔是什么掐松? 我笑而不...
    開封第一講書人閱讀 58,218評(píng)論 1 292
  • 正文 為了忘掉前任踱侣,我火速辦了婚禮,結(jié)果婚禮上大磺,老公的妹妹穿的比我還像新娘抡句。我一直安慰自己,他們只是感情好杠愧,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,234評(píng)論 6 388
  • 文/花漫 我一把揭開白布待榔。 她就那樣靜靜地躺著,像睡著了一般殴蹄。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上猾担,一...
    開封第一講書人閱讀 51,198評(píng)論 1 299
  • 那天袭灯,我揣著相機(jī)與錄音,去河邊找鬼绑嘹。 笑死稽荧,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的工腋。 我是一名探鬼主播姨丈,決...
    沈念sama閱讀 40,084評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼畅卓,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了蟋恬?” 一聲冷哼從身側(cè)響起翁潘,我...
    開封第一講書人閱讀 38,926評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎歼争,沒想到半個(gè)月后拜马,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,341評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡沐绒,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,563評(píng)論 2 333
  • 正文 我和宋清朗相戀三年俩莽,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片乔遮。...
    茶點(diǎn)故事閱讀 39,731評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡扮超,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蹋肮,到底是詐尸還是另有隱情出刷,我是刑警寧澤,帶...
    沈念sama閱讀 35,430評(píng)論 5 343
  • 正文 年R本政府宣布括尸,位于F島的核電站巷蚪,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏濒翻。R本人自食惡果不足惜屁柏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,036評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望有送。 院中可真熱鬧淌喻,春花似錦、人聲如沸雀摘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)阵赠。三九已至涯塔,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間清蚀,已是汗流浹背匕荸。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留枷邪,地道東北人榛搔。 一個(gè)月前我還...
    沈念sama閱讀 47,743評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親践惑。 傳聞我的和親對(duì)象是個(gè)殘疾皇子腹泌,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,629評(píng)論 2 354