当滚动太短而无法滚动时,Scrollview不会滑动

时间:2010-08-24 04:35:46

标签: android scroll scrollview viewflipper

我对Android应用程序开发很陌生,而且我一直在使用Android的SimpleOnGestureListener和ViewFlipper进行滑动手势。 ViewFlipper有3个子节点,每个子节点都是ScrollView。它们都是在Activity加载时动态填充的,并且在此之后它们不会更改。 ScrollView是SimpleOnGestureListeners附加的位置。

这是我正在使用的布局:
+ ViewFlipper
++ ScrollView(x3,每页一个,每个都有以下:) +++ LinearLayout(垂直)
++++的TextView
++++ TableLayout(动态填充w / TableRows)
++++查看

我使用你可以在网上任何地方找到的常用教程代码扩展了onFling方法,并且效果很好 - 除非其中一个ScrollViews没有足够的内容来滚动。

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

当我在滚动的页面上滑动时,我会在onFling中获得“in onClick”“in onScroll”中的内容等等。在一个太短而无法滚动的页面上,我在onShowPress中获得“in onClick” “在onLongPress中”,只有当我触摸内的太短的scrollview的孩子时 - 如果我触摸其他地方,我根本就没有事件。

关于什么是错误的想法,或者无论ScrollView有多大,如何检测滑动手势?

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


我对此有更深入的了解;似乎当滚动视图包含在翻转器(或工作区视图)中时,不会为每个动作事件调用onInterceptTouchEvent。

特别是,我在修改另一个视图类时修复了同样的问题(它不是鳍状肢独有的)时发现的行为如下 - 注意这只是Android 2.1:

如果滚动视图足够长以便滚动,则ScrollView会捕获ACTION_DOWN运动事件,并且每个后续的ACTION_MOVE事件都会通过脚蹼的onInterceptTouchEvent进行处理,并在其中进行相应的拦截和处理。在Android 2.2中,无论滚动长度如何,都会发生此行为。

返回2.1:如果滚动视图的滚动时间不够长,则滚动视图会捕获ACTION_DOWN运动事件 ,而是返回到鳍状肢的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重新发送事件,然后看看我们现在是否设置为滚动。如果是,我们会执行操作。

它不优雅,但它有效!

3 个答案:

答案 0 :(得分:7)

我需要创建一个扩展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中返回任何真实的东西(理所当然就是

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

如果我理解得当,它不起作用,而且确实如此。

答案 1 :(得分:1)

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

答案 2 :(得分:0)

有同样的问题。如果ScrollView的子项太短而没有滚动条,则需要在其子项上拦截touch事件。