dispatchTouchEvent事件分發(fā)淺析(四)Intercept攔截

上一篇殉簸,我們大體理解了分發(fā)的過程睬捶,并且簡單做了點(diǎn)擊髓堪,分析了執(zhí)行順序
這篇我們來看下 Intercept攔截

具體代碼可以見https://github.com/2954722256/demo_event

在看之前竞思, 我們先看一下 API

相關(guān)組件可以O(shè)verride的方法

Paste_Image.png

前言

前面用到了 dispatchTouchEvent 和 onTouchEvent
分別表示 分發(fā)事件 和 觸摸消費(fèi)的事件
我們可以發(fā)現(xiàn)踩娘, Activity 和 View都只有這2個(gè)方法
在ViewGroup除了這2個(gè)方法以外刮刑, 還有一個(gè) onInterceptTouchEvent 方法,
如果return true,表示攔截雷绢, 不向下傳遞了

我們看一下ViewGroup中
onInterceptTouchEvent 方法的實(shí)現(xiàn)

Paste_Image.png
public boolean onInterceptTouchEvent(MotionEvent ev) {
    return false;
}

簡單總結(jié)
我們可以發(fā)現(xiàn)這里泛烙,
默認(rèn)是return false, 不攔截
也就是說如果是直接extends ViewGroup翘紊,
return super.onInterceptTouchEvent(ev)
就是 return false
表示 不攔截


代碼

TouchEventFather:

package com.aohuan.test.dodoevent.view;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;

import com.aohuan.test.dodoevent.tools.TouchEventUtil;


public class TouchEventFather extends LinearLayout {

    private final Context mContext;

    public TouchEventFather(Context context) {
        super(context);
        this.mContext = context;
    }

    public TouchEventFather(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.mContext = context;
//      this.setOnClickListener(new OnClickListener() {
//          @Override
//          public void onClick(View v) {
//              TouchEventUtil.doClick(TouchEventFather.class);
//          }
//      });
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        TouchEventUtil.logActionMsg(getClass(),"dispatchTouchEvent",ev);
        return super.dispatchTouchEvent(ev);
//      return false;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        TouchEventUtil.logActionMsg(getClass(),"onInterceptTouchEvent",ev);
        return super.onInterceptTouchEvent(ev);
//      return true;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        TouchEventUtil.logActionMsg(getClass(),"onTouchEvent",ev);
        return super.onTouchEvent(ev);
    }


}

TouchEventChilds:

package com.aohuan.test.dodoevent.view;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;

import com.aohuan.test.dodoevent.tools.TouchEventUtil;


public class TouchEventChilds extends LinearLayout {

    private final Context mContext;

    public TouchEventChilds(Context context) {
        super(context);
        this.mContext = context;
    }

    public TouchEventChilds(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.mContext = context;
//      this.setClickable(false);
//      this.setOnClickListener(new OnClickListener() {
//          @Override
//          public void onClick(View v) {
//              TouchEventUtil.doClick(TouchEventChilds.class);
//          }
//      });
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        TouchEventUtil.logActionMsg(getClass(),"onInterceptTouchEvent",ev);
        return super.onInterceptTouchEvent(ev);
//      return true;
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        TouchEventUtil.logActionMsg(getClass(),"dispatchTouchEvent",ev);
        return super.dispatchTouchEvent(ev);
//      return true;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        TouchEventUtil.logActionMsg(getClass(),"onTouchEvent",ev);
        return super.onTouchEvent(ev);
    }

}

TouchEventChilds2:

package com.aohuan.test.dodoevent.view;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;

import com.aohuan.test.dodoevent.tools.TouchEventUtil;


public class TouchEventChilds2 extends Button {

    Context mContext;

    public TouchEventChilds2(Context context) {
        super(context);
        this.mContext = context;
    }

    public TouchEventChilds2(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.mContext = context;
//        this.setClickable(false);
//        this.setOnClickListener(new OnClickListener() {
//            @Override
//            public void onClick(View v) {
//                TouchEventUtil.doClick(TouchEventChilds2.class);
//            }
//        });
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        TouchEventUtil.logActionMsg(getClass(),"dispatchTouchEvent",ev);
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        TouchEventUtil.logActionMsg(getClass(),"onTouchEvent",ev);
        return super.onTouchEvent(ev);
    }


}


代碼簡述

這3個(gè)類之間胶惰,沒有直接關(guān)系,只是layout中簡單的關(guān)系

Paste_Image.png

這里 TouchEventFather霞溪, TouchEventChild孵滞, TouchEventChild2
分別表示 【1】, 【2】鸯匹, 【3】
我們可以分別設(shè)置值坊饶,和點(diǎn)擊他們,來理解 Intercept攔截

Paste_Image.png

不設(shè)置 onInterceptTouchEvent時(shí)候

我們分別點(diǎn)擊對應(yīng)的位置 【1】【2】【3】
大家可以猜一猜對應(yīng)的打印順序殴蓬。

點(diǎn)擊【1】

MainActivity    ----    dispatchTouchEvent  ---->   ACTION_DOWN ---->   noMsg
TouchEventFather    ----    dispatchTouchEvent  ---->   ACTION_DOWN ---->   noMsg
TouchEventFather    ----    onInterceptTouchEvent   ---->   ACTION_DOWN ---->   noMsg
TouchEventFather    ----    onTouchEvent    ---->   ACTION_DOWN ---->   noMsg
MainActivity    ----    onTouchEvent    ---->   ACTION_DOWN ---->   noMsg

Paste_Image.png

點(diǎn)擊【2】

MainActivity    ----    dispatchTouchEvent  ---->   ACTION_DOWN ---->   noMsg
TouchEventFather    ----    dispatchTouchEvent  ---->   ACTION_DOWN ---->   noMsg
TouchEventFather    ----    onInterceptTouchEvent   ---->   ACTION_DOWN ---->   noMsg
TouchEventChilds    ----    dispatchTouchEvent  ---->   ACTION_DOWN ---->   noMsg
TouchEventChilds    ----    onInterceptTouchEvent   ---->   ACTION_DOWN ---->   noMsg
TouchEventChilds    ----    onTouchEvent    ---->   ACTION_DOWN ---->   noMsg
TouchEventFather    ----    onTouchEvent    ---->   ACTION_DOWN ---->   noMsg
MainActivity    ----    onTouchEvent    ---->   ACTION_DOWN ---->   noMsg

Paste_Image.png

點(diǎn)擊【3】

MainActivity    ----    dispatchTouchEvent  ---->   ACTION_DOWN ---->   noMsg
TouchEventFather    ----    dispatchTouchEvent  ---->   ACTION_DOWN ---->   noMsg
TouchEventFather    ----    onInterceptTouchEvent   ---->   ACTION_DOWN ---->   noMsg
TouchEventChilds    ----    dispatchTouchEvent  ---->   ACTION_DOWN ---->   noMsg
TouchEventChilds    ----    onInterceptTouchEvent   ---->   ACTION_DOWN ---->   noMsg
TouchEventChilds2   ----    dispatchTouchEvent  ---->   ACTION_DOWN ---->   noMsg
TouchEventChilds2   ----    onTouchEvent    ---->   ACTION_DOWN ---->   noMsg
Paste_Image.png

簡單分析
·【1】是一個(gè)ViewGroup匿级,所以會(huì)分發(fā)下去,再回傳回去
·【2】是一個(gè)ViewGroup染厅,所以同樣會(huì)分發(fā)下去痘绎,再回傳回去
·【3】是一個(gè)View,所以觸發(fā)到OnTouchEvent后肖粮,就消費(fèi)了
· 我們可以發(fā)現(xiàn)在 dispatch后面孤页, 都會(huì)執(zhí)行onIntercept方法
· 前面說過 return super.onInterceptTouchEvent(ev),就是 return false涩馆,所以之前都是return false行施,就是不攔截
·注意:這里【3】是Button的子類,點(diǎn)擊會(huì)有點(diǎn)擊效果
·(后面會(huì)設(shè)置攔截后魂那,再注意觀察)


添加onInterceptTouchEvent 攔截

要攔截蛾号,就只要Override對應(yīng)ViewGroup的onInterceptTouchEvent方法,return true即可


TouchEventFather添加攔截

給TouchEventFather添加攔截涯雅,也就是對應(yīng)的方法return true以后
對應(yīng)的打印信息為:

MainActivity    ----    dispatchTouchEvent  ---->   ACTION_DOWN ---->   noMsg
TouchEventFather    ----    dispatchTouchEvent  ---->   ACTION_DOWN ---->   noMsg
TouchEventFather    ----    onInterceptTouchEvent   ---->   ACTION_DOWN ---->   noMsg
TouchEventFather    ----    onTouchEvent    ---->   ACTION_DOWN ---->   noMsg
MainActivity    ----    onTouchEvent    ---->   ACTION_DOWN ---->   noMsg
Paste_Image.png

我們可以發(fā)現(xiàn)鲜结,
到TouchEventFather后,就回傳給MainActivity的onTouchEvent
后面對應(yīng)的ViewGroup和View都沒有獲得到dispatchEvent


特殊測試

這個(gè)時(shí)候活逆, 我們給TouchEventChilds2添加一個(gè)點(diǎn)擊事件
因?yàn)門ouchEventChilds2是繼承Button的精刷,所以點(diǎn)擊很好測試

添加后,再次運(yùn)行
對應(yīng)的打印信息為:

MainActivity    ----    dispatchTouchEvent  ---->   ACTION_DOWN ---->   noMsg
TouchEventFather    ----    dispatchTouchEvent  ---->   ACTION_DOWN ---->   noMsg
TouchEventFather    ----    onInterceptTouchEvent   ---->   ACTION_DOWN ---->   noMsg
TouchEventFather    ----    onTouchEvent    ---->   ACTION_DOWN ---->   noMsg
MainActivity    ----    onTouchEvent    ---->   ACTION_DOWN ---->   noMsg
Paste_Image.png

我們可以發(fā)現(xiàn)划乖,界面上面沒有點(diǎn)擊效果
打印信息中也沒有點(diǎn)擊信息
說明贬养,點(diǎn)擊事件被攔截了
(通過前幾篇,我們也可以知道琴庵,先獲得TouchListener误算,再獲得onTouchEvent仰美,再會(huì)有ClickListener, 現(xiàn)在攔截以后儿礼, 不會(huì)有對應(yīng)的Touch事件了咖杂,更不會(huì)有Click事件了)


TouchEventChilds添加攔截

添加攔截后,對應(yīng)的信息為:

MainActivity    ----    dispatchTouchEvent  ---->   ACTION_DOWN ---->   noMsg
TouchEventFather    ----    dispatchTouchEvent  ---->   ACTION_DOWN ---->   noMsg
TouchEventFather    ----    onInterceptTouchEvent   ---->   ACTION_DOWN ---->   noMsg
TouchEventChilds    ----    dispatchTouchEvent  ---->   ACTION_DOWN ---->   noMsg
TouchEventChilds    ----    onInterceptTouchEvent   ---->   ACTION_DOWN ---->   noMsg
TouchEventChilds    ----    onTouchEvent    ---->   ACTION_DOWN ---->   noMsg
TouchEventFather    ----    onTouchEvent    ---->   ACTION_DOWN ---->   noMsg
MainActivity    ----    onTouchEvent    ---->   ACTION_DOWN ---->   noMsg
Paste_Image.png

我們可以發(fā)現(xiàn)蚊夫,
會(huì)dispatch到對應(yīng)的攔截以后诉字,就開始回傳


簡單總結(jié)

· onInterceptTouchEvent只有ViewGroup有,Activity和View都沒有
· onInterceptTouchEvent在當(dāng)前ViewGroup的dispatchTouchEvent之后執(zhí)行知纷,攔截后壤圃,就會(huì)從攔截的ViewGroup回傳, 不會(huì)dispatch給下一層
· super.onInterceptTouchEvent(ev)默認(rèn)返回false琅轧,所以return super.onInterceptTouchEvent(ev)伍绳,就是 return false,就是不攔截


下一篇我們可以了解dispatchTouchEvent事件分發(fā)淺析(五)消費(fèi)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末乍桂,一起剝皮案震驚了整個(gè)濱河市冲杀,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌睹酌,老刑警劉巖权谁,帶你破解...
    沈念sama閱讀 206,602評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異憋沿,居然都是意外死亡旺芽,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門卤妒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來甥绿,“玉大人字币,你說我怎么就攤上這事则披。” “怎么了洗出?”我有些...
    開封第一講書人閱讀 152,878評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵士复,是天一觀的道長。 經(jīng)常有香客問我翩活,道長阱洪,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,306評(píng)論 1 279
  • 正文 為了忘掉前任菠镇,我火速辦了婚禮冗荸,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘利耍。我一直安慰自己蚌本,他們只是感情好盔粹,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評(píng)論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著程癌,像睡著了一般舷嗡。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上嵌莉,一...
    開封第一講書人閱讀 49,071評(píng)論 1 285
  • 那天进萄,我揣著相機(jī)與錄音,去河邊找鬼锐峭。 笑死中鼠,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的沿癞。 我是一名探鬼主播兜蠕,決...
    沈念sama閱讀 38,382評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼抛寝!你這毒婦竟也來了熊杨?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,006評(píng)論 0 259
  • 序言:老撾萬榮一對情侶失蹤盗舰,失蹤者是張志新(化名)和其女友劉穎晶府,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體钻趋,經(jīng)...
    沈念sama閱讀 43,512評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡川陆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蛮位。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片较沪。...
    茶點(diǎn)故事閱讀 38,094評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖失仁,靈堂內(nèi)的尸體忽然破棺而出尸曼,到底是詐尸還是另有隱情,我是刑警寧澤萄焦,帶...
    沈念sama閱讀 33,732評(píng)論 4 323
  • 正文 年R本政府宣布控轿,位于F島的核電站,受9級(jí)特大地震影響拂封,放射性物質(zhì)發(fā)生泄漏茬射。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評(píng)論 3 307
  • 文/蒙蒙 一冒签、第九天 我趴在偏房一處隱蔽的房頂上張望在抛。 院中可真熱鬧,春花似錦萧恕、人聲如沸刚梭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽望浩。三九已至辖所,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間磨德,已是汗流浹背缘回。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評(píng)論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留典挑,地道東北人酥宴。 一個(gè)月前我還...
    沈念sama閱讀 45,536評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像您觉,于是被迫代替她去往敵國和親拙寡。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評(píng)論 2 345

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