Android事件傳遞機(jī)制之ViewGroup

ViewGroup事件傳遞

上篇筆記中介紹道埋心,ViewGroup中參與事件傳遞的方法有以下三個(gè):

public boolean dispatchTouchEvent(MotionEvent event)
public boolean onTouchEvent(MotionEvent event)
public boolean onInterceptTouchEvent(MotionEvent ev)

ViewGroup事件傳遞方法調(diào)用

dispatchTouchEvent

當(dāng)我們點(diǎn)擊控件時(shí)广凸,首先調(diào)用的是布局組件(ViewGroup)的dispatchTouchEvent方法。這個(gè)方法和View中的不太一樣,它需要去確定用戶(hù)到底點(diǎn)擊的是哪個(gè)子View载慈,并將事件分發(fā)給他毅桃。然后調(diào)用這個(gè)子View的dispatchTouchEvent,最后按照上篇筆記中記錄的流程翁狐,執(zhí)行事件的分發(fā)类溢。ViewGroup.dispatchTouchEvent()部分源代碼如下:

final boolean intercepted;
if (actionMasked == MotionEvent.ACTION_DOWN
                 || mFirstTouchTarget != null) {
    final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
    if (!disallowIntercept) {
        intercepted = onInterceptTouchEvent(ev);
        ev.setAction(action); // restore action in case it was changed
    } else {
        intercepted = false;
    }
} else {
    // There are no touch targets and this action is not an initial down
    // so this view group continues to intercept touches.
    intercepted = true;
}

上述代碼中,有個(gè)比較重要的局部變量:intercepted谴蔑。這個(gè)變量決定了ViewGroup是否將事件分發(fā)給子View豌骏。而在代碼中我們可以看到,這個(gè)變量的值就是onInterceptTouchEvent()方法的返回值隐锭。接下來(lái)我們看onInterceptTouchEvent()方法.

onInterceptTouchEvent

onInterceptTouchEvent源代碼:

Public boolean onInterceptTouchEvent(MotionEvent ev) {
        return false;
}

這個(gè)方法的代碼及其簡(jiǎn)單窃躲。當(dāng)該方法返回true時(shí),即事件交給ViewGroup自身來(lái)消費(fèi)钦睡,后續(xù)調(diào)用ViewGroup的onTouch和onTouchEvent方法蒂窒;當(dāng)返回false時(shí),事件將分發(fā)給子View來(lái)觸發(fā)。
當(dāng)事件交由子View來(lái)觸發(fā)時(shí)洒琢,那么ViewGroup.diapatchTouchEvent方法的返回值完全有子View的diapatchTouchEvent返回值決定秧秉。如果子View是可點(diǎn)擊的,那么ViewGroup的diapatchTouchEvent返回true衰抑,也就是代表事件已經(jīng)被子View消費(fèi)掉了象迎,即不會(huì)執(zhí)行ViewGroup的onTouch和onTouchEvent方法。如果子View沒(méi)有消費(fèi)事件呛踊,那么會(huì)調(diào)用ViewGroup的父類(lèi)的diapatchTouchEvent方法砾淌,進(jìn)行事件分發(fā),交由onTouch和onTouchEvent觸發(fā)谭网。當(dāng)我們點(diǎn)擊ViewGroup的空白區(qū)域汪厨,同樣會(huì)調(diào)用父類(lèi)的diapatchTouchEvent進(jìn)行事件分發(fā)。

實(shí)踐

  1. 當(dāng)事件正常從ViewGroup分發(fā)到對(duì)應(yīng)的子View愉择,log打印如下:
事件傳遞ViewGroup-->View.png

2.當(dāng)事件在ViewGroup中被攔截劫乱,onInterceptTouchEvent方法返回true,Log打印如下:

事件在ViewGroup中被攔截.png

3.當(dāng)點(diǎn)擊了ViewGroup中不可點(diǎn)擊的子View锥涕,Log打印如下:

Button屬性enable設(shè)置為false.png

Button要設(shè)置成不可點(diǎn)擊狀態(tài)衷戈,只能通過(guò)將Button控件的enable屬性設(shè)置為false。

事件攔截

事件傳遞方法返回值都是boolean型站楚,true代表事件已經(jīng)被消費(fèi)脱惰,false代表事件沒(méi)有被消費(fèi),可以分發(fā)窿春。

onTouch方法返回true

onTouch方法默認(rèn)返回值都是false拉一,當(dāng)我們使其返回true,將事件攔截在了touch事件旧乞。也就是說(shuō)在dispatchTouchEvent方法中不會(huì)調(diào)用onTouchEvent方法(觸發(fā)點(diǎn)擊事件在該方法中)蔚润。

onInterceptTouchEvent方法返回true

onInterceptTouchEvent方法默認(rèn)返回是false,當(dāng)我們將其返回值設(shè)定為true時(shí)尺栖,也就是讓事件不能分發(fā)給ViewGroup的子View嫡纠。讓ViewGroup自身來(lái)消費(fèi)事件。

Activity觸摸事件傳遞

其實(shí)延赌,當(dāng)我們觸摸屏幕時(shí)除盏,事件傳遞的順序應(yīng)該是activity->viewgroup->view。和VIewGroup挫以,View相同者蠕,Activity也有dispatchTouchEvent和onTouchEvent方法。觸摸事件最先調(diào)用的是Activity的dispatchTouchEvent方法,代碼如下:

public boolean dispatchTouchEvent(MotionEvent ev) {
    if (ev.getAction() == MotionEvent.ACTION_DOWN) {
        onUserInteraction();
    }
    if (getWindow().superDispatchTouchEvent(ev)) {
        return true;
    }
    return onTouchEvent(ev);
}

首先判斷當(dāng)前事件是否是ACTION_DOWN掐松,如果是調(diào)用onUserInteraction()方法踱侣。該方法可以在Activity中被重寫(xiě)粪小,在事件被分發(fā)前會(huì)調(diào)用該方法。該方法的返回值是void型抡句,不會(huì)對(duì)事件傳遞結(jié)果造成影響探膊。接著會(huì)判斷getWindow().superDispatchTouchEvent(ev)的執(zhí)行結(jié)果。這一步首先通過(guò)getWindow()方法得到Activity被加載時(shí)待榔,創(chuàng)建的PhoneWindow對(duì)象逞壁,然后調(diào)用PhoneWindow對(duì)象中的DecorView成員變量的dispatchTouchEvent方法對(duì)事件進(jìn)行分發(fā)。如果事件沒(méi)有被DecorView及其子View消費(fèi)究抓,那么調(diào)用Activity的onTouchEvent()方法消費(fèi)事件猾担。

參考

文獻(xiàn)1文獻(xiàn)2刺下、文獻(xiàn)3文獻(xiàn)4

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末稽荧,一起剝皮案震驚了整個(gè)濱河市橘茉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌姨丈,老刑警劉巖畅卓,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異蟋恬,居然都是意外死亡翁潘,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)歼争,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)拜马,“玉大人,你說(shuō)我怎么就攤上這事沐绒×┟В” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵乔遮,是天一觀的道長(zhǎng)扮超。 經(jīng)常有香客問(wèn)我,道長(zhǎng)蹋肮,這世上最難降的妖魔是什么出刷? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮坯辩,結(jié)果婚禮上馁龟,老公的妹妹穿的比我還像新娘。我一直安慰自己濒翻,他們只是感情好屁柏,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布啦膜。 她就那樣靜靜地躺著,像睡著了一般淌喻。 火紅的嫁衣襯著肌膚如雪僧家。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,144評(píng)論 1 285
  • 那天裸删,我揣著相機(jī)與錄音八拱,去河邊找鬼。 笑死涯塔,一個(gè)胖子當(dāng)著我的面吹牛肌稻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播匕荸,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼爹谭,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了榛搔?” 一聲冷哼從身側(cè)響起诺凡,我...
    開(kāi)封第一講書(shū)人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎践惑,沒(méi)想到半個(gè)月后腹泌,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡尔觉,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年凉袱,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片侦铜。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡专甩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出泵额,到底是詐尸還是另有隱情配深,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布嫁盲,位于F島的核電站篓叶,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏羞秤。R本人自食惡果不足惜缸托,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望瘾蛋。 院中可真熱鬧俐镐,春花似錦、人聲如沸哺哼。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至棍苹,卻和暖如春无宿,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背枢里。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工孽鸡, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人栏豺。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓彬碱,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親奥洼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子巷疼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

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