1. DOWN 事件的流向
【关键点】
dispatchTouchEvent
、onTouchEvent
返回true
:事件就停止传递了(没有谁能再收到这个事件)。dispatchTouchEvent
返回false
:事件停止往子 View 传递和分发同时开始往父控件回溯,就像递归停止然后开始回溯。dispatchTouchEvent
、onTouchEvent
、onInterceptTouchEvent
返回super.xxxxxx()
:事件会依照 U 型路径走完整个事件。
2. MOVE 和 UP 事件的流向
2.1. dispatchTouchEvent 返回 true
则 ACTION_MOVE
和 ACTION_UP
的事件传到这个 View 后就不再往下传递了,并立即消费掉。
2.2. onTouchEvent 返回 true
则 ACTION_MOVE 和 ACTION_UP 的事件传到这个 View 后就不再往下传递了,并传给自己的 onTouchEvent 消费掉。
2.3. 总结
ACTION_DOWN
事件在哪个控件消费了(return true
), 那么ACTION_MOVE
和ACTION_UP
就会从上往下(通过dispatchTouchEvent
)做事件分发往下传,就只会传到这个控件,不会继续往下传。- 如果
ACTION_DOWN
事件是在dispatchTouchEvent
消费,那么事件到此为止停止传递。 - 如果
ACTION_DOWN
事件是在onTouchEvent
消费的,那么会把ACTION_MOVE
或ACTION_UP
事件传给该控件的onTouchEvent
处理并结束传递。
3. setOnTouchListener
public boolean dispatchTouchEvent(MotionEvent event) {
// ...
boolean result = false;
// ...
if (onFilterTouchEventForSecurity(event)) {
// ...
if (li != null && li.mOnTouchListener != null
&& (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnTouchListener.onTouch(this, event)) {
// 优先处理OnTouchListener
// 如果返回值是true,则不会再执行自身的onTouchEvent,并消费该事件
result = true;
}
// 转交给自己的onTouchEvent
if (!result && onTouchEvent(event)) {
result = true;
}
}
// ...
return result;
}
【结论】
- 未设置
OnTouchListener
,系统默认执行onTouchEvent(event)
方法。 - 设置了
OnTouchListener
,系统会先执行它,并根据其返回值再决定是否执行onTouchEvent(event)
。 - 看
OnTouchListener
的优先级比onTouchEvent
高。