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

Jon*_*n O 8 android scroll scrollview viewflipper

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

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

我使用您可以在网上找到的常用教程代码扩展了onFling方法,并且它工作得很好 - 除非其中一个ScrollViews没有足够的内容来滚动.

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

当我在滚动的页面上滑动时,我会在onTling中获得"in onClick""in onScroll"中的内容等等.在一个太短而无法滚动的页面上,我在onLongPress中获得"in onClick""on onShowPress" ",这是只有当我触摸内容的太短滚动型的孩子-如果我触摸别处我没有得到任何事件都没有.

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

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


我对此有了更多的了解; 似乎当滚动视图包含在翻转器(或WorkspaceView)中时,不会为每个动作事件调用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;
Run Code Online (Sandbox Code Playgroud)

这是来自WorkspaceView.java(Android的Workspace.java的修改,在google代码上的andro-views项目中找到,现在在这里:水平"标签"ish在视图之间滚动).在我们收到移动事件的情况下,我们正在滚动(只有当我们故意选择拦截它时才发生 - 也就是说,它是在拦截函数中设置的,所以我们已经去过拦截函数)我们执行我们渴望的移动行为.如果我们在这里收到移动事件并且我们没有滚动,那么我们通过onIntercept重新发送事件,然后看看我们现在是否设置为滚动.如果是,我们执行操作.

它不优雅,但它的工作原理!

Jon*_*n O 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;
} 
Run Code Online (Sandbox Code Playgroud)

我不知道为什么,但是如果我尝试在dispatchTouchEvent中返回任何东西,那么它是合乎逻辑的(合乎逻辑的事情就是

return (gestureDetector.onTouchEvent(ev) || super.dispatchTouchEvent(ev)); 
Run Code Online (Sandbox Code Playgroud)

如果我理解得当,它不起作用,这样做.