View的事件体系
0. 事件的定义
- 首先这章集中在View 的事件体系,所以键盘事件(keyevent)就先不说了
- view的事件定义为motionevent,其中各个view,viewgroup分发的均是motionevent,只是各自的流程不一样,同时,gesturedetector 能监测的也是motionevent
点击事件的分发,其实就是将产生的一个motionevent(一下简称为event或事件)传递给一个具体的view被处理掉,传递过程即为事件的分发过程
1. 分发过程
- 首先说明一个东西 viewgroup 继承自view,但是事件的分发一定是从一个viewgroup开始的,如果不是,那就不用分发了,直接由view自己处理了
一段伪代码镇楼
public boolean dispatchTouchEvent(MotionEvent event) { boolean consumed = false; if(onInterceptTouchEvent(event)){ consumed = ontouchevent(event); }else{ for(int i=0;i< childcount,i++) { consumed = child.dispatchTouchEvent(MotionEvent event); if(consumed){ break; } } } return consumed; }
onInterceptTouchEvent(event) 这个方法是viewgroup特有的,用来判断事件是否是自己处理,需要自己处理,调用ontouchevent.这段代码的逻辑很清晰,就是该我处理的我处理,不该我处理的给儿子们处理.
给出一些结论更好的理解整个过程
- 同一个事件序列是指从手指接触屏幕那一刻起,到手指离开屏幕那一刻结束,在这个过程中所产生的一些列事件,这个事件序列以down事件开始,up事件结束,中间含有数量不定的move事件
- 正常情况下,一个事件只能被一个View拦截消耗,这一条原因可以参考(3),因为一旦某个元素拦截了此次事件,那么同一个事件的序列的所有事件都会直接交给它处理,因此同一个事件序列中的事件不能同时交给两个view处理
- 某个view一旦决定拦截事件,那么这个事件的所有序列都会交给它来处理(如果他能收到事件)
- 某个view一旦开始处理事件,如果它不能消耗掉down事件的话,那么这个事件序列的move和up事件将不会再交给他处理
- 如果view不消耗除down事件的其他事件,那么这个事件会消失,同时不会回调给父布局(因为这个事件序列的down,开始事件已经交给这个view处理了),最后的事件会交给activity处理。(这条不理解了)
- viewgroup默认不拦截任何事件
- view没有onInterceptTouchEvent(event),一旦有点击事件,交给ontouchevent处理
- view的ontouchevent默认返回true,除非是不可点击的。
st=>start: Activity
e=>end: END
op1=>operation: Window
op2=>operation: PhoneWindow
op3=>operation: DecoView
op4=>operation: contentviewgroup
op5=>operation: Viewgroups
op6=>operation: View
op7=>operation: ontouchevent
sub1=>subroutine: My Subroutine
cond1=>condition: onInterceptTouchEvent(event)
cond2=>condition: onTouchEvent(event)
st->op1->op2->op3->op4->op5->cond1
cond1(yes)->op7->e
cond1(no,right)->op6->cond2
cond2(yes)->e
cond2(no)->op5