ViewGroup的事件分发机制
大体流程为:
ViewGroup的dispatchTouchEvent
-> ViewGroup的onInterceptTouchEvent
-> 子View的dispatchTouchEvent
->子View的onTouchEvent
1. ViewGroup.dispatchTouchEvent 事件拦截
2. ViewGroup.onInterceptTouchEvent 事件处理
3. View.dispatchTouchEvent 事件消费
总结:从最外层向内传递(如果没有拦截的话),从最里层向外消费(如果没有return ture的话)
View的事件分发机制
其实就三个方法:
1. View.dispatchTouchEvent()
↓
2. View.mOnTouchListener.onTouch()
↓
3. View.onTouchEvent()
↓
如果View.mOnTouchListener.onTouch()
返回了ture表示事件已经被消费了,View.onTouchEvent()
将不会被调用。
如果View.mOnTouchListener.onTouch()
返回了false则事件还会继续传递给View.onTouchEvent()
。
如果View.onTouchEvent()
返回了ture表示事件已经被消费了,结束。
如果View.onTouchEvent()
返回了false则还会调用mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
另外还有一点,在OnTouchEvent
中的主要还有DOWN
、MOVE
、UP
三个Action:
Down中:115ms内没有触发UP,此时标记位为PREPRESSED
,这个时间内不会触发OnClick(),当超过了这个时间,则将标记为PREPRESSED清除,并改为PRESSED
MOVE中:主要检测用户是否划出控件,115内划出直接移除mPendingCheckForTap
,115后划出,将移除PRESSED标识
UP中:115内,此时标志位PREPRESSED
总结为就是:
UP-Down=time;
time < 115ms: PREPRESSED
状态
115ms < time < 5ooms: 执行onClick()
回调
500ms < time检查是否设置了OnLongClickListerner
如果有则会调用boolean onLongClick(View v);
,如果没有或者onLongClick()
返回了false,则依然还会调用onClick()
dispatchTouchEvent源码:
//已经省略部分源码
public boolean dispatchTouchEvent(MotionEvent event) {
//mOnTouchListener不为空的话,优先给mOnTouchListener处理
if (mOnTouchListener != null && mOnTouchListener.onTouch(this, event)) {
result = true;
}
//mOnTouchListener如果onTouch处理完返回false
//则继续交给onTouchEvent()处理
if (!result && onTouchEvent(event)) {
result = true;
}
if(!result){
onUnhandledEvent(event, 0);
}
return result;
}
一图胜千言,可以拿着流程图去对比一下源码会有更好的效果哦: