android view事件传递机制对不管是初学者还是有经验的开发者来说,都是一个比较核心的机制。可能说起事件分发机制,很多人都能立马就能说出dispatchTouchEvent(),onInterceptTouchEvent(),onTouchEvent()这三个回调方法,有些人甚至可能也会说出“隧道“,“冒泡“机制。诚然,android 的view事件分发机制确实离不开这三个方法,但是对于这三个方法之间是如何分发,拦截,相互协调工作的,怎样“隧道“,“冒泡“以及每个方法中返回的布尔值对触摸事件造成的影响,相信很多人理解的可能还不是十分透彻。
本篇文章就将通过在一个三层的view型树结构上触发手势触摸事件实验,通过不断修改这三个方法中的返回值,来深入理解android 中 view的事件分发,拦截机制。
该实验中将用到四个类文件,分别是:
- TestViewEventActivity :用来展示三层view布局文件,以及接收用户触摸事件的Activity
- OuterLayout 第一层,继承自RelativeLayout
- InngerLayout 第二层view,继承自RelativeLayout
LeafView 第三层view ,继承子TextView
运行起来后,效果图展示如下:
先来看TestViewEventActivity的源代码:
package love.gaoge.view.event;
import android.os.Bundle;
import android.view.MotionEvent;
import love.gaoge.R;
import love.gaoge.base.BaseActivity;
import love.gaoge.util.Logg;
/**
* 测试父view,子view touch事件
* @author gaoge
* @version V1.0
* @date 2016-03-02 18:20
* @tips
*/
public class TestViewEventActivity extends BaseActivity{
String tag = "eve";
private OuterLayout outer;
private InnerLayout inner;
private LeafView leaf;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_view_event);
outer = (OuterLayout)findViewById(R.id.outer);
inner = (InnerLayout)findViewById(R.id.inner);
leaf = (LeafView)findViewById(R.id.leaf);
/**
* 只有设置了clickListener以后,才可以监听到ACTION_MOVE,ACTION_UP事件!!!
*/
// outer.setOnClickListener(this);
// inner.setOnClickListener(this);
// leaf.setOnClickListener(this);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
Logg.d(tag, "TestViewEvent.dispatchTouchEvent(),ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Logg.d(tag, "TestViewEvent.dispatchTouchEvent(),ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Logg.d(tag, "TestViewEvent.dispatchTouchEvent(),ACTION_UP");
break;
case MotionEvent.ACTION_CANCEL:
Logg.d(tag, "TestViewEvent.dispatchTouchEvent(),ACTION_CANCEL");
break;
}
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
Logg.d(tag, "TestViewEvent.onTouchEvent(),ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Logg.d(tag, "TestViewEvent.onTouchEvent(),ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Logg.d(tag, "TestViewEvent.onTouchEvent(),ACTION_UP");
break;
case MotionEvent.ACTION_CANCEL:
Logg.d(tag, "TestViewEvent.onTouchEvent(),ACTION_CANCEL");
break;
}
return super.onTouchEvent(event);
}
}
OuterLayout源代码:
package love.gaoge.view.event;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.RelativeLayout;
import love.gaoge.util.Logg;
/**
* @author gaoge
* @version V1.0
* @date 2016-03-02 18:18
* @tips
*/
public class OuterLayout extends RelativeLayout {
String tag = "eve";
public OuterLayout(Context context) {
super(context);
}
public OuterLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public OuterLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
Logg.d(tag, "OuterLayout.dispatchTouchEvent(),ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Logg.d(tag, "OuterLayout.dispatchTouchEvent(),ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Logg.d(tag,