滑动手势和 android ListActivity 的问题:滑动手势正在激活底层列表项

发布于 2024-12-01 04:08:15 字数 2518 浏览 1 评论 0原文

我正在尝试在列表活动上实现滑动手势。这是可行的,但问题是触摸事件也会激活列表上的项目!

我寻找过其他答案,但不幸的是没有找到有效的解决方案。这是我正在使用的代码:

在列表活动中:

// Setup the swipe detector
mSwipeGestureListener = new SwipeGestureListener(this);
mGestureDetector = new GestureDetector(mSwipeGestureListener);
mGestureDetector.setIsLongpressEnabled(false);

@Override
public boolean dispatchTouchEvent(final MotionEvent ev)
{
    boolean handled = false;

    if (mGestureDetector != null)
    {
        handled = mGestureDetector.onTouchEvent(ev);
    }

    handled |= super.dispatchTouchEvent(ev);

    return handled;
}

这是我的手势侦听器的代码:

  public class SwipeGestureListener extends GestureDetector.SimpleOnGestureListener
  {
    protected final Activity mActivity;
    protected final int mTouchSlop;
    protected final int mMinimumSwipeVelocity;

    public SwipeGestureListener(final Activity activity)
    {
        mActivity = activity;
        final ViewConfiguration viewConfiguration = ViewConfiguration.get(activity);

        mTouchSlop = viewConfiguration.getScaledTouchSlop();
        mMinimumSwipeVelocity = viewConfiguration.getScaledMinimumFlingVelocity();
    }

    @Override
    public boolean onFling(final MotionEvent e1, final MotionEvent e2, final float velocityX, final float velocityY)
    {
        // Don't handle swipe if Y offset is greater than touch slop
        if (Math.abs(e1.getY() - e2.getY()) > mTouchSlop)
        {
            return false;
        }
        else
        {
            if (e1.getX() - e2.getX() > mTouchSlop
             && -velocityX > mMinimumSwipeVelocity)
            {
                // User swiped finger left.
                onSwipeToLeft();
            }
            else if (e2.getX() - e1.getX() > mTouchSlop
             && velocityX > mMinimumSwipeVelocity)
            {
                // User swiped finger left.
                onSwipeToRight();
            }

            // We're interested in these series of events
            return true;
        }        
    }

    // It is necessary to return true from onDown for the onFling event to register
    @Override
    public boolean onDown(final MotionEvent e)
    {
        return true;
    }

    protected void onSwipeToLeft() {}

    protected void onSwipeToRight() {};
   }

我完全被难住了。我究竟如何在 Android 中处理手势,而手势又不会激活列表中的底层项目!

PS 在根布局上使用 view.setOnTouchListener 导致永远接收不到触摸事件;这就是我使用dispatchTouchEvent的原因。

任何帮助将不胜感激。

谢谢!

I'm trying to implement a swipe fling gesture on a list activity. This is working but the problem is that the touch events also activate the items on the list!

I've looked for other answers but unfortunately did not find a working solution. Here is the code that I am using:

In the List Activity:

// Setup the swipe detector
mSwipeGestureListener = new SwipeGestureListener(this);
mGestureDetector = new GestureDetector(mSwipeGestureListener);
mGestureDetector.setIsLongpressEnabled(false);

@Override
public boolean dispatchTouchEvent(final MotionEvent ev)
{
    boolean handled = false;

    if (mGestureDetector != null)
    {
        handled = mGestureDetector.onTouchEvent(ev);
    }

    handled |= super.dispatchTouchEvent(ev);

    return handled;
}

And here is the code for my gesture listener:

  public class SwipeGestureListener extends GestureDetector.SimpleOnGestureListener
  {
    protected final Activity mActivity;
    protected final int mTouchSlop;
    protected final int mMinimumSwipeVelocity;

    public SwipeGestureListener(final Activity activity)
    {
        mActivity = activity;
        final ViewConfiguration viewConfiguration = ViewConfiguration.get(activity);

        mTouchSlop = viewConfiguration.getScaledTouchSlop();
        mMinimumSwipeVelocity = viewConfiguration.getScaledMinimumFlingVelocity();
    }

    @Override
    public boolean onFling(final MotionEvent e1, final MotionEvent e2, final float velocityX, final float velocityY)
    {
        // Don't handle swipe if Y offset is greater than touch slop
        if (Math.abs(e1.getY() - e2.getY()) > mTouchSlop)
        {
            return false;
        }
        else
        {
            if (e1.getX() - e2.getX() > mTouchSlop
             && -velocityX > mMinimumSwipeVelocity)
            {
                // User swiped finger left.
                onSwipeToLeft();
            }
            else if (e2.getX() - e1.getX() > mTouchSlop
             && velocityX > mMinimumSwipeVelocity)
            {
                // User swiped finger left.
                onSwipeToRight();
            }

            // We're interested in these series of events
            return true;
        }        
    }

    // It is necessary to return true from onDown for the onFling event to register
    @Override
    public boolean onDown(final MotionEvent e)
    {
        return true;
    }

    protected void onSwipeToLeft() {}

    protected void onSwipeToRight() {};
   }

I am completely stumped. How on earth can I handle gestures in Android without the gesture also activating the underlying items in the list!

P.S. Using view.setOnTouchListener on the root layout resulted in never receiving touch events; that's why I used dispatchTouchEvent.

Any help would be much appreciated.

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

随遇而安 2024-12-08 04:08:15

这不是一个完整的解决方案,但我能够通过以下代码更改来解决该问题:

我没有使用dispatchEvent,而是这样做:

    getListView().setOnTouchListener(new View.OnTouchListener() 
    {
        @Override
        public boolean onTouch(final View v, final MotionEvent me)
        {
            boolean handled = false;

            if (mGestureDetector != null)
            {
                handled = mGestureDetector.onTouchEvent(me);
            }

            return handled;
        }
    });

我改进了fling手势,如下所示:

    @Override
    public boolean onFling(final MotionEvent e1, final MotionEvent e2, final float velocityX, final float velocityY)
    {        
        if (e1 != null && e2 != null)
        {
            final float length = Math.abs(e1.getX() - e2.getX());
            final float height = Math.abs(e1.getY() - e2.getY());

            // Accept criteria: X movement more than or equal to touch slop, total
            // slope <= 50%
            if (length < mTouchSlop || height / length > 0.50)
            {
                return false;
            }
            else
            {
                if (-velocityX > mMinimumSwipeVelocity)
                {
                    // User swiped finger left.
                    onSwipeToLeft();
                }
                else if (velocityX > mMinimumSwipeVelocity)
                {
                    // User swiped finger right.
                    onSwipeToRight();
                }

                // We're interested in these series of events
                return true;
            }
        }
        else
        {
            return false;
        }
    }

并且我删除了onDown()覆盖返回 true,因为这会扰乱 ListView 上的滚动。

希望这可以帮助其他人。

This isn't a full solution, but I was able to work around the problem with the following code changes:

Instead of using dispatchEvent, I do this:

    getListView().setOnTouchListener(new View.OnTouchListener() 
    {
        @Override
        public boolean onTouch(final View v, final MotionEvent me)
        {
            boolean handled = false;

            if (mGestureDetector != null)
            {
                handled = mGestureDetector.onTouchEvent(me);
            }

            return handled;
        }
    });

I improved the fling gesture as follows:

    @Override
    public boolean onFling(final MotionEvent e1, final MotionEvent e2, final float velocityX, final float velocityY)
    {        
        if (e1 != null && e2 != null)
        {
            final float length = Math.abs(e1.getX() - e2.getX());
            final float height = Math.abs(e1.getY() - e2.getY());

            // Accept criteria: X movement more than or equal to touch slop, total
            // slope <= 50%
            if (length < mTouchSlop || height / length > 0.50)
            {
                return false;
            }
            else
            {
                if (-velocityX > mMinimumSwipeVelocity)
                {
                    // User swiped finger left.
                    onSwipeToLeft();
                }
                else if (velocityX > mMinimumSwipeVelocity)
                {
                    // User swiped finger right.
                    onSwipeToRight();
                }

                // We're interested in these series of events
                return true;
            }
        }
        else
        {
            return false;
        }
    }

And I removed the onDown() override that was returning true because that was screwing up scrolling on the ListView.

Hope that this can help someone else out there.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文