在Android中,消息的传递控制主要是通过两个方法共同配合使用来对用户的触摸消息进行分发的,下面就来看看这两个方法;
onInterceptTouchEvent:此方法定义于ViewGroup中,顾名思义,这个方法是用于ViewGroup拦截(intercept)触摸消息的;
onTouchEvent:此方法定义于View中,用于处理用户的触摸事件;
下面来看这两个方法的定义原型;
public boolean onInterceptTouchEvent(MotionEvent ev); public boolean onTouchEvent(MotionEvent event);
这两个方法的一个共同点就是都有一个参数MotionEvent用于获取触摸事件的具体信息(比如按下,移动等等消息形态)和函数返回值(用于控制不同场合的触摸处理);
简单说一下MotionEvent,它包含了用户触摸消息的类型,常用的几种触摸消息类型为:ACTION_DOWN,ACTION_MOVE,ACTION_UP,ACTION_CANCEL, 分别表示触摸按下,移动,结束的状态;这几种消息类型不是并发产生的,而是如同触摸发生的次序一样有序产生的,DOWN->MOVE->UP/CANCEL;
下边通过一个例子来研究,分别自定义一个简单的ViewGroup和View,用于跟踪onTouchEvent和onInterceptTouchEvent的执行;
LLinearLayout
public class LLinearLayout extends LinearLayout { public LLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); } public LLinearLayout(Context context) { super(context); } private float lastY; @Override public boolean onInterceptTouchEvent(MotionEvent ev) { String tag = "onInterceptTouchEvent"; Log.w(tag, "" + super.onInterceptTouchEvent(ev)); switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: Log.w(tag, "ACTION_DOWN"); lastY = ev.getX(); break; case MotionEvent.ACTION_MOVE: Log.w(tag, "ACTION_MOVE"); if (ev.getX() - lastY > 20) { Log.w(tag, "ACTION_MOVE>20"); return true; } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: Log.w(tag, "ACTION_UP"); break; } return false; } @Override public boolean onTouchEvent(MotionEvent event) { Log.w("onTouchEvent", "" + super.onTouchEvent(event)); return false; } }
LView
public class LView extends ImageView { public LView(Context context, AttributeSet attrs) { super(context, attrs); } public LView(Context context) { super(context); } @Override public boolean onTouchEvent(MotionEvent event) { String tag = "LView.onTouchEvent"; Log.e(tag, "" + super.onTouchEvent(event)); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: Log.e(tag, "ACTION_DOWN"); break; case MotionEvent.ACTION_MOVE: Log.e(tag, "ACTION_MOVE"); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: Log.e(tag, "ACTION_UP"); break; } return false; } }
在xml文件中将LView加入LLinearLayout中,通过一系列更改来一控究竟;
step1:
通过上面的Log信息,可以看出,触摸事件先被LLinearLayout拦截到(onInterceptTouchEvent),在这个Demo中,该方法返回值为false,接着就将Touch事件传递给LView,LView的onTouchEvent响应了此次触摸事件,并且也返回false;然后Touch事件再传递给LLinearLayout的onTouchEvent进行处理;
从上面我们可以简单的看出,Touch事件先被LLinearLayout拦截到,然后传递给LView,LView执行onTouchEvent处理逻辑;然后LLinearLayout再执行自己的onTouchEvent处理逻辑;@1
step2:将上面LLinearLayout的onInterceptTouchEvent方法返回值改为true,再次运行程序;
相比上面的Log信息,可以看到消息没有传递到LView;到这里,应该可以得出一个小小的结论了吧;