Android事件分发的详解

当用户点击屏幕时,将产生的触摸事件分为以下四种

ACTION_DOWN刚刚触摸屏幕
ACTION_MOVE 手指在屏幕滑动

ACTION_UP:手指离开屏幕

ACTION_CANCEL 非人为因素的取消

事件分发的对象有

Activity:控件的生命周期和处理事件

ViewGroup: 一组View的集合

View所有UI组件的基类

主要涉及到的方法

dispahchTouchEvent 用来事件分发

onIntercepterTouchEvent 判断事件是否拦截(这个只有ViewGroup里有)

onTouchEvent处理点击事件

当一个事件发和的时候是由Activity来分发的  所以走的是Activity的dispatchTouchEvent方法,而整个屏幕又是一个PhoneWindow,也就是由PhoneWindow来分发的,PhoneWindow里面则由窗口顶层布局DecorView来执行,DecorView是一个FragLayout子类,所以最终来还走到ViewGroup的dispatchTouchEvent, 如果Activity里的dispatchTouchEvent返回false,就会调用Activity.onTouchEvent方法,onTouchEvent这个方法会对触摸边界进行判断,返回true则是这个界面销毁了,false则是这个事件消费了,到此结束.

上面小结一下: 如果一个触摸事件没有任何View消费的话,最后就是走到Activity.onTouchEvent中

ViewGroup dispathTouchEvent()

一个事件的开始是由ACTION_DOWN开始的,在这里会做一系列初始化,在ACTION_DOWN的时候,里面有个标记

FLAG_DISALLOW_INTERCEPT 的判断,而这个值会由requestDisallowInterceptTouchEvent来赋值,这个值会直接影响到是否会将走到onInceptetTouchEvent里面,但这个值不会影响ACTION_DOWN事件,只会影响其以外的触摸事件.

如果一切正常,说会走到onInterceptTouchEvent这个事件拦截里面,默认返回的是false,为不拦截.

再如果onInterceptTouchEvent返回false的话,则在ACTION_DOWN触摸事件里会倒序遍历整个子View,里面检测View是否可见,是否在执行动画,是否在这个View的范围内.遍历完后,如果还是没有发再这个View,,则最终走的就是ViewGroup的父类的dispathcTouchEvent方法中,也就是VIew的dispatchTouchEvent,然后就是onTouchEvent方法

如果找到了这个View,就会处理其它的触摸事件,比如MOVE,UP等,就会走到子View的dispatchTouchEvent

 

View.onTouchEvent

在View的dispatchTouchEvent方法中,如果我们设置了touchEventListener的话就会为一个ListenerInfo附值,不为空,则先执行onTouch方法,如果onTouch方法返回true,则代码这个事件被消费,没有下一步,如果返回false或都没有setOnTouchListener的话才会到onTouchEvent(...)方法里

这里面主要是对长按和点击事件做处理,时面有个500ms的延时任务,如果在up的时候超过500则是长按,长按事件如果返回true则onClick不响应,如果小于500则反之,将长按flag设置为fase 并移除了长按事件,.就会响应onClick点击事件,当然需要setOnclickListener

如果设置了长按事件并返回了true则不会执行点击事件,如果长按事件返回fase则点击事件也会执行.

 

总结: 点击事件触发--->根View的ViewGroup-->调用dispatchTouchEvent-->调用onInterceptTouchEvent-->

          是否拦截  是-->调用自己的onTouchEvent-->是否消费  --- 否--->Activity onTouchEvent结束

                                                                                                       --- 是--->事件消费结束

                           否-->子ViewGroup-->调用dispatchTouchEvent-->调用onInterceptTouchEvent-->是否拦截  是:调用自己的onTouchEvent

                                                                                                                                                                                        否:View-->调用View的dispatchTouchEvent--->View没有onInterceptTouchEvent方法直接到--->自己的onTouchEvent

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章