Android滑动冲突的场景及解决方案

日志最终我们可以看到,在绿色处,HorizontalScrollViewChild是有消费MOVE事件的,那之前不是讲错了吗?既然HorizontalScrollViewChild有消费MOVE事件,为啥ScrollViewParent还能滑动呢?因为在刚开始滑动的时候,滑动的距离还太小,因此ScrollViewParent的onInterceptTouchEvent还没有拦截这个事件,所以HorizontalScrollViewChild可以消费到MOVE事件。但后面一旦垂直滑动了一定距离,MOVE事件就会直接被ScrollViewParent消费掉,从而实现竖直滑动。我们可以看ScrollViewParent的源码佐证一下:

final int y = (int) ev.getY(pointerIndex);
final int yDiff = Math.abs(y - mLastMotionY);
if (yDiff > mTouchSlop && (getNestedScrollAxes() & SCROLL_AXIS_VERTICAL) == 0) {
    mIsBeingDragged = true;
    mLastMotionY = y;
    initVelocityTrackerIfNotExists();
    mVelocityTracker.addMovement(ev);
    mNestedYOffset = 0;
    if (mScrollStrictSpan == null) {
        mScrollStrictSpan = StrictMode.enterCriticalSpan("ScrollView-scroll");
    }
    final ViewParent parent = getParent();
    if (parent != null) {
        parent.requestDisallowInterceptTouchEvent(true);
    }
}

可以看到第3行,只有当yDiff大于一定滑动距离即mTouchSlop时,才会被认定为在垂直方向上滑动,将mIsBeingDragged设置为true。若我们水平滑动HorizontalScrollViewChild,可以断定,因为yDiff是没有超过mTouchSlop的,所以HorizontalScrollViewChild就可以正常滑动了。观察日志:
可以看到,水平滑动HorizontalScrollViewChild时,ScrollViewParent没有在onInterceptTouchEvent拦截MOVE事件,MOVE事件得以顺利被HorizontalScrollViewChild消费,实现水平滑动。
那看样子,两个ScrollView并不冲突呀,他们都已经写好内部逻辑了。其实不然。假设我们现在手指放在HorizontalScrollViewChild区域中,滑斜上方45角度向左/向右滑动,这时候我们就会发现,有时候我们滑动的是HorizontalScrollViewChild,有时候我们滑动的却是ScrollViewParent,这就是典型的不同方向上的滑动冲突。

通用解决方案

一般情况下,我们有“内部拦截法”和“外部拦截法”两种解决方案去处理常见的滑动冲突。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值