Android:嵌套ScrollViews和Horizo​​ntalScrollViews,拦截

时间:2016-01-11 17:07:44

标签: android nested scrollview

我在Android中的ScrollViews中使用ScrollViews时遇到问题。我知道这不是最好的做法,但我需要让它发挥作用。

public static void disableScrollOnParentHorizontalScrollView(View v) {  
    v.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            int action = event.getAction();
            switch (action) {
            case MotionEvent.ACTION_DOWN:
                requestDisallowInterceptTouchEventByDirection(v, true, HorizontalScrollView.class);
                break;
            case MotionEvent.ACTION_UP:
                requestDisallowInterceptTouchEventByDirection(v, false, HorizontalScrollView.class);
                break;
            }
            v.onTouchEvent(event);
            return true;
        }
    });
}

对于使用ScrollView.class作为参数的垂直ScrollViews,我有与上面相同的方法。

private static void requestDisallowInterceptTouchEventByDirection(View v, boolean b, Class<?> clazz) {
    while (v.getParent() != null && v.getParent() instanceof View) {
        if (clazz.isInstance(v.getParent())) {
            v.getParent().requestDisallowInterceptTouchEvent(b);
        }
        v = (View) v.getParent();
    }
}

这是一个屏幕截图,我想告诉你究竟是什么问题。

  • ScrollView内部的嵌套Horizo​​ntalScrollView应垂直(父级)和水平(自己)滚动。
  • Horizo​​ntalScrollView内部的嵌套ScrollView应水平(父)和垂直(自己)滚动。
  • Horizo​​ntalScrollView内部的视图和垂直ScrollView应该滚动父项。

这在大多数情况下都适用。

screenshot

TextViews 5和9嵌套在ScrollViews中,TextViews 6和10嵌套在Horizo​​ntalScrollViews中。

  • 视图#2垂直滚动(2),父级水平滚动(1)
  • 视图#3水平滚动(3),父级垂直滚动(2)
  • ...
  • 视图#6水平滚动(6),垂直父级(4)
  • 视图#7水平滚动父级(3),垂直父级滚动(4)

因此,任何视图都应滚动它的父级,因为它本身不可滚动。

我的问题是垂直滚动视图(4)内的垂直滚动视图(5)不会欺骗外部垂直视图的水平滚动父级(3)。

在另一个方向上的相同问题(视图#10(水平滚动)不滚动它的父级(8,水平滚动)父级(4,垂直滚动),但视图右侧的视图#10滚动,8(水平)和4(垂直)。

似乎某些观点有错误的拦截,但我没有发现问题。

任何人都可以帮助我吗?

祝你好运

1 个答案:

答案 0 :(得分:0)

可能的解决方案

好的,要完成这个:我找到了一个可怕的解决方案,但它确实有效。

如果有两个嵌套的Horizo​​ntalScrollViews,我会搜索第一个(或最内部的)垂直ScrollView并禁用拦截。

public static void disableScrollOnParentHorizontalScrollView(View v) {

    v.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            int action = event.getAction();

            switch (action) {
            case MotionEvent.ACTION_DOWN:
                requestDisallowInterceptTouchEventByDirection(v, true, HorizontalScrollView.class); //funzt weitgehend
                if (isDirectlyHorizontalScrollViewAbove(v)) {
                    findFirstScrollViewAbove(v).requestDisallowInterceptTouchEvent(false);
                    findFirstScrollViewAbove(v).getParent().requestDisallowInterceptTouchEvent(true);
                }                   
                break;
            case MotionEvent.ACTION_UP:
                requestDisallowInterceptTouchEventByDirection(v, false, HorizontalScrollView.class);
                break;
            }
            v.onTouchEvent(event);
            return true;
        }
    });
}


private static boolean isDirectlyHorizontalScrollViewAbove(View v) {
    while (v.getParent() != null && v.getParent() instanceof View) {
        if (v.getParent() instanceof HorizontalScrollView) {
            return true;
        } else if (v.getParent() instanceof ScrollView) {
            return false;
        }
        v = (View) v.getParent();
    }
    return false;
}


private static ScrollView findFirstScrollViewAbove(View v) {
    while (v.getParent() != null && v.getParent() instanceof View) {
        if (v.getParent() instanceof ScrollView) {
            return (ScrollView) v.getParent();
        }
        v = (View) v.getParent();
    }
    return null;
}

// same method like before
private static void requestDisallowInterceptTouchEventByDirection(View v, boolean b, Class<?> clazz) {
    while (v.getParent() != null && v.getParent() instanceof View) {
        if (clazz.isInstance(v.getParent())) {
            v.getParent().requestDisallowInterceptTouchEvent(b);
        }
        v = (View) v.getParent();
    }
}

如果某人有更好的解决方案(或发现我的拦截问题),请回答:)

祝你好运