24

在这个特定问题上我能找到的最好的(虽然我不使用画廊):滚动视图和画廊干扰- 虽然并没有真正给出具体的答案。显然,我的实现不使用画廊。

跳到下一个粗体部分以获得有趣的部分

所以我在我的应用程序上得到了 Fling/Swipe/Flick/任何你想调用它的东西。灵感来自几个不同的地方,其中一些是 Stack Overflow 上的“基本手势检测”(网格布局上的 Fling 手势检测),Code Shogun(http://www.codeshogun.com/blog/2009/04 /16/how-to-implement-swipe-action-in-android/)和开发 Android (http://developingandroid.blogspot.com/2009/09/implementing-swipe-gesture.html),但我不使用我的应用程序中的 ViewFlipper。当发生投掷时,我只需更改标签(在末端环绕)。

现在,我的一些选项卡包含 ScrollViews。这些 ScrollViews 显然响应向上/向下滚动,以便让您查看其中的所有数据,这并不奇怪。问题是这些 ScrollViews 的“滚动”功能会覆盖我的投掷手势。我不能在 ScrollView 内翻滚(滚动就好),但它在它们之外完美地工作(在同一个选项卡上,在 TableRow 等其他视图上)。

我也快速浏览了http://blog.velir.com/index.php/2010/11/17/android-snapping-horizo​​ntal -scroll /,它提供了一种实现 Horizo​​ntalScrollView 的方法。但它仍然通过扩展 SimpleOnGestureListener(并覆盖 onFling)的类来处理手势,这与我的实现相同(这让我相信它不会真正有帮助)。来自 Google 的 ScrollView 源代码:http: //google.com/codesearch/p ?hl=en#uX1GffpyOZk/core/java/android/widget/ScrollView.java&d=3

有什么方法可以让我的 Swipe 和 ScrollView 实现毫不费力地协同工作?

这就是问题所在,我猜。ScrollView.java 还使用了一个名为 onTouchEvent 的方法以及用于 Activity 状态的 onTouchEvent 的文档:

“当触摸屏事件未被其下的任何视图处理时调用。这对于处理在窗口边界之外发生的触摸事件最有用,因为没有视图可以接收它。”

所以 ScrollView 确实“覆盖”了它——我该怎么办?有没有办法确保两者都被检查?ScrollView 处理 onTouchEvent 时未命中的我的 onTouchEvent:

@Override
/** Used for swipe gestures */
public boolean onTouchEvent(MotionEvent event) {
    if (gestureDetector.onTouchEvent(event))
        return true;
    else
        return false;
}

下面是更通用的源代码,它可能不是很重要。我的 Tabs 类中的gestureDetector 及其关联的侦听器:

    // Gestures
    gestureDetector = new GestureDetector(new MyGestureDetector());
    gestureListener = new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (gestureDetector.onTouchEvent(event)) {
                return true;
            }
            return false;
        }
    };

我的手势类是我的 Tabs 类(扩展 TabActivity)的嵌套类 - 它与您将在此主题上找到的任何其他代码相同:

/** GestureDetector used to swipe between classes */
class MyGestureDetector extends SimpleOnGestureListener {
    TabHost tabHost = getTabHost(); 

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        try {
            if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH) return false;
            if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                // my tab code
                return true;
            } else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
                // my tab code
                return true;
            }
        } catch (Exception e) {
            Log.e("MyGestureDetector onFling", e.toString());
        }
        return false;
    }
}
4

3 回答 3

19

我建议您查看 Google I/O 2010 应用程序源代码,因为它们的FlingableTabHost实现似乎已经解决了这个问题:

http://iosched.googlecode.com/svn/trunk/src/com/google/android/apps/iosched/ui/ScheduleActivity.java

我认为关键在于扩展TabHost和覆盖它的onInterceptTouchEvent方法。

于 2011-02-28T13:20:02.810 回答
0

在寻求解决我遇到的类似问题时,我遇到了这个花絮:

eventsInterceptionEnabled:当设置为 true 时,此属性告诉覆盖层在知道用户确实在绘制手势后立即从其子项中窃取事件。当覆盖下有一个可滚动视图时,这很有用,以避免在用户绘制手势时滚动底层子级

Android Dev site中,它讨论了<android.gesture.GestureOverlayView>在布局文件的 Root 中使用此属性。

于 2011-03-17T18:00:34.983 回答
0

对于它的价值,我发现 onFling 方法非常不可靠。我重写了 SimpleGestureDetector 中的 onScroll 方法,并将我的 onInterceptTouchEvent 定义为:

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    //Call super first because it does some hidden motion event handling
    boolean result = super.onInterceptTouchEvent(ev);
    if (this.mGestureScanner.onTouchEvent(ev)) return true;
    return result;
}
于 2011-10-01T04:29:35.407 回答