解决ScrollView嵌套viewPager中嵌套listView滑动事件冲突问题(水平方向)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wy391920778/article/details/79557251

我们在开发中经常会碰到view滑动冲突的情况。

滑动冲突的解决办法就两种:

1.外部拦截法:是指在点击事件先经过父容器的拦截处理,如果父容器需要处理此事件就进行拦截,如果不需要此事件就不拦截,这样就可以解决滑动冲突的问题,外部拦截法需要重写父容器的onInterceptTouchEvent()方法,在内部做相应拦截处理。

2.内部拦截法:是指点击事件先经过子View处理,如果子view需要次事件就直接消耗掉,否则就交给父容器进行处理,这样就可以解决滑动冲突的问题。内部拦截需要配合requestDisallowInterceptTouchEvent()方法,来确定子view是否允许父容器拦截事件。

    a.允许父容器进行事件拦截

        getParent().requestDisallowInterceptTouchEvent(false)

    b.禁止父容器进行事件拦截

        getParent().requestDisallowInterceptTouchEvent(true)


以上是解决滑动冲突的方法,下面我们回到我们今天解决的正题ScrollView嵌套viewPager中嵌套listView滑动事件冲突

这里可以使用第一种解决方案:外部拦截法

只需要自定义一个ScrollView,然后重写它的onInterceptTouchEvent()即可,代码如下:

public class VerticalScrollView extends ScrollView {

    private float xDistance, yDistance, xLast, yLast;

    public VerticalScrollView(Context context) {
        super(context);
    }

    public VerticalScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public VerticalScrollView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                xDistance = yDistance = 0f;
                xLast = ev.getX();
                yLast = ev.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                final float curX = ev.getX();
                final float curY = ev.getY();

                xDistance += Math.abs(curX - xLast);
                yDistance += Math.abs(curY - yLast);
                xLast = curX;
                yLast = curY;

                if (xDistance > yDistance) {
                    return false;
                }
        }
        return super.onInterceptTouchEvent(ev);
    }

}

第二种解决方案如下:不需要自定义控件

1.第一步:允许父容器进行事件拦截

scrollView.setOnScrollToBottomLintener(new BottomScrollView.OnScrollToBottomListener() {
    @Override
    public void onScrollBottomListener(boolean isBottom) {
        if (isBottom) {
            scrollView.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    switch (event.getAction()) {
                        case MotionEvent.ACTION_MOVE:
                            //解决滑动冲突

                            scrollView.getParent().requestDisallowInterceptTouchEvent(false);
                            break;
                    }
                    return false;
                }
            });
        }
    }
});

2.第二步:父元素也要默认拦截除了ACTION_DOWN以外的其他事件,这样当子元素调用

scrollView.getParent().requestDisallowInterceptTouchEvent(false)

方法时,父元素才能继续拦截所需的事件。

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    int action = ev.getAction();
    return action != MotionEvent.ACTION_DOWN; 
}

3.为什么父容器不能拦截ACTION_DOWN事件呢?

    因为ACTION_DOWN事件并不受FLAG_DISALLOW_INTERCEPT这个标记位的控制,所以一旦父容器拦截ACTION_DOWN事件,那么所有的事件都无法传递到子元素中去,这样内部拦截就无法起作用了。


猜你喜欢

转载自blog.csdn.net/wy391920778/article/details/79557251