View事件分发:
dispatchTouchEvent
设置了onTouchListener并且view是可点击状态并且onTouchListener的onTouch函数返回true,则直接返回true,任一条件不满足就继续调用自身的onTouchEvent函数
onTouchEvent
如果设置了不可点击,直接返回
如果是ACTION_DOWN事件
如果是鼠标右键点击,弹上下文菜单(为了兼容pc用户的使用习惯)
如果view是在一个可滑动的容器里,post个runnable判断延时100毫秒再去判断是不是长按事件,100毫秒内如果是滑动这个runnable会被remove
如果不在可滑动容器里,设置已按下,执行一些界面刷新,post个Runnable查看是不是个长按事件
如果是ACTION_MOVE事件
如果move到view外了,就remove掉所有的事件检查Runnable,退出按下状态
如果是ACTION_UP事件
请求焦点,如果还没有执行是否为长按的判断就remove掉那个长按检查Runnable,然后执行performclick,然后取消按下状态
点击事件分发机制:
Activity.dispatchTouchEvent
先让用户界面窗口处理 getWindow().superDispatchTouchEvent(),没处理再走自己的onTouchEvent
getWindow().superDispatchTouchEvent 内容是调DecorView的superDispatchTouchEvent,DecorView的 superDispatchTouchEvent内容就是调ViewGroup的dispatchTouchEvent
ViewGroup.dispatchTouchEvent
如果收到的是ACTION_DOWN事件,首先清空之前的事件列表,因为ACTION_DOWN是一个事件的开始;然后调用onInterceptTouchEvent查看是否要拦截该事件,如果拦截了,就交给父类也就是View的dispatchTouchEvent处理,如果没有拦截,就遍历所有子View,如果点击的这个点在View的范围内,就调用它的dispatchTouchEvent进行事件分发,如果这个事件被某个view消化了,就把这个记为TouchTarget;后续来了MOVE和UP事件,就直接拿touchtarget的dispatchTouchEvent处理,特殊的如果down没拦截,move或up拦截了,把这个事件变成cancel交给touchtarget处理
滑动事件
ScrollView重写了onInterceptTouchEvent当move的距离大于一定范围就认为是滑动交给自己View的dispatchTouchEvent处理