目录
一个事件首先来到Activity ,再到window(PhoneWinodw),再到DocorView,通过setContentView设置的view是DocorView的子View。
Activity处理事件
点击事件产生后,Activity会分发给window,继而分发给子View,如果被子View没有处理点击事件,会调用Activity的onTouchEvent()方法。
注意:Activity本身没有 onIntercetpTouchEvent方法,不难理解,Activity是分发事件的根,不需要拦截,只有viewGroup才需要拦截(view也没有拦截方法,也不需要拦截)。
ViewGroup处理事件
伪代码如下:
理解:
1.事件传递到ViewGroup时,dispatchTouchEvent方法会被调用。如果这个ViewGroup的onInterceptTouchEvent方法返回true,则表示它要拦截事件,事件就会交给当前ViewGroup的onTouchEvent方法处理。
2. 如果当前ViewGroup的onInterceptTouchEvent返回false,即不拦截事件,则会调用子元素的dispatchTouchEvent方法,这样就把事件传递给了子元素。
3. 如果子元素没有消耗事件,也就是子元素的dispatchTouchEvent方法返回false,那事件会由当前ViewGroup自己处理,当前ViewGroup的onTouchEvent会被调用。如果当前ViewGroup的dispatchTouchEvent方法也返回false,最后就会一层层往上,如果事件一直没有被消耗,那么最后Activity的onTouchEvent方法会被调用
注意:ViewGroup在ACTION_DOWN事件时开始拦截,
view处理事件
view没有onInterceptTouchEvent方法,因为已经是事件末端了,没有子 view了,不需要再拦截。
代码块
public boolean dispatchTouchEvent(MotionEvent event) {
。。。
if (onFilterTouchEventForSecurity(event)) {
if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
result = true;
}
//noinspection SimplifiableIfStatement
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnTouchListener != null
&& (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnTouchListener.onTouch(this, event)) {
result = true;
} if (!result && onTouchEvent(event)) { result = true; }
}
。。。
return result;
}
理解:
1.事件传递到view后,会首先判断是否设置了OnTouchListener,如果OnTouchListener的onTouch返回true,则不会调用onTouchEvent
2.事件传递到onTouchEvent后,只要view的Clickable和long_clickable有一个为true,那么就会消耗这个事件,onTouchEvent会返回true
这种情况下,当ACTION_UP事件后,会触发performClick方法,如果view设置了OnClickListener,那么performClick会调用onClick方法。
总结下来,优先级:OnTouchListener > onTouchEvent > OnClickListener