dispatchTouchEvent事件分发浅析(四)Intercept拦截

上一篇,我们大体理解了分发的过程,并且简单做了点击,分析了执行顺序
这篇我们来看下 Intercept拦截

具体代码可以见https://github.com/2954722256/demo_event

在看之前, 我们先看一下 API

相关组件可以Override的方法

Paste_Image.png

前言

前面用到了 dispatchTouchEvent 和 onTouchEvent
分别表示 分发事件 和 触摸消费的事件
我们可以发现, Activity 和 View都只有这2个方法
在ViewGroup除了这2个方法以外, 还有一个 onInterceptTouchEvent 方法,
如果return true,表示拦截, 不向下传递了

我们看一下ViewGroup中
onInterceptTouchEvent 方法的实现

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

简单总结
我们可以发现这里,
默认是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个类之间,没有直接关系,只是layout中简单的关系

Paste_Image.png

这里 TouchEventFather, TouchEventChild, TouchEventChild2
分别表示 【1】, 【2】, 【3】
我们可以分别设置值,和点击他们,来理解 Intercept拦截

Paste_Image.png

不设置 onInterceptTouchEvent时候

我们分别点击对应的位置 【1】【2】【3】
大家可以猜一猜对应的打印顺序。

点击【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

点击【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

点击【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】是一个ViewGroup,所以会分发下去,再回传回去
·【2】是一个ViewGroup,所以同样会分发下去,再回传回去
·【3】是一个View,所以触发到OnTouchEvent后,就消费了
· 我们可以发现在 dispatch后面, 都会执行onIntercept方法
· 前面说过 return super.onInterceptTouchEvent(ev),就是 return false,所以之前都是return false,就是不拦截
·注意:这里【3】是Button的子类,点击会有点击效果
·(后面会设置拦截后,再注意观察)


添加onInterceptTouchEvent 拦截

要拦截,就只要Override对应ViewGroup的onInterceptTouchEvent方法,return true即可


TouchEventFather添加拦截

给TouchEventFather添加拦截,也就是对应的方法return true以后
对应的打印信息为:

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

我们可以发现,
到TouchEventFather后,就回传给MainActivity的onTouchEvent
后面对应的ViewGroup和View都没有获得到dispatchEvent


特殊测试

这个时候, 我们给TouchEventChilds2添加一个点击事件
因为TouchEventChilds2是继承Button的,所以点击很好测试

添加后,再次运行
对应的打印信息为:

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

我们可以发现,界面上面没有点击效果
打印信息中也没有点击信息
说明,点击事件被拦截了
(通过前几篇,我们也可以知道,先获得TouchListener,再获得onTouchEvent,再会有ClickListener, 现在拦截以后, 不会有对应的Touch事件了,更不会有Click事件了)


TouchEventChilds添加拦截

添加拦截后,对应的信息为:

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

我们可以发现,
会dispatch到对应的拦截以后,就开始回传


简单总结

· onInterceptTouchEvent只有ViewGroup有,Activity和View都没有
· onInterceptTouchEvent在当前ViewGroup的dispatchTouchEvent之后执行,拦截后,就会从拦截的ViewGroup回传, 不会dispatch给下一层
· super.onInterceptTouchEvent(ev)默认返回false,所以return super.onInterceptTouchEvent(ev),就是 return false,就是不拦截


下一篇我们可以了解dispatchTouchEvent事件分发浅析(五)消费

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容