ViewGroup事件传递
同一事件序列指从手指接触屏幕到手指离开屏幕
MotionEvent ---> Activity ---> Window ---> DecorView
获取方法Activity.getWindow().getDecorView()
Activity#dispatchTouchEvent
|
|
|
public boolean dispatchTouchEvent(MotionEvent ev){
......
if(getWindow().superDispatchTouchEvent(ev)){
return true;
}
return onTouchEvent(ev);
}
Activity调用附属的Window分发 false---> 没人处理,调用Activity自身onTouchEvent
|
|
|
PhoneWindow#superDispatchTouchEvent
|
|
|
public boolean superDispatchTouchEvent(MotionEvent event){
return mDecor.superDispatchTouchEvent(event);
}
Window唯一实现类PhoneWindow
PhoneWindow将事件传递给DecorView
|
|
|
DecorView
|
|
|
((ViewGroup)getWindow().getDecorView().findViewById(android.R.id.content)).getChildAt(0);
获取我们通过setContentView设置的View
|
|
|
ViewGroup#dispatchTouchEvent
|
|
|
// 拦截状态
final boolean intercepted;
if(actionMasked == MotionEvent.ACTION_DOWN || mFirstTouchTarget != null){
final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT)!=0;
if(!disallowIntercept){
intercepted = onInterceptTouchEvent(ev);
ev.setAction(action);
}else{
intercepted = false;
}
} else {
intercepted = true;
}
说明:
dispatchTouchEvent $ ACTION_DOWN --> onInterceptTouchEvent()
dispatchTouchEvent $ ACTION_MOVE ACTION_UP --> ACTION_DOWN事件中当前ViewGroup不拦截 --> onInterceptTouchEvent()
1、ACTION_DOWN --> onInterceptTouchEvent(ev) --> intercepted==true 当前ViewGroup拦截 --> mFirstTouchTarget==null
--> ACTION_MOVE、ACTION_UP --> 由于条件不成立,导致无法再调用onInterceptTouchEvent()
2、mFirstTouchTarget有子元素成功处理事件被赋值
|
|
|
ACTION_DOWN
ACTION_DOWN时始终是如下值:
处理事件的子View mFirstTouchTarget==null 还未有子View处理事件,肯定为null
子View请求拦截 disallowIntercept=false ACTION_DOWN事件时会重置该值,所以肯定是false
|
|
|
ViewGroup#onInterceptTouchEvent()
| |
| |
| |
intercepted==false当前ViewGroup不拦截 intercepted==true当前ViewGroup拦截
mFirstTouchTarget != null mFirstTouchTarget==null
ACTION_MOVE ACTION_MOVE
| |
| |
| |
disallowIntercept==true onInterceptTouchEvent()方法不再调用,直接调用当前ViewGroup的onTouchEvent()
请求不拦截 --> 调用子View相关方法
disallowIntercept==false
请求拦截 --> onInterceptTouchEvent() --> intercepted
|
|
|
不拦截事件时分发给子View
总结: 1、ACTION_DOWN事件时,如果拦截了,那么不再调用onInterceptTouchEvent()
2、子View设置的请求是否拦截,只有在非ACTION_DOWN事件时生效
View点击事件的处理
这里没有事件拦截,在dispatchTouchEvent()中判断是否设置OnTouchListener
OnTouchListener#onTouch
| |
| |
| |
false onTouchEvent true onTouchEvent不再调用
|
|
|
设置了OnClickListener则调用