觸摸事件的分發(fā) (Activity篇)

概述

一圖勝千言:

TouchEvent事件傳遞.png

Activity對(duì)觸摸事件的分發(fā)

  1. 我們首先來(lái)看一下Activity是如何分發(fā)觸摸事件的:
 public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            onUserInteraction();
        }
        if (getWindow().superDispatchTouchEvent(ev)) {//將事件傳遞給和該Activity組合的Window對(duì)象吮炕。
            return true;
        }
        return onTouchEvent(ev);
    }

可以看到,事件被傳遞給了和Activity對(duì)應(yīng)的Window對(duì)象。通過(guò)查看Window源碼我們知道姑廉,Window是一個(gè)虛擬類。Window的累注釋中明確說(shuō)明目前只有一個(gè)實(shí)現(xiàn)類叫做PhoneWindow。

  1. 我們來(lái)看一下PhoneWindow是如何傳遞觸摸事件的:
@Override
    public boolean superDispatchTouchEvent(MotionEvent event) {
        return mDecor.superDispatchTouchEvent(event);
    }

可以看到事件被傳遞給了Activity的DecorView热某。我們知道菩鲜,DecorView是Activity的頂級(jí)視圖园细。他是PhoneWindow的一個(gè)內(nèi)部類。

  1. DecorView對(duì)事件的傳遞接校。
private final class DecorView extends FrameLayout implements RootViewSurfaceTaker {

        public boolean superDispatchTouchEvent(MotionEvent event) {
            return super.dispatchTouchEvent(event);
        }
}

我們看到猛频,DecorView的superDispatchTouchEvent方法調(diào)用了父類的dispatchTouchEvent(event)方法。而DecorView是繼承自FrameLayout的蛛勉。FrameLayout繼承自ViewGroup并且沒(méi)有重寫dispatchTouchEvent(event)方法鹿寻。

至此,觸摸事件已經(jīng)從Activity傳遞到了和該Activity對(duì)應(yīng)的ViewTree的頂級(jí)ViewGroup中诽凌。
事件在ViewGroup中的分發(fā)過(guò)程毡熏,我們將在后續(xù)文章中詳細(xì)分析。這里重點(diǎn)需要了解:Activity在通過(guò)dispatchTouchEvent()傳遞觸摸事件的時(shí)候皿淋,會(huì)調(diào)用到ViewGroup的dispatchTouchEvent()招刹。從而實(shí)現(xiàn),將Activity中的觸摸事件傳遞給它所包含的View或ViewGroup窝趣。

Activity對(duì)觸摸事件的處理

回顧一下Activity的dispatchTouchEvent()方法的源碼:

    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            onUserInteraction();
        }
        if (getWindow().superDispatchTouchEvent(ev)) {//將事件傳遞給和該Activity組合的Window對(duì)象疯暑。
            return true;
        }
        // 如果superDispatchTouchEvent()返回false。
        // 即Activity的根視圖以及根視圖的子視圖都沒(méi)有處理該事件的話哑舒,則調(diào)用Activity的onTouchEvent()
        return onTouchEvent(ev);
    }

上面小節(jié)描述的情況是getWindow().superDispatchTouchEvent(ev)中一級(jí)一級(jí)向下傳遞的情況妇拯。那么如果getWindow().superDispatchTouchEvent(ev)調(diào)用完成返回false,即即Activity的根視圖以及根視圖的子視圖都沒(méi)有處理該事件的話洗鸵,則調(diào)用Activity的onTouchEvent()越锈,由Activity中的onTouchEvent做出最后的處理。
我們看一下Activity的onTouchEvent()的代碼:

    public boolean onTouchEvent(MotionEvent event) {
        if (mWindow.shouldCloseOnTouch(this, event)) {
            finish();
            return true;
        }
        
        return false;
    }

可以看到膘滨,Activity中默認(rèn)的onTouchEvent方法很簡(jiǎn)單:
只處理一種情況:當(dāng)mWindow.shouldCloseOnTouch(this, event)返回true時(shí)調(diào)用finish()方法結(jié)束Activity甘凭。其他情況一律不處理。那么mWindow.shouldCloseOnTouch(this, event)在哪種情況下返回true就顯得非常重要火邓。我們來(lái)看下Window類中shouldCloseOnTouch()方法的的源碼:

    public boolean shouldCloseOnTouch(Context context, MotionEvent event) {
      if (mCloseOnTouchOutside && event.getAction() == MotionEvent.ACTION_DOWN
              && isOutOfBounds(context, event) && peekDecorView() != null) {
          return true;
      }
      return false;
  }
  1. mCloseOnTouchOutside是一個(gè)boolean變量丹弱,它是由Window的android:windowCloseOnTouchOutside屬性值決定。
  2. isOutOfBounds(context, event)是判斷該event的坐標(biāo)是否在context(對(duì)于本文來(lái)說(shuō)就是當(dāng)前的Activity)之外铲咨。是的話躲胳,返回true;否則纤勒,返回false坯苹。
  3. peekDecorView()則是返回PhoneWindow的mDecor。
    也就是說(shuō)摇天,如果設(shè)置了android:windowCloseOnTouchOutside屬性為true粹湃,并且當(dāng)前事件是ACTION_DOWN恐仑,而且點(diǎn)擊發(fā)生在Activity之外,同時(shí)Activity還包含視圖的話再芋,則返回true菊霜;表示該點(diǎn)擊事件會(huì)導(dǎo)致Activity的結(jié)束。

比較典型的情況就是dialog形的Activity济赎。

下一篇我們將分析事件在ViewTree中的傳遞過(guò)程鉴逞。

參考文獻(xiàn)

http://wangkuiwu.github.io/2015/01/02/TouchEvent-Activity/
http://blog.csdn.net/yanbober/article/details/45932123
http://blog.csdn.net/ns_code/article/details/49848801

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市司训,隨后出現(xiàn)的幾起案子构捡,更是在濱河造成了極大的恐慌,老刑警劉巖壳猜,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件勾徽,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡统扳,警方通過(guò)查閱死者的電腦和手機(jī)喘帚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)咒钟,“玉大人吹由,你說(shuō)我怎么就攤上這事≈熳欤” “怎么了倾鲫?”我有些...
    開(kāi)封第一講書人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)萍嬉。 經(jīng)常有香客問(wèn)我乌昔,道長(zhǎng),這世上最難降的妖魔是什么壤追? 我笑而不...
    開(kāi)封第一講書人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任磕道,我火速辦了婚禮,結(jié)果婚禮上行冰,老公的妹妹穿的比我還像新娘捅厂。我一直安慰自己,他們只是感情好资柔,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著撵割,像睡著了一般贿堰。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上啡彬,一...
    開(kāi)封第一講書人閱讀 49,741評(píng)論 1 289
  • 那天羹与,我揣著相機(jī)與錄音故硅,去河邊找鬼。 笑死纵搁,一個(gè)胖子當(dāng)著我的面吹牛吃衅,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播腾誉,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼徘层,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了利职?” 一聲冷哼從身側(cè)響起趣效,我...
    開(kāi)封第一講書人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎猪贪,沒(méi)想到半個(gè)月后跷敬,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡热押,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年西傀,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片桶癣。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡拥褂,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出鬼廓,到底是詐尸還是另有隱情肿仑,我是刑警寧澤,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布碎税,位于F島的核電站尤慰,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏雷蹂。R本人自食惡果不足惜伟端,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望匪煌。 院中可真熱鬧责蝠,春花似錦、人聲如沸萎庭。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)驳规。三九已至肴敛,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背医男。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工砸狞, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人镀梭。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓刀森,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親报账。 傳聞我的和親對(duì)象是個(gè)殘疾皇子研底,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348

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