- 要点
- 所谓事件分发,就是对MotionEvent一系列事件的分发,包括ACTION_DOWN、ACTION_MOVE、ACTION_UP
- 每次分发都是从ACTION_DOWN开始,到ACTION_UP为结束,过程是ACTION_MOVE.其中ACTION_DOWN、ACTION_UP只有一次,ACTION_MOVE多次
- 当一个事件产生后,传递过程遵循如下顺序:
- 相关方法:
- dispatchTouchEvent
- onInterceptTouchEvent
- onTouchEvent
- 触摸事件onTouch
- 点击事件onClick/onLongClick
- 整个时间是个责任链模式传递的.事件传递过程是由外向内的,即事件总是先传递给父元素,然后再由父元素分发给子View,子元素可以通过调用parentView.requestDisallowInterceptTouchEvent方法,来设置disallowIntercept=true,从而阻止父ViewGroup的onInterceptTouchEvent拦截操作,但是ACTION_DOWN事件除外
- 伪代码:
底层中断上报 -> Activity -> Window -> View
(即Activity -> Window -> PhoneWindow-> DecorView -> View)
public void dispatchTouchEvent(MotionEvent ev) {
boolean consume = false;
if (onInterceptTouchEvent(ev)) {
//根据触摸监听的返回值决定是否consume
if (mOnTouchListener != null && view是enable的) {
if (mOnTouchListener.onTouch(ev)) {
consume = true;
} else {
//在onTouchEvent方法中,如果设置了点击事件,则点击事件会被响应
consume = onTouchEvent(ev); //默认可点击或可长按则返回true
}
} else {
//在onTouchEvent方法中,如果设置了点击事件,则点击事件会被响应
consume = onTouchEvent(ev); //默认可点击或可长按则返回true
}
} else {
consume = child.dispatchTouchEvent(ev);
}
return consume;
}- 伪代码注意点:
- ViewGroup默认不拦截任何事件。ViewGroup的onInterceptTouchEvent方法默认返回false。
- View没有onInterceptTouchEvent方法,一旦有点击事件传递给它,那么它的onTouchEvent方法就会被调用。
- activity#dispatchTouchEvent是入口(实际上我们可以理解为DecorView#dispatchTouchEvent的才是入口,如果activity重写了dispatchTouchEvent,就会调用,否则会直接调用viewgroup#dispatchTouchEvent;
- activity#dispatchTouchEvent默认也会调用viewgroup#dispatchTouchEvent)
- 如果所有view都不处理,最后会交给activity#onTouchEvent
- 一张图概括上面的流程

- 疑问点:onInterceptTouchEvent的返回值,好像会根据view的类型,有所区别,具体问题具体分析吧...
相关连接:
- Android艺术探索
- gityuan.com/2015/09/19/…