ViewGroup事件传递

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则调用
posted @ 2016-08-01 16:51  轻云沉峰  阅读(188)  评论(0)    收藏  举报