【问题标题】:ScrollView with children view, how to intercept scroll conditionally带有子视图的ScrollView,如何有条件地拦截滚动
【发布时间】:2014-01-02 14:56:51
【问题描述】:

我有一个容器ViewGroup,让我们在ScrollView 中将其称为screen。这个容器视图托管了许多其他 Views 我们称它们为 widgets,其中一些有兴趣防止 ScrollView 滚动并自己使用 MotionEvent(例如可平移图像)

我无法确定要使用的正确事件拦截策略。 ScrollView 总是在子进程之前处理事件,或者子进程处理事件但 scrollview 被禁用。

如果此视图想要捕获事件,我阅读了有关在子视图中发出 getParent().requestDisableInterceptTouchEvent() 的信息,但他们的 onTouchEvent 没有被调用,我想是因为 ScrollView 已经预先吞没了事件。我想我有 2 层层(容器 + 小部件)的事实阻止了它的工作,我想容器 ViewGroup 必须在这里发挥重要作用,但我不知道是哪一个......

我能否知道,在ScrollView'sonInterceptTouchEvent 级别,容器viewGroup 上的哪个小部件已被触摸以决定我是否应该拦截?

或者...

ViewGroup 中的“小部件”层如何在 ScrollView 之前获取事件,以便我可以调用 getParent().onRequestDisableInterceptTouch() ... 还是 getParent().getParent().onRequestDisableInterceptTouch()

提前致谢

我已阅读相关问题,但没有运气... Handle touch events in ScrollView Android

【问题讨论】:

    标签: android touch scrollview touch-event


    【解决方案1】:

    经过一夜的可口可乐和调试后,我设法让它工作了。我分享这个解决方案以防万一有人感兴趣,因为我花了很多时间才让它运行起来。

    我没有设法让它与getParent().onRequestDisableInterceptTouch() 一起运行,我很接近,但是一旦我截获了对父级的触摸,就无法找到让子小部件获得滚动所需的 MotionEvents 的方法,所以即使正确阻止了外部滚动,内部小部件也没有滚动。

    所以解决方法是interceptTouchEventsin the children ONLY,并且如果children是可滚动的(已知属性),并且触摸是ACTION_DOWN,则禁用上面两级的scrollview。如果触摸是 ACTION_UP,我们启用滚动视图。

    要启用/禁用滚动视图,我只需拦截触摸事件并使用标志过滤事件。

    我做了三个辅助类,一个给ScrollView,一个给Container,一个给widgets:

    这个类包装了每个小部件,如果我调用 setNeedsScroll(true) ,那么触摸将被拦截,当它被触摸时,它会(告诉容器)告诉滚动视图禁用自身。当触摸被释放时,它将重新启用滚动视图。

    class WidgetWrapperLayout extends FrameLayout {
    
        private boolean mNeedsScroll=false;
    
        public WidgetWrapperLayout(Context context) {
            super(context);
        }
    
      /** Called anytime, ie, during construction, to indicate that this 
        * widget uses vertical scroll, so we need to disable its container scroll 
        */
    
        public void setNeedsScroll(boolean needsScroll) { 
            mNeedsScroll=needsScroll; 
        }
    
        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            if (mNeedsScroll)  {
                switch (ev.getAction()) {  
                case MotionEvent.ACTION_DOWN:
                    ((SlideLayout)getParent()).setEnableScroll(false);
                    break;
                case MotionEvent.ACTION_UP:
                    ((SlideLayout)getParent()).setEnableScroll(true);
                    break;
                }
                return false;
            }
            return super.onInterceptTouchEvent(ev);
        }
    }
    

    这是容器,是scrollview 的唯一子容器,它包含不同的小部件。它只是为孩子提供方法,以便他们可以启用/禁用滚动:

    public class ContainerLayout extends FrameLayout {
    
        public ContainerLayout(Context context) {
            super(context);
        }
    
        public void setEnableScroll(boolean status) {
            if (Conf.LOG_ON) Log.d(TAG, "Request enable scroll: "+status);
            ((StoppableScrollView)getParent()).setScrollEnabled(status);
        }
    }
    

    最后是一个可以停用的滚动视图。它禁用滚动'old-skool',拦截和阻止事件。

    public class StoppableScrollView extends ScrollView {
    
        private String TAG="StoppableScrollView";
    
        private boolean mDisableScrolling=false;
    
        public StoppableScrollView(Context context) {
            super(context);
        }
    
        /** Enables or disables ScrollView scroll */
        public void setScrollEnabled (boolean status) { 
            if (Conf.LOG_ON) Log.d(TAG, "Scroll Enabled "+status);
            mDisableScrolling=!status; 
        }
    
    
        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            if (mDisableScrolling) return false;
            return super.onInterceptTouchEvent(ev);
        }
    }
    

    【讨论】:

      【解决方案2】:

      在您的 Activity 中实现 View.OnTouchListener 并将该侦听器添加到 ScrollView。然后在onTouchEvent(...) 中返回 true。在返回之前调用您要处理该事件的孩子的onTouch

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-09-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-09-14
        • 1970-01-01
        • 1970-01-01
        • 2015-06-30
        相关资源
        最近更新 更多