【问题标题】:Scrollview doesn't swipe when it's too short to scroll滚动视图太短而无法滚动时不会滑动
【发布时间】:2010-08-24 04:35:46
【问题描述】:

我是 Android 应用程序开发的新手,我一直在使用 Android 的 SimpleOnGestureListener 和 ViewFlipper 玩滑动手势。 ViewFlipper 有 3 个子级,每个子级都是一个 ScrollView。它们都是在 Activity 加载时动态填充的,之后它们不会改变。 ScrollView 是附加 SimpleOnGestureListeners 的地方。

这是我正在使用的布局:
+ViewFlipper
++ScrollView(x3,每页一个,每个都有以下内容:)
+++线性布局(垂直)
++++文本视图
++++TableLayout(动态填充 w/TableRows)
++++查看

我用你可以在网上任何地方找到的通用教程代码扩展了 onFling 方法,它工作得很好——除非其中一个 ScrollView 不包含足够的滚动内容。

我通过在 SimpleOnGestureListener 的每个方法上覆盖和调用 super 来添加打印到日志,从而将问题缩小到触摸检测。

当我在滚动的页面上滑动时,我会看到充满“in onClick”、“in onScroll”、“in onFling”等内容。在太短而无法滚动的页面上,我会看到“in onClick”“in onShowPress” “在 onLongPress 中”,只有当我触摸太短的滚动视图的子项的内容时——如果我触摸其他地方,我根本不会收到任何事件。

关于出了什么问题的想法,或者无论 ScrollView 有多大,如何检测滑动手势?

编辑:我已经确定,当我在 Android 2.2 模拟器上运行它时,与我一直使用的 Android 2.1u1 DroidX 模拟器相反,它会消失。这可以在多个环境中重现。


我对此有更多的了解;当滚动视图包含在鳍状肢(或 WorkspaceView)中时,似乎不会为每个运动事件调用 onInterceptTouchEvent。

特别是,我在修改另一个视图类以解决同样的问题时发现的行为(不是鳍状肢独有的)如下 - 请注意,这仅适用于 Android 2.1:

如果scrollview足够长可以滚动,则ACTION_DOWN运动事件被ScrollView捕获,后续的每一个ACTION_MOVE事件都会经过flipper的onInterceptTouchEvent,在那里被拦截并适当处理。在 android 2.2 中,无论滚动长度如何,都会发生此行为。

回到2.1:如果scrollview不够长滚动,ACTION_DOWN运动事件被scrollview捕获,而是回到flipper的onTouchEvent。同一手势的所有后续 ACTION_MOVE 事件跳过 onInterceptTouchEvent 函数,直接进入 onTouchEvent 函数!

我解决这个问题的方法是将 onTouchEvent 中的功能用于 ACTION_MOVE 事件,并将其重构为自己的方法。这样,我可以让 onTouchEvent 调用 onInterceptTouchEvent,如果它检测到该事件之前未处理,则该功能后跟该功能。

case MotionEvent.ACTION_MOVE:

                if (touchState == TOUCH_STATE_SCROLLING) {
                    handleScrollMove(ev);
                } else {
    //              Log.d("workspace","caught a move touch event but not scrolling");
                    //NOTE:  We will never hit this case in Android 2.2.  This is to fix a 2.1 bug.
                    //We need to do the work of interceptTouchEvent here because we don't intercept the move
                    //on children who don't scroll.

                    Log.d("workspace","handling move from onTouch");

                    if(onInterceptTouchEvent(ev) && touchState == TOUCH_STATE_SCROLLING){
                        handleScrollMove(ev);
                    }

                }

                break;

这是来自 WorkspaceView.java(Android 的 Workspace.java 的修改,在 google 代码的 andro-views 项目中找到,现在在这里:Horizontal "tab"ish scroll between views)。如果我们收到一个移动事件,并且我们正在滚动(只有当我们故意选择拦截它时才会发生这种情况 - 即它在拦截函数中设置,所以我们已经进入拦截函数)我们执行我们想要的移动行为。如果我们在这里接收到一个移动事件并且我们没有滚动,那么我们通过 onIntercept 将事件发送回,然后查看我们现在是否设置为滚动。如果是,我们执行该操作。

它并不优雅,但它确实有效!

【问题讨论】:

    标签: android scroll scrollview viewflipper


    【解决方案1】:

    我需要创建一个扩展 ScrollView 的新类,并使用它:

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);
        return gestureDetector.onTouchEvent(event);
    }
    
    @Override 
    public boolean dispatchTouchEvent(MotionEvent ev){
        gestureDetector.onTouchEvent(ev);
        super.dispatchTouchEvent(ev); 
        return true;
    } 
    

    我不知道为什么,但是如果我尝试在 dispatchTouchEvent 中返回除 true 之外的任何内容(合乎逻辑的事情应该是

    return (gestureDetector.onTouchEvent(ev) || super.dispatchTouchEvent(ev)); 
    

    如果我理解正确),它不起作用,但它确实起作用。

    【讨论】:

      【解决方案2】:

      尝试在您的布局 xml 中为每个 ScrollViews 设置 android:fillViewport="true"。这告诉ScrollView 与它所包含的视图一样大。

      【讨论】:

      • 在所有子节点上都设置为这样。我什至直接将xml复制并粘贴到curious-creature.org/2010/08/15/scrollviews-handy-trick/… 并尝试将其作为子视图。经过一番摆弄后,我设法让它们都填满了视口。但即使他们这样做了,回调也没有运气。到目前为止,没有滚动条 = 没有 onFling。
      【解决方案3】:

      有同样的问题。当ScrollView 的子元素太短而没有滚动条时,您需要拦截触摸事件。

      【讨论】:

        猜你喜欢
        • 2019-06-09
        • 2017-01-11
        • 1970-01-01
        • 1970-01-01
        • 2021-11-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多