与 ScrollView 一起滑动/翻转选项卡更改?

Posted

技术标签:

【中文标题】与 ScrollView 一起滑动/翻转选项卡更改?【英文标题】:Swipe/Fling tab-changing in conjunction with ScrollView? 【发布时间】:2011-07-03 10:41:12 【问题描述】:

在这个特定问题上我能找到的最好的(虽然我不使用画廊):ScrollView and Gallery interfering - 虽然并没有真正给出具体的答案。而且我的实现显然不使用画廊。

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

所以不久前我在我的应用程序上使用了 Fling/Swipe/Flick/任何你想调用的方法。灵感来自几个不同的地方,其中一些是 Stack Overflow (Fling gesture detection on grid layout)、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-horizontal-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 类中的手势检测器及其关联的侦听器:

    // 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;
    

【问题讨论】:

我遇到了您在此处提到的相同问题。我完成了覆盖我的自定义画廊的 onInterceptTouchEvent()。它有效,但非常复杂和丑陋。最终的解决方案不能用于不同的视图集。我认为最好的方法是编写我自己的忽略水平滚动事件的滚动视图实现。 【参考方案1】:

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

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

我认为关键在于扩展TabHost 并覆盖其onInterceptTouchEvent 方法。

【讨论】:

我在我的 Tabs 类中实现了手势检测,但它扩展了 TabActivity。我是否应该将处理完全放在另一个类中,然后扩展 TabHost?我不太确定如何实施它(缺乏概述),呵呵。 为什么不完全按照他们在那个项目中所做的那样实现它?您应该能够将他们的 FlingableTabHost 内部类定义复制到您的 TabActivity 类中。只需确保为引用自定义 FlingableTabHost 视图而不是普通 TabHost 的内容视图使用自定义布局,例如:code.google.com/p/iosched/source/browse/trunk/res/layout/… Hoorah,我让它与一些主要的变通方法一起工作。实施谷歌的 FlingableTabHost 使它与我有 ScrollViews 的活动一起工作,但在其他一些部分停止了它的工作。所以我重新启用了我的 onTouchEvent-listener,现在它在两者上都可以使用。它不漂亮,但它有效。 :) 非常感谢,杰夫。我可能想在某个时候重新实现我的应用程序,重点是基于视图的应用程序(所以我不会经常在活动之间跳转),就我为此使用的代码而言,它不应该太复杂,对吧?顺便说一句,有一些 +rep 和声称的赏金。【参考方案2】:

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

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

从Android Dev site 开始,它谈到了在布局文件的<android.gesture.GestureOverlayView> Root 中使用此属性。

【讨论】:

正如 Jeff 所建议的,我只是采用了 Google 在链接的 ScheduleActivity(和 .xml)中解决它的方式。这不是最漂亮的解决方案,因为我同时在听两件事,但它可以很好地确保滚动和滑动工作完美无缺。 :)【参考方案3】:

不管怎样,我发现 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;

【讨论】:

以上是关于与 ScrollView 一起滑动/翻转选项卡更改?的主要内容,如果未能解决你的问题,请参考以下文章

iOS Swift ScrollView、UITableView、滚动区域

Flutter:无法或更改 TabController 的选项卡之间滑动的敏感性

在 Flutter 中使用具有不同选项卡的不同 FAB,并在它们之间滑动时更改按钮?

与 ScrollView 结合的自定义选项卡视图的问题

在UITableViewStylePlain情况下sectionHeader可以与tableview一起滑动的解决方法

带路由器的可滑动 Vuetify 选项卡