本篇讲述的是Android控件的事件机制,这也是Android自定义控件的核心部分。由于Android系统越来越完善,现在它的事件处理机制也完善的越来越好,不过整体的核心思想是没有变化的,所以在本篇博客中是使用的较低版本的Android源代码来进行事件处理的分析的。
一、事件机制的整体概述:
Android控件的事件处理机制采用的是事件由外向内传递的方式,废话不多说上一张图便可以清晰明了,图如下所示:
二、事件机制的详细分析
在事件处理的过程中主要涉及如下三个方法:
2.1 dispatchTouchEvent:
这个方法用于分发事件,它可以说是事件处理的总控开关,它一旦失效那么整个控件的事件处理体系可以算是破碎了。ViewGroup中针对这个方法的源码实现如下所示:
View mTarget=null;//保存捕获Touch事件处理的View
public boolean dispatchTouchEvent(MotionEvent ev) {
//....其他处理,在此不管
if(ev.getAction()==KeyEvent.ACTION_DOWN){
//每次Down事件,都置为Null
if (disallowIntercept || !onInterceptTouchEvent(ev)) {
mTarget=null;
View[] views=getChildView();
for(int i=0;i<views.length;i++){
if(views[i].dispatchTouchEvent(ev)){
mTarget=views[i];
return true;
}
}
}
}
//当子View没有捕获down事件时,ViewGroup自身处理。这里处理的Touch事件包含Down、Up和Move
if(mTarget==null){
return super.dispatchTouchEvent(ev);
}
if (!disallowIntercept && onInterceptTouchEvent(ev)) {
//其他操作,不管
// clear the target
mMotionTarget = null;
return true;
}
//这一步在Action_Down中是不会执行到的,只有Move和UP才会执行到。
return mTarget.dispatchTouchEvent(ev);
}
2.2 onInterceptTouchEvent:
这个方法用于阻隔事件的传递,它可以理解成建立在高速路上的收费站。这个方法存在于ViewGroup及其子类中,它的存在本来就是为了方便控件的容器来操纵控件的。ViewGroup中针对这个方法的源码实现如下所示:
public boolean onInterceptTouchEvent(MotionEvent ev) {
return false;
}
2.3 onTouchEvent
这个方法用来处理事件,在它的方法内部可以针对具体的事件类型来处理相应的业务逻辑。
View中针对这个方法的源码实现如下所示:
public boolean onTouchEvent(MotionEvent event) {
//其他操作,不管 如果可以点击则为true
return false;
}
三、场景辅助理解
说明:家规相当于事件传递的基本规则;梨相当于MotionEvent;传递梨的过程相当于dispatchOnTouchEvent;迫切需要吃相当于onInterceptTouchEvent;请求父亲不要跟我强相当于调用requestDisallowedInterceptTouchEvent(true);
注意:除了最后一个场景之外只要处理如何吃梨一般都会触发MotionEvent.ACTION_DOWN、MotionEvent.ACTION_MOVE、MotionEvent.ACTION_UP这三类事件,最后一个场景处理会触发这三个事件外还会触发MotionEvent.ACTION_CANCEL这类事件,因为中途抢走事件子View肯定要先取消事件,然后再将取消事件之前的事件状态交给抢走的控件处理;