自定义View 事件冲突

一、事件滑动

图片.png

图片.png

图片.png

图片.png

图片.png

图片.png

图片.png

图片.png

图片.png

图片.png

图片.png

图片.png

二、拦截机制

1.外部拦截
图片.png
2.内部拦截
图片.png

三、案例

1.ViewPage 嵌套 ListView滑动冲突
1、外部拦截解决 ——重写viewpage 的onInterceptTouchEvent
 // 外部拦截法:父容器处理冲突
 // 我想要把事件分发给谁就分发给谁
  private int mLastX, mLastY;
 @Override
 public boolean onInterceptTouchEvent(MotionEvent event) {
 //        if (event.getAction() == MotionEvent.ACTION_DOWN){
//            super.onInterceptTouchEvent(event);
 //            return false;
 //        }
//        return true;

    int x = (int) event.getX();
    int y = (int) event.getY();

    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN: {
            mLastX = (int) event.getX();
            mLastY = (int) event.getY();
            break;
        }
        case MotionEvent.ACTION_MOVE: {
            int deltaX = x - mLastX;
            int deltaY = y - mLastY;
            if (Math.abs(deltaX) > Math.abs(deltaY)) {
                return true;
            }
            break;
        }
        case MotionEvent.ACTION_UP: {
            break;
        }
        default:
            break;
    }

    return super.onInterceptTouchEvent(event);

}
2、内部拦截解决

1.重写viewpage 的onInterceptTouchEvent

 @Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    if (event.getAction() == MotionEvent.ACTION_DOWN){
       super.onInterceptTouchEvent(event);
        return false;
    }
    return true;

}
2.重写Listview的dispatchTouchEvent

 内部拦截法:子view处理事件冲突
private int mLastX, mLastY;
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
    int x = (int) event.getX();
    int y = (int) event.getY();

    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN: {
            getParent().requestDisallowInterceptTouchEvent(true);
            break;
        }
        case MotionEvent.ACTION_MOVE: {
            int deltaX = x - mLastX;
            int deltaY = y - mLastY;
            if (Math.abs(deltaX) > Math.abs(deltaY)) {
                getParent().requestDisallowInterceptTouchEvent(false);
            }
            break;
        }
        case MotionEvent.ACTION_UP: {
            break;

        }
        default:
            break;
    }

    mLastX = x;
    mLastY = y;
    return super.dispatchTouchEvent(event);
}
2.SwipeRefreshLayout嵌套 ViewPager滑动冲突
1、外部拦截解决 ——重写SwipeRefreshLayout 的onInterceptTouchEvent
 //外部拦截
 private int mLastX, mLastY;
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {

    //外部拦截  y>x 说明竖直滑动,进行拦截 否则不拦截
    int x = (int) event.getX();
    int y = (int) event.getY();

    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN: {
            mLastX = (int) event.getX();
            mLastY = (int) event.getY();
            break;
        }
        case MotionEvent.ACTION_MOVE: {
            int deltaX = x - mLastX;
            int deltaY = y - mLastY;
            if (Math.abs(deltaY) > Math.abs(deltaX)) {
                return true;
            }

            break;
        }
        case MotionEvent.ACTION_UP: {
            break;
        }
        default:
            break;
    }

    return super.onInterceptTouchEvent(event);
}
2、内部拦截解决 ——重写SwipeRefreshLayout 的onInterceptTouchEvent

1.重写SwipeRefreshLayout 的onInterceptTouchEvent

 @Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    if (event.getAction() == MotionEvent.ACTION_DOWN){
       super.onInterceptTouchEvent(event);
        return false;
    }
    return true;
}

2.重写ViewPager的dispatchTouchEvent

//内部拦截
private float startX;
private float startY;
private float x;
private float y;
private float deltaX;
private float deltaY;
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
            startX = ev.getX();
            startY = ev.getY();
            ViewCompat.setNestedScrollingEnabled(this,true);
            getParent().requestDisallowInterceptTouchEvent(true);
            break;
        case MotionEvent.ACTION_MOVE:
            x = ev.getX();
            y = ev.getY();
            deltaX = Math.abs(x - startX);
            deltaY = Math.abs(y - startY);
            if (deltaX < deltaY) {
                getParent().requestDisallowInterceptTouchEvent(false);
            }
            break;
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:
            break;
    }
    return super.dispatchTouchEvent(ev);
}

因为SwipeRefreshLayout重写了requestDisallowInterceptTouchEvent方法:

 public void requestDisallowInterceptTouchEvent(boolean b) {
    if ((VERSION.SDK_INT >= 21 || !(this.mTarget instanceof AbsListView)) && (this.mTarget == null ||     ViewCompat.isNestedScrollingEnabled(this.mTarget))) {
        super.requestDisallowInterceptTouchEvent(b);
    }

}

所以 ViewCompat.isNestedScrollingEnabled(this.mTarget)) 返回为true时才能有效;所以调用前添加

ViewCompat.setNestedScrollingEnabled(this,true);

你可能感兴趣的:(自定义View 事件冲突)