1、Activity对点击事件的分发过程
点击事件由MotionEvent表示,由Activity的dispatchTouchEvent进行shij事件派发,
具体的工作步骤:
Activity内部的Window(实现类PhoneWindow)->DecorView->到达顶级View(根View)
2、顶级View对点击事件的分发过程
具体逻辑:如果顶级ViewGroup拦截事件即onInterceptTouchEvent返回true,则事件由ViewGroup处理,这时如果ViewGroup的mOnTouchListener被设置,则onTouch会被调用,否则onTouchEvent会被调用。也就是说,如果都提供的话,onTouch会屏蔽掉onTouchEvent。在onTouchEvent中,如果设置了mOnClickListener,则onClick会被调用。如果顶级ViewGroup不拦截事件,事件会传递给它所在的点击事件链上的子View,这是子View的dispatchTouchEvent会被调用。到此为止,事件已经从ding顶级View传递给下一层View,接下来的传递过程和顶级View是一致的,如此循环,完成整个事件的分发。(摘自《Android开发艺术探索》P146)
(1)ViewGroup对点击事件的分发过程,主要实现在ViewGroup的dispatchTouchEvent方法中,具体源码及我的理解
//Check for interception.
final boolean intercepted;
if(actionMasked == MotionEvent.ACTION_DOWN || mFirstTouchTarget != null){
fianl boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
if(!disallowIntercept){
intercepted = onInterceptTouchEvent(ev);
ev.setAvtion(action);//restore action in case it was changed
}else{
intercepted = false;//不拦截,向下传递
}
}else{
intercepted = true;//拦截(不是DOWN操作,没有子View)
}
代码分段理解:
if(actionMasked == MotionEvent.ACTION_DOWN || mFirstTouchTarget != null){
mFirstTouchTarget != null:当ViewGroup不拦截事件并将事件交由子View处理时,此等式成立。
1)无论是否有DOWN操作,只要有子View;2)包含DOWN操作,无论是否有子View;3)包含DOWN操作,并且含有子View;是以上三种情况之一就进入for循环,否则直接拦截
fianl boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
若mGroupFlags中设置了FLAG_DISALLOW_INTERCEPT,此处disallowIntercept为true
if(!disallowIntercept){
intercepted = onInterceptTouchEvent(ev);
ev.setAvtion(action);//restore action in case it was changed
进入上述循环的操作原因是:包含DOWN操作,在DOWN操作中会重置FLAG_DISALLOW_INTERCEPT标记位,使得disallowIntercept为false。循环内部:调用onInterceptTouchEvent(ev);判断是否拦截。
else{
intercepted = false;//不拦截,向下传递
}
没进入for内部原因:在子View中设置了FLAG_DISALLOW_INTERCEPT标记位,disallowIntercept为true,进入else,不拦截。