前提知识
Touch事件的分发和消费机制
Note: 如果onTouchEvent中返回true, 则表示消费了这个事件,这个事件就不会再传递下去了,如果子View return true, 那么父ViewGroup的onTouchEvent就不会执行。
原因分析
ScrollView的onInterceptTouchEvent源码:
public boolean onInterceptTouchEvent(MotionEvent ev) {
/**
* 从这里可以看出当前Event为MOVE,且mIsBeingDragged(滑动)为true时,就拦截
* Event. 记住是MOVE.
*/
final int action = ev.getAction();
if ((action == MotionEvent.ACTION_MOVE) && (mIsBeingDragged)) {
return true;
}
//省略代码
switch (action & MotionEvent.ACTION_MASK) {
//省略代码
case MotionEvent.ACTION_DOWN: {
final int y = (int) ev.getY();
if (!inChild((int) ev.getX(), (int) y)) {
mIsBeingDragged = false;
recycleVelocityTracker();
break;
}
/*
* Remember location of down touch.
* ACTION_DOWN always refers to pointer index 0.
*/
mLastMotionY = y;
mActivePointerId = ev.getPointerId(0);
initOrResetVelocityTracker();
mVelocityTracker.addMovement(ev);
/*
* If being flinged and user touches the screen, initiate drag;
* otherwise don't. mScroller.isFinished should be false when
* being flinged.
*/
mIsBeingDragged = !mScroller.isFinished();
//从这里可以看出在DOWN事件时,是不拦截DOWN事件的,此DOWN事件会传递
//到子View中,这样子View就可调用onTouchEvent,不过此时是DOWN事件
if (mIsBeingDragged && mScrollStrictSpan == null) {
mScrollStrictSpan = StrictMode.enterCriticalSpan("ScrollView-scroll");
}
//初始化Scroll
startNestedScroll(SCROLL_AXIS_VERTICAL);
break;
}
//省略代码<