事件分发源码分析
事件最先传递个当前的Activity,由Activity的dispatchTouchEvent来进行时间派发
具体的工作由Activity内部的Window来完成的,Window会将事件传递给decorview,
decorview就是当前视图的底层容器
dispatchTouchEvent返回值为true 表示事件被他或者她的子view给消化了
如果返回false表示没有任何的view消化了 就不能设置target了 那么
public void dispatchTouchEvent(MotionEvent event){
.....
if(getWindow().superDispatchTouchEvent(event)){
return true;
}
return onTouchEvent(ev);
}
事件开始交给Activity所附属的Window进行分发 如果返回true 那么整个事件循环就结
束了,返回false意味着时间没有任何控件进行处理 ,那么就由Activity的
onTouchEvent就会被调用执行
WindowPhone是Window的实现类,那么他也实现了superDispatchTouchEvent()的抽象方
法,WindowPhone是Window唯一的实现类
而在PhoneWindow中的PhoneWindow的superDispatchTouchEvent()实现是
public void superDispatchTouchEvent(MotionEvent event){
mDecor.superDispatchTouchEvent(event);
}
那么PhoneWindow将事件直接传递给了DecorView
顶级View DecorView的分发是这样的
事件传达到ViewGroup的之后,会调用viewGroup的dispatchtouchEvent方法,
1、如果顶级ViewGroup的拦截事件即onInterceptTouchEvent的返回为true,这由事件
ViewGroup处理
如果此时viewGroup设置了setOnTouchListener,则调用他的回调onTouch,同
时屏蔽了onTouchEvent
如果没有设置setOnTouchListener,那么onTouchEvent会被调用
dispatch里面 会检测是否设置了FLAG_DISALLOW_INTERCEPT,而这个标识位是通过子View的requestDisallowInterceptTouchEvent方法调用的,这样就不会调用onInterceptTouchEvent方法了
但是对ACTION_DOWN是不起作用的,因为每次ACTION_DOWN的时候都会调用restTouchState 去重置状态
requestDisallowInterceptTouchEvent不会影响ViewGroup对ACTION_DOWN的处理
当ViewGrop决定拦截事件后,后续的时间默认交给他自己的onTouch 并且不会再调用onInterceptTouchEvent方法
如果想提前处理所有的时间,请选择使用dispatchTouchEvent方法,因为他每次都会被调用
另外一个点FLAG_DISALLOW_INTERCEPT这个对于我们解决滑动冲突提供了一个解决方案
如果ViewGroup本身不拦截事件,也就是不用自己onTouchEvent处理
那么会继续走下去,分发给他自己的子View进行处理
在源码中 回去遍历所有的子View,然后查看点击事件的坐标是否在某个子View上面以及判断动画运动的点是否在触摸点位置
如果满足这两个条件那么就调用 dispatchTransformTouchEvent,实际上就是调用子View的dispatchTouchEvent方法
如果有符合条件的,就调用addTouchTarget方法,在这里面mFirstTouchTarget被赋值了刚才的子view
如果子View的dispatchTouchEvent返回为true,那么就把mFirstTouchTarget赋值了,这样以后viewGroup就不会拦截了
View的dispatchTouchEvent方法比较简单
首先会判断有没有设置setOnTouchListener,如果有就调用OnTouchListener中的onTouch方法,如果onTouch反悔了true,那么onTouchEvent就不会被调用,因为OnTouchListener的优先级高于onTouchEvent
在onTouchEvent里面,只要View的CLICKABLE和LONG_CLICKABLE有一个为true,那么就会消耗这个时间,即onTouchEvent方法返回true,不管他是不是DISABLE状态。
在ACTION_UP时间触发时,会触发performClick方法,如果设置了setOnClickListener,那么performClick会调用onClick
如果没有符合条件的子View,那么这个点击事件就调用了super.dispatchTouchEvent交给他的父类View进行事件的处理
事件最先传递个当前的Activity,由Activity的dispatchTouchEvent来进行时间派发
具体的工作由Activity内部的Window来完成的,Window会将事件传递给decorview,
decorview就是当前视图的底层容器
dispatchTouchEvent返回值为true 表示事件被他或者她的子view给消化了
如果返回false表示没有任何的view消化了 就不能设置target了 那么
public void dispatchTouchEvent(MotionEvent event){
.....
if(getWindow().superDispatchTouchEvent(event)){
return true;
}
return onTouchEvent(ev);
}
事件开始交给Activity所附属的Window进行分发 如果返回true 那么整个事件循环就结
束了,返回false意味着时间没有任何控件进行处理 ,那么就由Activity的
onTouchEvent就会被调用执行
WindowPhone是Window的实现类,那么他也实现了superDispatchTouchEvent()的抽象方
法,WindowPhone是Window唯一的实现类
而在PhoneWindow中的PhoneWindow的superDispatchTouchEvent()实现是
public void superDispatchTouchEvent(MotionEvent event){
mDecor.superDispatchTouchEvent(event);
}
那么PhoneWindow将事件直接传递给了DecorView
顶级View DecorView的分发是这样的
事件传达到ViewGroup的之后,会调用viewGroup的dispatchtouchEvent方法,
1、如果顶级ViewGroup的拦截事件即onInterceptTouchEvent的返回为true,这由事件
ViewGroup处理
如果此时viewGroup设置了setOnTouchListener,则调用他的回调onTouch,同
时屏蔽了onTouchEvent
如果没有设置setOnTouchListener,那么onTouchEvent会被调用
dispatch里面 会检测是否设置了FLAG_DISALLOW_INTERCEPT,而这个标识位是通过子View的requestDisallowInterceptTouchEvent方法调用的,这样就不会调用onInterceptTouchEvent方法了
但是对ACTION_DOWN是不起作用的,因为每次ACTION_DOWN的时候都会调用restTouchState 去重置状态
requestDisallowInterceptTouchEvent不会影响ViewGroup对ACTION_DOWN的处理
当ViewGrop决定拦截事件后,后续的时间默认交给他自己的onTouch 并且不会再调用onInterceptTouchEvent方法
如果想提前处理所有的时间,请选择使用dispatchTouchEvent方法,因为他每次都会被调用
另外一个点FLAG_DISALLOW_INTERCEPT这个对于我们解决滑动冲突提供了一个解决方案
如果ViewGroup本身不拦截事件,也就是不用自己onTouchEvent处理
那么会继续走下去,分发给他自己的子View进行处理
在源码中 回去遍历所有的子View,然后查看点击事件的坐标是否在某个子View上面以及判断动画运动的点是否在触摸点位置
如果满足这两个条件那么就调用 dispatchTransformTouchEvent,实际上就是调用子View的dispatchTouchEvent方法
如果有符合条件的,就调用addTouchTarget方法,在这里面mFirstTouchTarget被赋值了刚才的子view
如果子View的dispatchTouchEvent返回为true,那么就把mFirstTouchTarget赋值了,这样以后viewGroup就不会拦截了
View的dispatchTouchEvent方法比较简单
首先会判断有没有设置setOnTouchListener,如果有就调用OnTouchListener中的onTouch方法,如果onTouch反悔了true,那么onTouchEvent就不会被调用,因为OnTouchListener的优先级高于onTouchEvent
在onTouchEvent里面,只要View的CLICKABLE和LONG_CLICKABLE有一个为true,那么就会消耗这个时间,即onTouchEvent方法返回true,不管他是不是DISABLE状态。
在ACTION_UP时间触发时,会触发performClick方法,如果设置了setOnClickListener,那么performClick会调用onClick
如果没有符合条件的子View,那么这个点击事件就调用了super.dispatchTouchEvent交给他的父类View进行事件的处理