Android 觸摸事件傳遞機(jī)制

Android 觸摸事件傳遞機(jī)制

1 觸摸事件的類型

  • ACTION_DOWN : 用戶手指按下操作,一般標(biāo)志著觸摸事件的開始.
  • ACTION_MOVE : 用戶按下后移動手指.
  • ACTION_UP : 用戶手指離開屏幕.觸摸事件的結(jié)束.

一次屏幕的觸摸操作中,ACTION_UP 和 ACTION_DOWN 是必須有的.ACTION_MOVE視情況而定.

2. 事件傳遞的三個階段

  • 事件分發(fā)(dispatch) : 事件的分發(fā)對應(yīng)著dispatchTouchEvent方法,在Android系統(tǒng)中所有的事件都是通過這個方法進(jìn)行分發(fā)的.

    函數(shù)原型 :

    // 事件分發(fā)方法
    public boolean dispatchTouchEvent(MotionEvent ev);
    
    • 返回值 truefalse : 當(dāng)前視圖將事件消耗,不再繼續(xù)分發(fā)給子視圖.
    • 返回值 super.dispatchTouchEvent(ev) : 繼續(xù)分發(fā)事件.
  • 事件攔截(Intercept) : 事件的攔截對應(yīng)著onInterceptTouchEvent 方法.這個方法
    只有在ViewGroup及其子類中才存在,View和Activity中不存在.

    函數(shù)原型 :

    // 事件攔截
    public boolean onInterceptTouchEvent(MotionEvent ev);
    
    • 返回值 true : 攔截此事件,不再繼續(xù)分發(fā).同時交給自身的onTouchEvent方法進(jìn)行消費.
    • 返回值 falsesuper.onInterceptTouchEvent : 不攔截事件,繼續(xù)傳遞給子視圖.
  • 事件消費(Consume) : 事件消費對應(yīng)著 onTouchEvent 方法.

    函數(shù)原型 :

    // 消費函數(shù)
    public void onTouchEvent(MotionEvent ev);
    
    • 返回值 true : 當(dāng)前視圖可以處理當(dāng)前事件,事件將不會向上傳遞給父視圖.
    • 返回值 false : 當(dāng)前視圖處理不了該事件,事件會被傳遞給父視圖的onTouchEvent方法進(jìn)行處理.

3. Android擁有事件傳遞處理能力的類

  • Activity : 擁有 dispatchTouchEventonTouchEvent 方法.
  • ViewGroup : dispatchTouchEvent涮俄、onInterceptTouchEventonTouchEvent
  • View : : dispatchTouchEvent归苍、onTouchEvent

4. View 的事件傳遞機(jī)制

參考代碼 : app , 下面對程序及結(jié)果進(jìn)行分析.

  • 不進(jìn)行人為干預(yù). 不設(shè)置listener情況.

    • dispatchTouchEventonTouchEvent 返回父類的同名方法.
    • onTouch 返回 false

    運(yùn)行結(jié)果 :

    MainActivity: dispatchTouchEvent : DOWN
    MyTextView: dispatchTouchEvent : DOWN
    MyTextView: onTouchEvent : DOWN
    MainActivity: onTouchEvent : DOWN
    MainActivity: dispatchTouchEvent : UP
    MainActivity: onTouchEvent : UP
    

    從LOG中可以看出事件傳遞方式如下 :

    • dispatchTouchEvent 方法從外層向內(nèi)層傳遞.
    • onTouchEvent 從內(nèi)層向外層傳遞.
    • 如果某一層處理了事,那么當(dāng)前事件序列的其他事件不會向下傳遞.對于當(dāng)前情況下由于MainActivity
      處理 ACTION_DOWN事件 所以該事件序列中的 ACTION_UP 事件也就到MainActivity就不
      再下發(fā)給子視圖了.
  • 不進(jìn)行人為干預(yù),設(shè)置listener情況.

    onTouch返回false 運(yùn)行結(jié)果 :

    MainActivity: dispatchTouchEvent : DOWN
    MyTextView: dispatchTouchEvent : DOWN
    MainActivity: onTouch : DOWN
    MyTextView: onTouchEvent : DOWN
    
    MainActivity: dispatchTouchEvent : UP
    MyTextView: dispatchTouchEvent : UP
    MainActivity: onTouch : UP
    MyTextView: onTouchEvent : UP
    
    MainActivity: MyTextView OnClick
    

    onTouch返回true 運(yùn)行結(jié)果 :

    // onTouch 返回true : the listener consume the event
    MainActivity: dispatchTouchEvent : DOWN
    MyTextView: dispatchTouchEvent : DOWN
    MainActivity: onTouch : DOWN
    
    MainActivity: dispatchTouchEvent : UP
    MyTextView: dispatchTouchEvent : UP
    MainActivity: onTouch : UP
    

    LOG 信息顯示事件是 MyTextView 視圖處理的.

    • 事件處理的流程
      • 如果設(shè)置了listener則首先調(diào)用 listener 的 onTouch 方法.
        • 返回值 true : 表示listener處理該事件. onTouchEventonClick 不會被調(diào)用.
        • 返回值 false : 表示listener不處理該事件. onTouchEventOnClick 不會被調(diào)用.
      • onTouchEvent 如果onTouch 方法返回true
      • onClick 如果 onTouch 方法返回 true
  • dispatchTouchEvent 返回 falsetrue

    在兩種情況下當(dāng)前視圖都會消耗該事件,該事件不會繼續(xù)分發(fā)給子視圖.
    同時不會調(diào)用onTouchEvent,onClick 等方法
    MainActivity 運(yùn)行結(jié)果 :

    MainActivity: dispatchTouchEvent : DOWN
    MainActivity: dispatchTouchEvent : UP
    

    MyTextView 運(yùn)行結(jié)果

    MainActivity: dispatchTouchEvent : DOWN
    MyTextView: dispatchTouchEvent : DOWN
    MainActivity: dispatchTouchEvent : UP
    MyTextView: dispatchTouchEvent : UP
    
  • onTouchEvent 方法返回 true

    當(dāng)前視圖消耗該事件,該事件處理不會向上傳遞. OnClick 方法不被調(diào)用

    MyTextView 運(yùn)行結(jié)果

    MainActivity: dispatchTouchEvent : DOWN
    MyTextView: dispatchTouchEvent : DOWN
    MainActivity: onTouch : DOWN
    MyTextView: onTouchEvent : DOWN
    
    MainActivity: dispatchTouchEvent : UP
    MyTextView: dispatchTouchEvent : UP
    MainActivity: onTouch : UP
    MyTextView: onTouchEvent : UP
    
  • onTouchEvent 方法返回 false

    當(dāng)前視圖不處理該事件,事件將會被傳遞給上層控件處理.并且 onClick 不會被調(diào)用.

    MyTextView 運(yùn)行結(jié)果

    MainActivity: dispatchTouchEvent : DOWN
    MyTextView: dispatchTouchEvent : DOWN
    MainActivity: onTouch : DOWN
    MyTextView: onTouchEvent : DOWN
    MainActivity: onTouchEvent : DOWN
    
    MainActivity: dispatchTouchEvent : UP
    MainActivity: onTouchEvent : UP
    
  • onTouchEvent 返回 super.onTouchEvent(ev)

    MyTextView 運(yùn)行結(jié)果 :

    MainActivity: dispatchTouchEvent : DOWN
    MyTextView: dispatchTouchEvent : DOWN
    MainActivity: onTouch : DOWN
    MyTextView: onTouchEvent : DOWN
    
    MainActivity: dispatchTouchEvent : UP
    MyTextView: dispatchTouchEvent : UP
    MainActivity: onTouch : UP
    MyTextView: onTouchEvent : UP
    
    MainActivity: MyTextView OnClick
    
    

5. ViewGroup 事件傳遞

  • onIntercepTouchEvent 返回 falsesuper.onIntercepTouchEvent

    在這種情況下,事件會繼續(xù)分發(fā).

    MyRelativeLayout 運(yùn)行結(jié)果 :

    MainActivity: dispatchTouchEvent : DOWN
    MyRelativeLayout: dispatchTouchEvent : DOWN
    MyRelativeLayout: onInterceptTouchEvent : DOWN
    MyTextView: dispatchTouchEvent : DOWN
    MainActivity: onTouch : DOWN
    MyTextView: onTouchEvent : DOWN
    MainActivity: dispatchTouchEvent : UP
    MyRelativeLayout: dispatchTouchEvent : UP
    MyRelativeLayout: onInterceptTouchEvent : UP
    MyTextView: dispatchTouchEvent : UP
    MainActivity: onTouch : UP
    MyTextView: onTouchEvent : UP
    MainActivity: MyTextView OnClick
    
  • onInterceptTouchEvent 返回 true

    在這種情況下,此視圖會攔截事件,并交給自身的 onTouchEvent 處理.
    MyRelativeLayout 運(yùn)行結(jié)果 :

    // 事件最終是Activity處理的.
    MainActivity: dispatchTouchEvent : DOWN
    MyRelativeLayout: dispatchTouchEvent : DOWN
    MyRelativeLayout: onInterceptTouchEvent : DOWN
    MyRelativeLayout: onTouchEvent : DOWN
    MainActivity: onTouchEvent : DOWN
    MainActivity: dispatchTouchEvent : UP
    MainActivity: onTouchEvent : UP
    

代碼地址 : https://github.com/RichardFrankios/AndroidAdvanced

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市镜粤,隨后出現(xiàn)的幾起案子幢踏,更是在濱河造成了極大的恐慌髓需,老刑警劉巖,帶你破解...
    沈念sama閱讀 223,126評論 6 520
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件房蝉,死亡現(xiàn)場離奇詭異僚匆,居然都是意外死亡微渠,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,421評論 3 400
  • 文/潘曉璐 我一進(jìn)店門咧擂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來逞盆,“玉大人,你說我怎么就攤上這事松申≡坡” “怎么了?”我有些...
    開封第一講書人閱讀 169,941評論 0 366
  • 文/不壞的土叔 我叫張陵贸桶,是天一觀的道長焕数。 經(jīng)常有香客問我,道長刨啸,這世上最難降的妖魔是什么堡赔? 我笑而不...
    開封第一講書人閱讀 60,294評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮设联,結(jié)果婚禮上善已,老公的妹妹穿的比我還像新娘。我一直安慰自己离例,他們只是感情好换团,可當(dāng)我...
    茶點故事閱讀 69,295評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著宫蛆,像睡著了一般艘包。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上耀盗,一...
    開封第一講書人閱讀 52,874評論 1 314
  • 那天想虎,我揣著相機(jī)與錄音,去河邊找鬼叛拷。 笑死舌厨,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的忿薇。 我是一名探鬼主播裙椭,決...
    沈念sama閱讀 41,285評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼署浩!你這毒婦竟也來了揉燃?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,249評論 0 277
  • 序言:老撾萬榮一對情侶失蹤筋栋,失蹤者是張志新(化名)和其女友劉穎炊汤,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,760評論 1 321
  • 正文 獨居荒郊野嶺守林人離奇死亡婿崭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,840評論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了肴颊。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片氓栈。...
    茶點故事閱讀 40,973評論 1 354
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖婿着,靈堂內(nèi)的尸體忽然破棺而出授瘦,到底是詐尸還是另有隱情,我是刑警寧澤竟宋,帶...
    沈念sama閱讀 36,631評論 5 351
  • 正文 年R本政府宣布提完,位于F島的核電站,受9級特大地震影響丘侠,放射性物質(zhì)發(fā)生泄漏徒欣。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,315評論 3 336
  • 文/蒙蒙 一蜗字、第九天 我趴在偏房一處隱蔽的房頂上張望打肝。 院中可真熱鬧,春花似錦挪捕、人聲如沸粗梭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,797評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽断医。三九已至,卻和暖如春奏纪,著一層夾襖步出監(jiān)牢的瞬間鉴嗤,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,926評論 1 275
  • 我被黑心中介騙來泰國打工序调, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留躬窜,地道東北人。 一個月前我還...
    沈念sama閱讀 49,431評論 3 379
  • 正文 我出身青樓炕置,卻偏偏與公主長得像荣挨,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子朴摊,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,982評論 2 361

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