代码之家  ›  专栏  ›  技术社区  ›  Jon O

滚动视图太短而无法滚动时不会滑动

  •  8
  • Jon O  · 技术社区  · 14 年前

    我对Android应用程序开发还很陌生,我一直在用Android的simpleongestureelistener和ViewFlipper玩刷卡手势。ViewFlipper有3个子级,每个子级都是一个ScrollView。当活动加载时,它们都是动态填充的,并且在加载之后不会改变。ScrollView是SimpleNogestureListeners的附件。

    以下是我使用的布局:
    +视图翻转器
    ++ScrollView(x3,每页一个,每个带有以下内容:)
    +++线性布局(垂直)
    ++++文本视图

    我用你在网上任何地方都能找到的常用教程代码扩展了onFling方法,它工作得很好——除非其中一个ScrollViews包含的内容不够滚动。

    我已经将问题缩小到了触摸检测,通过重写并调用SimpleOnGestureListener的每个方法中的super,将打印添加到日志中。

    在内部 太短的滚动视图的孩子们——如果我触摸其他地方,我就根本看不到任何事件。

    关于什么是错的,或者不管滚动视图有多大如何检测滑动手势的想法?

    编辑:我已经确定,当我在android2.2模拟器上运行它时,与我一直使用的android2.1u1droidx模拟器相反,它会消失。这在多种环境下都是可重复的。


    我对此有更深入的了解;似乎当scrollview包含在flipper(或WorkspaceView)中时,不会为每个运动事件调用onInterceptTouchEvent。

    如果scrollview足够长,可以滚动,则scrollview会捕获ACTION\u DOWN motion事件,并且每个后续的ACTION\u MOVE事件都会经过flipper的InterceptTouchEvent,在那里它会被拦截并得到适当的处理。在android2.2中,无论滚动长度如何,都会发生这种行为。

    回到2.1:如果scrollview不够长,无法滚动,那么ACTION\u DOWN motion事件是 跳过 onInterceptTouchEvent函数,直接转到onTouchEvent函数!

    我解决这个问题的方法是利用onTouchEvent中的ACTION\u MOVE事件功能,并将其重构为自己的方法。这样,如果onTouchEvent检测到事件以前未经处理,我就可以让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;
    

    这是从工作空间视图.java(Android的工作区.java,在谷歌代码上的andro views项目中找到,现在这里: Horizontal "tab"ish scroll between views ). 如果我们收到一个move事件,并且我们正在滚动(只有当我们故意选择截取它时才会发生——也就是说,它是在intercept函数中设置的,所以我们已经去过intercept函数)我们执行我们想要的移动行为。如果我们在这里收到一个move事件,而我们没有滚动,那么我们通过onIntercept将事件发送回来,然后查看是否现在设置为滚动。如果是这样,我们就执行这个动作。

    虽然不优雅,但很管用!

    2 回复  |  直到 7 年前
        1
  •  7
  •   Jon O    14 年前

    我需要创建一个扩展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中返回除true以外的任何内容(合乎逻辑的事情应该是

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

        2
  •  1
  •   Rich Schuler    14 年前

    尝试设置 android:fillViewport="true" 在每个 ScrollView 卷轴视图 和它所包含的视图一样大。

        3
  •  0
  •   doctorram    5 年前

    有同样的问题。你需要截获孩子们的触摸事件 ScrollView