View学习之解决滑动冲突

一、常见的滑动冲突场景

  1.外部滑动方向和内部滑动的方向不一致

  View学习之解决滑动冲突

        图一

  2.外部滑动方向和内部滑动方向一致

  View学习之解决滑动冲突

             图二

  3.外部滑动方向和内部滑动的方向不一致和外部滑动方向和内部滑动方向一致

   View学习之解决滑动冲突

                  图三

二、解决方法

  1.外部拦截法 : 外部和内部的滑动方向不一样也就是说只要判断当前dy和dx的大小,如果dy>dx,那么当前就是竖直滑动,否则就是水平滑动

View学习之解决滑动冲突

父view:

public boolean onInterceptTouchEvent(MotionEvent ev) {
final float x = ev.getX();
final float y = ev.getY();

final int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
mDownPosX = x;
mDownPosY = y;

break;
case MotionEvent.ACTION_MOVE:
final float deltaX = Math.abs(x - mDownPosX);
final float deltaY = Math.abs(y - mDownPosY);
// 这里是够拦截的判断依据是左右滑动,读者可根据自己的逻辑进行是否拦截
if (deltaX > deltaY) {
return false;
}
}

return super.onInterceptTouchEvent(ev);
}

  



  2.内部拦截法 : 指父容器不拦截任何事件,所有的事件都传递给子元素,如果子元素需要此事件就直接消耗掉,否则就交给父容器去处理,这种方法和Android中的事件分发机制不一致,
          需要配合requestDisallowInterceptTouchEvent方法才能正常工作

子view :
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
int x = (int) ev.getRawX();
int y = (int) ev.getRawY();
int dealtX = 0;
int dealtY = 0;

switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
dealtX = 0;
dealtY = 0;
// 保证父view不做拦截
getParent().requestDisallowInterceptTouchEvent(true);
break;
case MotionEvent.ACTION_MOVE:
dealtX += Math.abs(x - lastX);
dealtY += Math.abs(y - lastY);
Log.i(TAG, "dealtX:=" + dealtX);
Log.i(TAG, "dealtY:=" + dealtY);
// 这里是够拦截的判断依据是左右滑动,读者可根据自己的逻辑进行是否拦截
if (dealtX >= dealtY) {
getParent().requestDisallowInterceptTouchEvent(true);
} else {
        //保证父view做拦截

getParent().requestDisallowInterceptTouchEvent(false);
}
lastX = x;
lastY = y;
break;
case MotionEvent.ACTION_CANCEL:
break;
case MotionEvent.ACTION_UP:
break;

}
return super.dispatchTouchEvent(ev);
}


参考链接:https://blog.csdn.net/gdutxiaoxu/article/details/52939127