前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >dispatchTouchEvent事件分发浅析(四)Intercept拦截

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

作者头像
dodo_lihao
发布2018-09-12 11:04:00
6170
发布2018-09-12 11:04:00
举报
文章被收录于专栏:懒人开发懒人开发

上一篇,我们大体理解了分发的过程,并且简单做了点击,分析了执行顺序 这篇我们来看下 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

代码语言:javascript
复制
public boolean onInterceptTouchEvent(MotionEvent ev) {
    return false;
}

简单总结 我们可以发现这里, 默认是return false, 不拦截 也就是说如果是直接extends ViewGroup, return super.onInterceptTouchEvent(ev) 就是 return false 表示 不拦截


代码

TouchEventFather:

代码语言:javascript
复制
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:

代码语言:javascript
复制
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:

代码语言:javascript
复制
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】

代码语言:javascript
复制
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】

代码语言:javascript
复制
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】

代码语言:javascript
复制
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以后 对应的打印信息为:

代码语言:javascript
复制
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的,所以点击很好测试

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

代码语言:javascript
复制
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添加拦截

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

代码语言:javascript
复制
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,就是不拦截

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016.08.23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 相关组件可以Override的方法
  • 前言
  • 代码
  • 代码简述
    • 不设置 onInterceptTouchEvent时候
    • 添加onInterceptTouchEvent 拦截
    • TouchEventFather添加拦截
    • 特殊测试
    • TouchEventChilds添加拦截
    • 简单总结
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档