2

我有一个带有两个视图的简单应用程序,一个是 TableView,另一个是 ListView。我使用 GestureDetector 来检测屏幕上的滑动,类似于此处的操作。一切正常,如果列表视图只填充了几个项目,但是当 ListView 填满整个屏幕时,手势检测停止工作。在屏幕上滑动只会突出显示列表项之一。

我认为这是因为 ListView 以某种方式从 GestureListener 窃取了触摸事件。有没有办法防止这种情况?

4

2 回答 2

2

如果您遍历相当准确的水平路径,我发现 GestureDetector 在 ListItems 中可以正常工作。但是,如果您稍微偏离,列表会滚动并且手势不会完成。情况如下:

  • GestureDetector 开始愉快地从您通过 setOnTouchListener() 安装在 ListItems 中的 onTouch 中获取 MotionEvents。
  • ListView 同时监听通过 onInterceptTouchEvent() 发送到其子视图的事件
  • ListView 检测到您已经开始滚动并从 onInterceptTouchEvent() 返回 true。
  • 从那时起,MotionEvents 被发送到 ListView 而不是原始目标...... ListView 开始在其 onTouch 处理程序中接收 MotionEvents。这一直持续到最后的 ACTION_UP。(请注意,从 ACTION_DOWN 到所有 ACTION_MOVE 到 ACTION_UP 的 MotionEvents 被认为是一个单一的手势,一切都在序列中的最后一个 ACTION_UP 之后重新开始)
  • 原始目标 (ListItem) 获得一个 ACTION_CANCEL MotionEvent 并且 ListItem 中的 GestureDetector 退出。如果您将 GestureDetector 的代码粘贴到您的应用程序中并单步执行,就会出现这种情况。

即使触摸稍微偏离水平方向,我也需要我的应用程序表现得好像水平滑动仍在继续。

解决方案:这涉及 ViewGroup.requestDisallowInterceptTouchEvent (boolean disallowIntercept),它阻止父级能够窥视运动事件。该方法涉及实现 onTouchListener 以检测轻微滑动(10 像素左右),然后停止父级拦截运动事件。然后父级将不会滚动,并且手势检测器会继续完成。

这是代码:

private boolean mFlingInProgress = false;
private float mStartX = 0;
private final int FLING_TRIGGER_DISTANCE = 10;

@Override
public boolean onTouch(View v, MotionEvent event) {
    int action = event.getAction();
    float currentX = event.getRawX();

    switch (action) {
    case MotionEvent.ACTION_DOWN:
        mStartX = currentX;
        break;
    case MotionEvent.ACTION_MOVE:
        if (false == mFlingInProgress) {
            if (Math.abs(currentX - mStartX) > FLING_TRIGGER_DISTANCE) {
                // stop the parent intercepting motion events
                mLayout.getParent().requestDisallowInterceptTouchEvent(true);
                mFlingInProgress = true;
            }
        } 
        break;
    case MotionEvent.ACTION_UP:
        mFlingInProgress = false;
        break;
    }

    return mGestureDetector.onTouchEvent(event);
}
于 2012-11-05T22:52:37.273 回答
1

您可以创建一个自定义列表视图,然后在其中实现手势检测器,即在列表的每一行上。可能值得一试。

于 2010-12-15T13:23:09.040 回答