1.View事件的分发机制
请想象一下生活中非常常见的现象:
假设你所在的学校,学校接到一份通知说领导要来视察。假设学校的校长级别最高,他下面有你的班主任老师,级别次之:最底层,就是干活的你,没有级别。现在为了应对领导的视察校长要把学校的门口公共卫生搞干净(这是一项任务)。校长把这一项任务安排给你的班主任,你的班主任把这项任务安排给了你。而好不容易你把活干完了,你就把任务交给了班主任,班主任觉得完成的不错,于是签了名字交给校长。这样一个任务就顺利的完成了。为了能够方便的了解整个事件的流程,我做了如下的设计:
校长----MyViewGroupA,最外层的ViewGroup.
班主任--MyViewGroupB,中间层的ViewGroup.
干活的你--MyView,在最顶层
整体效果图如下:
我们新建三个类 MyViewGroupA.java ,MyViewGroupB.java,MyView.java
MyViewGroupA.java:
<span style="font-size:12px;">public class MyViewGroupA extends LinearLayout {
public MyViewGroupA(Context context) {
super(context);
}
public MyViewGroupA(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyViewGroupA(Context context, AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.d("xys", "ViewGroupA dispatchTouchEvent" + ev.getAction());
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.d("xys", "ViewGroupA onInterceptTouchEvent" + ev.getAction());
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.d("xys", "ViewGroupA onTouchEvent" + event.getAction());
return super.onTouchEvent(event);
// return true;
}
}</span>
MyViewGroupB.java:
<span style="font-size:12px;">public class MyViewGroupB extends LinearLayout {
public MyViewGroupB(Context context) {
super(context);
}
public MyViewGroupB(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyViewGroupB(Context context, AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.d("xys", "ViewGroupB dispatchTouchEvent" + ev.getAction());
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.d("xys", "ViewGroupB onInterceptTouchEvent" + ev.getAction());
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.d("xys", "ViewGroupB onTouchEvent" + event.getAction());
return super.onTouchEvent(event);
// return true;
}
}</span>
MyView.java:
<span style="font-size:12px;">import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
public class MyView extends View {
public MyView(Context context) {
super(context);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyView(Context context, AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.d("xys", "View onTouchEvent" + event.getAction());
return super.onTouchEvent(event);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
Log.d("xys", "View dispatchTouchEvent" + event.getAction());
return super.dispatchTouchEvent(event);
}
}</span>
我们分情况来比较
1.1 先不修改任何返回值,点击一下View,log打印信息如下:
可以看见正常情况下,
事件的传递顺序是:
校长(MyViewGroupA)—班主任(MyViewGroupB)—你(View)。事件的传递顺序先执行dispatchTouchEvent()方法,再执行onInterceptEvent()方法。
事件的处理顺序是:
你(View)—班主任(MyViewGroupB)—校长(MyViewGroupA)。事件处理都是执行onTouchEvent()方法。
事件传递的返回值非常容易理解:True,拦截,不继续;False,不拦截,继续流程。
事件处理的返回值也类似:True,处理了,不用审核了:False,给上级处理。
初始情况下返回值都是False.
1.2 假设校长觉得这项任务没必要找班主任,自己就可以完成。因此事件就被校长拦截了,即让MyViewGroupA的
onInterceptTouchEvent()方法返回true,我们再来看看log信息。
跟我们所想的一样,校长把所有的事情都干完了,没后面的人什么事了。
1.3 假设班主任觉得这项任务没必要找你,自己就可以完成。因此事件就被班主任拦截了,即让MyViewGroupB的
onInterceptTouchEvent()方法返回true,我们再来看看log信息。
我们就可以知道,班主任把所有的事情都做完了,后面的你(MyView)就不需要干活 了。到此我们的事件的分发,拦截机制应该比较清楚了。
再来看看事件的处理:
1.4 先来看那看底层的人民---你(MyView),当你处理完底层任务以后,需要上级的确认,所以你的处理事件返回false。但是有一天你不干了罢工了,也就不用报告上级 班主任了,所以直接返回true。即让onTouchEvent()方法返回true,点击view,让我们来看看log信息。
可以看出事件传递和以前一样,但是事件处理到你(MyView)就结束了。因为你返回true,不用向上级报告。
1.5 如果你把完成的任务递交给班主任,但是班主任觉得你完成的不够好并没有把你做好的任务报告给校长。所以直接返回true。即让班主任的onTouchEvent()方法返回true,点击view,让我们来看看log信息。
可以知道事件处理到班主任(MyViewGroupB)就结束了。
通过上面的几种情况分析,我们可以得出如下结论:
事件的传递顺序是:
校长(MyViewGroupA)—班主任(MyViewGroupB)—你(View)。事件的传递顺序先执行dispatchTouchEvent()方法,再执行onInterceptEvent()方法。
事件的处理顺序是:
你(View)—班主任(MyViewGroupB)—校长(MyViewGroupA)。事件处理都是执行onTouchEvent()方法。
事件传递的返回值非常容易理解:True,拦截,不继续;False,不拦截,继续流程。
事件处理的返回值也类似:True,处理了,不用审核了:False,给上级处理。
初始情况下返回值都是False。