首先,从最简单的一种情况开始
***************************************
分割线 demo1
***************************************
假设一个视图,外面一层是RelativeLayout,内部包了一个TextView,则事件传递的顺序如下
07-25 05:26:27.037 10515-10515/com.example.androidtest I/EventTest: MainActivity 0 Event:按下.............................................................
07-25 05:26:27.037 10515-10515/com.example.androidtest I/EventTest: MainActivity 0 dispatchTouchEvent
07-25 05:26:27.037 10515-10515/com.example.androidtest I/EventTest: CustomRelativeLayout 1 dispatchTouchEvent
07-25 05:26:27.037 10515-10515/com.example.androidtest I/EventTest: CustomRelativeLayout 1 onIntereptTouchcEvent
07-25 05:26:27.037 10515-10515/com.example.androidtest I/EventTest: CustomTextView 3 dispatchTouchEvent
07-25 05:26:27.037 10515-10515/com.example.androidtest I/EventTest: CustomTextView 3 onTouchEvent
07-25 05:26:27.037 10515-10515/com.example.androidtest I/EventTest: CustomRelativeLayout 1 onTouchEvent
07-25 05:26:27.037 10515-10515/com.example.androidtest I/EventTest: MainActivity 0 onTouchEvent
07-25 05:26:27.092 10515-10515/com.example.androidtest I/EventTest: MainActivity 0 Event:抬起.............................................................
07-25 05:26:27.092 10515-10515/com.example.androidtest I/EventTest: MainActivity 0 dispatchTouchEvent
07-25 05:26:27.092 10515-10515/com.example.androidtest I/EventTest: MainActivity 0 onTouchEvent
事件传送 level 0 1 3 -- 3 1 0
从log信息我们可以看出,首先Activity 接收到按下事件,然后activity把这个事件向下分别分发,结果一直到最后的TextView都没有人处理这个事件,
则这时系统只好又依次调用父级节点的onTouchEvent,仍然没有谁来处理,这个时候系统觉得,既然按下都没有谁来处理,抬起事件自然就更没有谁来处理了。
所以抬起事件索性就没有分发给View层了。呵呵,是不是和生活中的某种场景很像。
***************************************
分割线 demo2
***************************************
现在我们把上面的条件稍微修改下,把CustomTextView的dispatchTouchEvent返回值改为Ture
@Override public boolean dispatchTouchEvent(MotionEvent event) { Log.i(Constants.tag,tag+level+" dispatchTouchEvent "); boolean superReturn = super.dispatchTouchEvent(event); return true; }
07-25 05:37:12.157 11242-11242/com.example.androidtest I/EventTest: MainActivity 0 Event:按下............................................................. 07-25 05:37:12.157 11242-11242/com.example.androidtest I/EventTest: MainActivity 0 dispatchTouchEvent 07-25 05:37:12.157 11242-11242/com.example.androidtest I/EventTest: CustomRelativeLayout 1 dispatchTouchEvent 07-25 05:37:12.157 11242-11242/com.example.androidtest I/EventTest: CustomRelativeLayout 1 onIntereptTouchcEvent 07-25 05:37:12.157 11242-11242/com.example.androidtest I/EventTest: CustomTextView 3 dispatchTouchEvent 07-25 05:37:12.157 11242-11242/com.example.androidtest I/EventTest: CustomTextView 3 onTouchEvent 07-25 05:37:12.220 11242-11242/com.example.androidtest I/EventTest: MainActivity 0 Event:抬起............................................................. 07-25 05:37:12.220 11242-11242/com.example.androidtest I/EventTest: MainActivity 0 dispatchTouchEvent 07-25 05:37:12.220 11242-11242/com.example.androidtest I/EventTest: CustomRelativeLayout 1 dispatchTouchEvent 07-25 05:37:12.220 11242-11242/com.example.androidtest I/EventTest: CustomRelativeLayout 1 onIntereptTouchcEvent 07-25 05:37:12.220 11242-11242/com.example.androidtest I/EventTest: CustomTextView 3 dispatchTouchEvent 07-25 05:37:12.220 11242-11242/com.example.androidtest I/EventTest: CustomTextView 3 onTouchEvent
这次TextView获取到了抬起事件。
并且我们可以看到,一旦触摸事件被消费掉了,则事件传递就会终止,并没有像第一个案例那样没有人消费的情况下又回传。
事件传送level 0 1 3
***************************************
分割线 demo3
***************************************
下面,我们来看看onInterceptTouchEvent的作用
把RelativeLayout 的onInterceptTouchEvent修改如下
@Override public boolean onInterceptTouchEvent(MotionEvent ev) { Log.i(Constants.tag,tag+level+" onIntereptTouchcEvent "); boolean superReturn = super.onInterceptTouchEvent(ev); return true; }07-25 05:51:14.717 11917-11917/com.example.androidtest I/EventTest: MainActivity 0 Event:按下............................................................. 07-25 05:51:14.717 11917-11917/com.example.androidtest I/EventTest: MainActivity 0 dispatchTouchEvent 07-25 05:51:14.718 11917-11917/com.example.androidtest I/EventTest: CustomRelativeLayout 1 dispatchTouchEvent 07-25 05:51:14.718 11917-11917/com.example.androidtest I/EventTest: CustomRelativeLayout 1 onIntereptTouchcEvent 07-25 05:51:14.718 11917-11917/com.example.androidtest I/EventTest: CustomRelativeLayout 1 onTouchEvent 07-25 05:51:14.718 11917-11917/com.example.androidtest I/EventTest: MainActivity 0 onTouchEvent 07-25 05:51:14.805 11917-11917/com.example.androidtest I/EventTest: MainActivity 0 Event:抬起............................................................. 07-25 05:51:14.805 11917-11917/com.example.androidtest I/EventTest: MainActivity 0 dispatchTouchEvent 07-25 05:51:14.805 11917-11917/com.example.androidtest I/EventTest: MainActivity 0 onTouchEvent可以看到,事件没能传递到TextView层,这个和TextView本身的方法返回值无关,因为在外层ViewGroup就已经截断了事件传递当然,这里我们只是阻止了事件向下传递,但并没有去handle这事件,因此这个事件又返回去了(调用外层onTouchEvent方法),导致activity认为没人处理这个事件,所以抬起事件没有向下传递。ok,继续,我们继续修改demo3代码,***************************************
分割线 demo4
***************************************
修改了RelativeLayout的代码如下@Override public boolean dispatchTouchEvent(MotionEvent ev) { Log.i(Constants.tag,tag+level+" dispatchTouchEvent "); boolean superReturn = super.dispatchTouchEvent(ev); return true; }07-25 05:58:11.484 12111-12111/com.example.androidtest I/EventTest: MainActivity 0 Event:按下............................................................. 07-25 05:58:11.484 12111-12111/com.example.androidtest I/EventTest: MainActivity 0 dispatchTouchEvent 07-25 05:58:11.484 12111-12111/com.example.androidtest I/EventTest: CustomRelativeLayout 1 dispatchTouchEvent 07-25 05:58:11.484 12111-12111/com.example.androidtest I/EventTest: CustomRelativeLayout 1 onIntereptTouchcEvent 07-25 05:58:11.484 12111-12111/com.example.androidtest I/EventTest: CustomRelativeLayout 1 onTouchEvent 07-25 05:58:11.573 12111-12111/com.example.androidtest I/EventTest: MainActivity 0 Event:抬起............................................................. 07-25 05:58:11.573 12111-12111/com.example.androidtest I/EventTest: MainActivity 0 dispatchTouchEvent 07-25 05:58:11.573 12111-12111/com.example.androidtest I/EventTest: CustomRelativeLayout 1 dispatchTouchEvent 07-25 05:58:11.573 12111-12111/com.example.androidtest I/EventTest: CustomRelativeLayout 1 onTouchEvent可以看到,后续的事件RelativeLayout也能接收到了。OK,现在demo1变种,假设在事件传递过程中,在外层的ViewGroup的dispatchTouchEvent返回值改为True,会起到***************************************
分割线 demo5
***************************************
onInterceptTouchEvent的效果吗,答案是:不会。TextView 的分发方法@Override public boolean dispatchTouchEvent(MotionEvent event) { Log.i(Constants.tag,tag+level+" dispatchTouchEvent "); boolean superReturn = super.dispatchTouchEvent(event); return true; }外层RelativeLayout的分发方法@Override public boolean dispatchTouchEvent(MotionEvent ev) { Log.i(Constants.tag,tag+level+" dispatchTouchEvent "); boolean superReturn = super.dispatchTouchEvent(ev); return true; }同时给予TextView@Override public boolean dispatchTouchEvent(MotionEvent event) { Log.i(Constants.tag,tag+level+" dispatchTouchEvent "); boolean superReturn = super.dispatchTouchEvent(event); return true; }7-25 06:08:14.391 12901-12901/com.example.androidtest I/EventTest: MainActivity 0 Event:按下.............................................................
07-25 06:08:14.392 12901-12901/com.example.androidtest I/EventTest: MainActivity 0 dispatchTouchEvent
07-25 06:08:14.392 12901-12901/com.example.androidtest I/EventTest: CustomRelativeLayout 1 dispatchTouchEvent
07-25 06:08:14.392 12901-12901/com.example.androidtest I/EventTest: CustomRelativeLayout 1 onIntereptTouchcEvent
07-25 06:08:14.392 12901-12901/com.example.androidtest I/EventTest: CustomTextView 3 dispatchTouchEvent
07-25 06:08:14.392 12901-12901/com.example.androidtest I/EventTest: CustomTextView 3 onTouchEvent
07-25 06:08:14.469 12901-12901/com.example.androidtest I/EventTest: MainActivity 0 Event:抬起.............................................................
07-25 06:08:14.469 12901-12901/com.example.androidtest I/EventTest: MainActivity 0 dispatchTouchEvent
07-25 06:08:14.470 12901-12901/com.example.androidtest I/EventTest: CustomRelativeLayout 1 dispatchTouchEvent
07-25 06:08:14.470 12901-12901/com.example.androidtest I/EventTest: CustomRelativeLayout 1 onIntereptTouchcEvent
07-25 06:08:14.470 12901-12901/com.example.androidtest I/EventTest: CustomTextView 3 dispatchTouchEvent
07-25 06:08:14.470 12901-12901/com.example.androidtest I/EventTest: CustomTextView 3 onTouchEvent可以看出,最终还是TextView获取了处理事件的权限。也就是说,作为父节点的View,如果你想比子View优先处理事件,那么你就要通过onInterceptTouchEvent的返回值来控制。通过dispatchTouchEvent方法的返回值来控制是无效的。***************************************
分割线 demo6
***************************************
仍然是第一个例子的变种,
假设一个事件序列向下传递,如果到最终的View没有去处理,在事件返回的过程中,我可以获取处理View的权限吗,答案是可以
我们通过第一个例子知道,在事件返回的过程中,一直调用的是onTouchEvent方法,
我们改写RelativeLayout的onTouchEvent方法
@Override public boolean onTouchEvent(MotionEvent event) { Log.i(Constants.tag,tag+level+" onTouchEvent "); boolean superReturn = super.onTouchEvent(event); return true; }07-25 06:15:24.820 13160-13160/com.example.androidtest I/EventTest: MainActivity 0 Event:按下.............................................................
07-25 06:15:24.821 13160-13160/com.example.androidtest I/EventTest: MainActivity 0 dispatchTouchEvent
07-25 06:15:24.821 13160-13160/com.example.androidtest I/EventTest: CustomRelativeLayout 1 dispatchTouchEvent
07-25 06:15:24.821 13160-13160/com.example.androidtest I/EventTest: CustomRelativeLayout 1 onIntereptTouchcEvent
07-25 06:15:24.821 13160-13160/com.example.androidtest I/EventTest: CustomTextView 3 dispatchTouchEvent
07-25 06:15:24.821 13160-13160/com.example.androidtest I/EventTest: CustomTextView 3 onTouchEvent
07-25 06:15:24.821 13160-13160/com.example.androidtest I/EventTest: CustomRelativeLayout 1 onTouchEvent
07-25 06:15:24.884 13160-13160/com.example.androidtest I/EventTest: MainActivity 0 Event:抬起.............................................................
07-25 06:15:24.884 13160-13160/com.example.androidtest I/EventTest: MainActivity 0 dispatchTouchEvent
07-25 06:15:24.884 13160-13160/com.example.androidtest I/EventTest: CustomRelativeLayout 1 dispatchTouchEvent
07-25 06:15:24.884 13160-13160/com.example.androidtest I/EventTest: CustomRelativeLayout 1 onTouchEvent
可以看到,在事件最终传递到TextView之后,没有人拦截,也没有人处理,那么,在事件回传的过程中,RelativeLayout的onTouchEvent方法决定去处理
这个事件了。
然后,当抬起事件来临的时候,这个事件就给了RelativeLayout,没有再向下传给TextView.
也就是说按下的时候,这个事件已经找准了要处理自己的View,那就是RelativeLayout,那么,当抬起的时候,自然没必要把事件给别人了,而是传给了RelativeLayout就好了。