最近在看《Android高级进阶》,其中对事件的传递机制讲述的很清楚,以此文章作为读书笔记记录。
事件传递的三个阶段
1.事件的分发:
dispatchTouchEvent方法:决定是直接消费这个事件还是将事件继续分发给子视图。
public boolean dispatchTouchEvent(MotionEvent event)
方法返回值:
返回值 | 含义 |
---|---|
true | 事件被当前视图消费掉,不再继续分发事件 |
super.dispatchTouchEvent或false | 继续分发该事件 |
2.事件的拦截:
onInterceptTouchEvent方法:只在ViewGroup及其子类中存在,表示对事件进行拦截。
public boolean onInterceptTouchEvent(MotionEvent event)
方法返回值:
返回值 | 含义 |
---|---|
true | 拦截这个事件,不继续分发给子视图,同时交由自身的onTouchEvent方法进行消费 |
super.onInterceptTouchEvent或false | 不对事件进行拦截,需要继续传递给子视图 |
3.事件的消费:
onTouchEvent方法:表示对事件的消费。
public boolean onTouchEvent(MotionEvent event)
方法返回值:
返回值 | 含义 |
---|---|
true | 当前视图可以处理对应的事件,事件不会向上传递给父视图 |
false | 当前视图不处理这个事件,事件会被传递给父视图的onTouchEvent方法进行处理 |
4.总结:
对象 | 对象拥有的方法 |
---|---|
View和Activity | dispatchTouchEvent,onTouchEvent |
ViewGroup | dispatchTouchEvent,onInterceptTouchEvent,onTouchEvent |
View的事件传递机制
定义一个继承TextView的类MyTextView,定义一个MainActivitiy展示MyTextView,为MyTextView设置onClick和onTouch监听,ACTION_DOEN事件的处理流程如下所示:
总结:
1.触摸事件的传递流程是从diapatchTouchEvent开始的,如果不进行人为干预也就是默认返回父类的同名函数,则事件将会依照嵌套层次从外层向内层传递,到达最内层的view时,由它的onTouchEvent方法处理,该方法如果能够消费该事件,则返回ture,如果处理不力,则返回false,这时事件会重新向外层传递,并由外层View的onTouchEvent方法进行处理,以此类推。
2.如果事件在向内层传递过程中由于人为干预,事件处理函数返回true,则会导致事件提前被消费掉,内层View将不会收到这个事件。
3.View控件的事件触发顺序是先执行onTouch方法,在最后才执行onClick方法(因为查看源码可知dispatchTouchEvent方法->onTouch->onTouchEvent->performClick里面执行onclick)。如果onTouch返回true,则事件不会继续传递,最后也不会调用onClick方法;如果onTouch返回false,则事件继续传递。
ViewGroup的事件传递机制
自定义一个ViewGroup,继承RelativeLayout为MyRelativeLayout,将Layout作为MyTextView的容器,事件流程如下图所示:
总结:
1.触摸事件的传递顺序是由Activity到ViewGroup,再由ViewGroup递归传递给它的子View。
2.ViewGroup通过onInterceptTouchEvent方法对事件进行拦截,如果该方法返回ture,则事件不会传递给子VIew,如果返回false或者superInterceptTouchEvent,则事件会传递给子View。
3.在子View中对事件进行消费后,ViewGroup将接收不到任何事件。