上一篇,我们大体理解了分发的过程,并且简单做了点击,分析了执行顺序
这篇我们来看下 Intercept拦截
具体代码可以见https://github.com/2954722256/demo_event
在看之前, 我们先看一下 API
相关组件可以Override的方法
前言
前面用到了 dispatchTouchEvent 和 onTouchEvent
分别表示 分发事件 和 触摸消费的事件
我们可以发现, Activity 和 View都只有这2个方法
在ViewGroup除了这2个方法以外, 还有一个 onInterceptTouchEvent 方法,
如果return true,表示拦截, 不向下传递了
我们看一下ViewGroup中
onInterceptTouchEvent 方法的实现
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中简单的关系
这里 TouchEventFather, TouchEventChild, TouchEventChild2
分别表示 【1】, 【2】, 【3】
我们可以分别设置值,和点击他们,来理解 Intercept拦截
不设置 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
点击【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
点击【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
简单分析
·【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
我们可以发现,
到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
我们可以发现,界面上面没有点击效果
打印信息中也没有点击信息
说明,点击事件被拦截了
(通过前几篇,我们也可以知道,先获得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
我们可以发现,
会dispatch到对应的拦截以后,就开始回传
简单总结
· onInterceptTouchEvent只有ViewGroup有,Activity和View都没有
· onInterceptTouchEvent在当前ViewGroup的dispatchTouchEvent之后执行,拦截后,就会从拦截的ViewGroup回传, 不会dispatch给下一层
· super.onInterceptTouchEvent(ev)默认返回false,所以return super.onInterceptTouchEvent(ev),就是 return false,就是不拦截
下一篇我们可以了解dispatchTouchEvent事件分发浅析(五)消费