android View 和 ViewGroup 事件分发机制

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中的主要还有DOWNMOVEUP三个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;
}

一图胜千言,可以拿着流程图去对比一下源码会有更好的效果哦:

这里写图片描述

发布了46 篇原创文章 · 获赞 62 · 访问量 30万+

猜你喜欢

转载自blog.csdn.net/qq_27512671/article/details/80090894