上一篇殉簸,我們大體理解了分發(fā)的過程睬捶,并且簡單做了點(diǎn)擊髓堪,分析了執(zhí)行順序
這篇我們來看下 Intercept攔截
具體代碼可以見https://github.com/2954722256/demo_event
在看之前竞思, 我們先看一下 API
相關(guān)組件可以O(shè)verride的方法
前言
前面用到了 dispatchTouchEvent 和 onTouchEvent
分別表示 分發(fā)事件 和 觸摸消費(fèi)的事件
我們可以發(fā)現(xiàn)踩娘, Activity 和 View都只有這2個(gè)方法
在ViewGroup除了這2個(gè)方法以外刮刑, 還有一個(gè) onInterceptTouchEvent 方法,
如果return true,表示攔截雷绢, 不向下傳遞了
我們看一下ViewGroup中
onInterceptTouchEvent 方法的實(shí)現(xiàn)
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)系
這里 TouchEventFather霞溪, TouchEventChild孵滞, TouchEventChild2
分別表示 【1】, 【2】鸯匹, 【3】
我們可以分別設(shè)置值坊饶,和點(diǎn)擊他們,來理解 Intercept攔截
不設(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
點(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
點(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
簡單分析
·【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
我們可以發(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
我們可以發(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
我們可以發(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,就是不攔截