事件分发机制
1. view事件分发
在view中有俩个方法,一个为onTouchEvent();和dispatchTouchEvent()<—分发—>;
接下来我们来写一段伪代码测试一下这俩个方法的触发流程及返回值会对结果造成什么样的影响
package cn.com.touchdemo;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
/**
* Created by Administrator on 2017/10/16 0016.
*/
public class MyView extends View {
private static final String TAG = "MyView";
public MyView(Context context) {
super(context);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
Log.e(TAG, "dispatchTouchEvent: ");
return super.dispatchTouchEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.e(TAG, "onTouchEvent: ");
return super.onTouchEvent(event);
}
}
未做任何处理Log如下:
10-16 10:44:38.726 12013-12013/cn.com.touchdemo E/MyView: dispatchTouchEvent:
10-16 10:44:38.727 12013-12013/cn.com.touchdemo E/MyView: onTouchEvent:
首先我们能看出这个dispatchTouchEvent()方法是有一个boolean类型的返回值,我们手动的将这个返回值改成true 和 false 分别测试。(下面我就贴代码,只写log)
- 返回true时:
10-16 10:51:52.197 20380-20380/cn.com.touchdemo E/MyView: dispatchTouchEvent:
10-16 10:51:52.226 20380-20380/cn.com.touchdemo E/MyView: dispatchTouchEvent:
10-16 10:51:52.267 20380-20380/cn.com.touchdemo E/MyView: dispatchTouchEvent:
10-16 10:51:52.268 20380-20380/cn.com.touchdemo E/MyView: dispatchTouchEvent:
- 返回false时:
10-16 10:53:22.812 22731-22731/cn.com.touchdemo E/MyView: dispatchTouchEvent:
这时我们看出这个方法无论返回true或false都不会触发onTouchEvent(),这个事件。只有返回值是默认父类的方法时才会不进行拦截onTouchEvent()事件。
由此可以看出如果我们想要拦截一个view的事件的是只需重写dispatchTouchEvent();方法,将返回值该成false,并且不使用父类的super.dispatchTouchEvent(event),这样这个view的事件就会停止分发下去。在此处消费。
2. viewGroup事件分发
viewGroup不同于view的是它有三个方法:
onInterceptTouchEvent(ev) <–拦截–>
dispatchTouchEvent(ev) <–分发–>
onTouchEvent(event)
下面我们通过一段伪代码来测试一下这个三个方法的触发流程及拦截的效果
package cn.com.touchdemo;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ViewGroup;
/**
* Created by Administrator on 2017/10/16 0016.
*/
public class MyGroupView extends ViewGroup {
private static final String TAG = "MyGroupView";
public MyGroupView(Context context) {
super(context);
}
public MyGroupView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.e(TAG, "onInterceptTouchEvent: ");
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.e(TAG, "dispatchTouchEvent: ");
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.e(TAG, "onTouchEvent: ");
return super.onTouchEvent(event);
}
}
我点击了三次这个控件,log如下
10-16 11:09:06.032 30529-30529/cn.com.touchdemo E/MyGroupView: dispatchTouchEvent:
10-16 11:09:06.033 30529-30529/cn.com.touchdemo E/MyGroupView: onInterceptTouchEvent:
10-16 11:09:06.033 30529-30529/cn.com.touchdemo E/MyGroupView: onTouchEvent:
10-16 11:09:07.132 30529-30529/cn.com.touchdemo E/MyGroupView: dispatchTouchEvent:
10-16 11:09:07.132 30529-30529/cn.com.touchdemo E/MyGroupView: onInterceptTouchEvent:
10-16 11:09:07.132 30529-30529/cn.com.touchdemo E/MyGroupView: onTouchEvent:
10-16 11:09:07.982 30529-30529/cn.com.touchdemo E/MyGroupView: dispatchTouchEvent:
10-16 11:09:07.982 30529-30529/cn.com.touchdemo E/MyGroupView: onInterceptTouchEvent:
10-16 11:09:07.982 30529-30529/cn.com.touchdemo E/MyGroupView: onTouchEvent:
首先,我们将dispatchTouchEvent这个事件的返回值改成false,正常来说应该不会触发任何事件,测试一下
10-16 11:11:17.333 15844-15844/cn.com.touchdemo E/MyGroupView: dispatchTouchEvent:
10-16 11:11:18.191 15844-15844/cn.com.touchdemo E/MyGroupView: dispatchTouchEvent:
10-16 11:11:18.907 15844-15844/cn.com.touchdemo E/MyGroupView: dispatchTouchEvent:
果然如此(与view中的dispatchTouchEvent相同),接下来将dispatchTouchEvent改成默认,我们来测试onInterceptTouchEvent这个事件的返回值有什么区别。
- 返回false时:
10-16 11:14:02.881 19799-19799/cn.com.touchdemo E/MyGroupView: dispatchTouchEvent:
10-16 11:14:02.881 19799-19799/cn.com.touchdemo E/MyGroupView: onInterceptTouchEvent:
10-16 11:14:02.881 19799-19799/cn.com.touchdemo E/MyGroupView: onTouchEvent:
10-16 11:14:03.600 19799-19799/cn.com.touchdemo E/MyGroupView: dispatchTouchEvent:
10-16 11:14:03.600 19799-19799/cn.com.touchdemo E/MyGroupView: onInterceptTouchEvent:
10-16 11:14:03.600 19799-19799/cn.com.touchdemo E/MyGroupView: onTouchEvent:
无效果
- 返回true时:
10-16 11:14:59.469 21546-21546/cn.com.touchdemo E/MyGroupView: dispatchTouchEvent:
10-16 11:14:59.469 21546-21546/cn.com.touchdemo E/MyGroupView: onInterceptTouchEvent:
10-16 11:14:59.469 21546-21546/cn.com.touchdemo E/MyGroupView: onTouchEvent:
10-16 11:15:00.544 21546-21546/cn.com.touchdemo E/MyGroupView: dispatchTouchEvent:
10-16 11:15:00.544 21546-21546/cn.com.touchdemo E/MyGroupView: onInterceptTouchEvent:
10-16 11:15:00.544 21546-21546/cn.com.touchdemo E/MyGroupView: onTouchEvent:
10-16 11:15:01.240 21546-21546/cn.com.touchdemo E/MyGroupView: dispatchTouchEvent:
10-16 11:15:01.241 21546-21546/cn.com.touchdemo E/MyGroupView: onInterceptTouchEvent:
10-16 11:15:01.241 21546-21546/cn.com.touchdemo E/MyGroupView: onTouchEvent:
同样是无效果的
当我们在这个viewGroup中加入child的时候
- 返回 true时,child的事件不会被触发。
- 返回false和默认的时候child的事件都会正常触发。
总结:
- view中事件分发机制:
1.onTouchEvent(); 处理手势事件这里不深入介绍
2.dispatchTouchEvent(); 事件分发,当此处返回值不是默认值时,当前控件的触摸事件就会在此处消费,不会触发其他任何事件包括onTouchEvent()或onClick()等。 - viewGroup中事件分发机制:
1.onInterceptTouchEvent(ev) 此方法是viewGroup独有的拦截事件,主要负责对子view的事件进行拦截。若此处返回true时,当前viewGroup的childView将不会触发他们本身设置的事件,当返回true和默认的时候会不拦截,但当dispatchTouchEvent返回非默认的时候及表示当前事件只能在此处消费的时候子view也不会触发任何事件。
2.dispatchTouchEvent(ev) 同于view
3.onTouchEvent(event) 同于view
————————-
:不是每一次努力都会有收获,但是,每一次收获都必须努力,这是一个不公平的不可逆转的命题。