我对 Android 应用程序开发还很陌生,我一直在使用 Android 的 SimpleOnGestureListener 和 ViewFlipper 玩滑动手势。ViewFlipper 有 3 个子级,每个子级都是一个 ScrollView。它们都是在 Activity 加载时动态填充的,之后它们不会改变。ScrollView 是附加 SimpleOnGestureListeners 的地方。
这是我正在使用的布局:
+ViewFlipper
++ScrollView(x3,每个页面一个,每个都有以下内容:
)+++LinearLayout(垂直)
++++TextView
++++TableLayout(动态填充 w/TableRows )
++++查看
我用你可以在网上任何地方找到的通用教程代码扩展了 onFling 方法,它工作得很好——除非其中一个 ScrollViews 不包含足够的滚动内容。
我通过在 SimpleOnGestureListener 的每个方法上覆盖和调用 super 来添加打印到日志,从而将问题缩小到触摸检测。
当我在滚动的页面上滑动时,我会得到一些充满“in onClick”“in onScroll”“onFling”等的东西。在一个太短而无法滚动的页面上,我会得到“in onClick”“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 的修改,在谷歌代码的 andro-views 项目中找到,现在在这里:水平“tab”ish scroll between views)。如果我们收到一个移动事件,并且我们正在滚动(只有当我们故意选择拦截它时才会发生这种情况 - 即它在拦截函数中设置,所以我们已经进入拦截函数)我们执行我们想要的移动行为。如果我们在这里收到一个移动事件并且我们没有滚动,那么我们通过 onIntercept 将事件发送回,然后查看我们现在是否设置为滚动。如果是这样,我们执行该操作。
它不优雅,但它有效!