onInterceptTouchEvent中指针计数不正确

5
我希望我的ViewPager只在使用单个手指时滑动。所以我扩展了该类并实现了onInterceptTouchEvent,如下所示:
@Override
public boolean onInterceptTouchEvent(MotionEvent ev)
{
    if(ev.getPointerCount() > 1)
    {
        return false;
    }
    return true;
}

但是getPointerCount()始终返回“1”,无论屏幕上有多少点。当我重写onTouchEvent时,我可以得到正确的数字,但这样做会导致一个错误,完全阻止了分页器的工作(http://code.google.com/p/android/issues/detail?id=18990),当你将第一个手指从多点触摸中抬起时,它会抛出一个杀死应用程序的异常:java.lang.IllegalArgumentException: pointerIndex out of range 还有其他方法吗?
编辑:
指针计数问题仍然存在,但我能够解决在onTouchEvent中抛出的异常。 我在得到异常时正在执行以下操作:
if(ev.getPointerCount() == 1)
{
    return super.onTouchEvent(ev);
}
return false;

问题在于当您将第一个手指从多点触控中抬起时,ViewPager的onTouchEvent最终处理ACTION_UP事件而没有先处理ACTION_DOWN事件。因此,我想出了这个解决方法,避免了异常并且当您放下第二个手指时会结束ViewPager的移动:
private boolean moving = false;
@Override
public boolean onTouchEvent (MotionEvent ev)
{
    int action = ev.getAction();
    if(action == MotionEvent.ACTION_DOWN)
    {
        moving = true;
    }
    if(ev.getPointerCount() == 1)
    {
        if(moving)
        {
            return super.onTouchEvent(ev);
        }

        if(action == MotionEvent.ACTION_UP)
        {
            moving = false;
        }
    }
    else if(ev.getPointerCount() > 1 && moving)
    {
        ev.setAction(MotionEvent.ACTION_UP);
        moving = false;
        return super.onTouchEvent(ev);
    }
    return false;
}

非常好的解决方案,谢谢!这真的为我节省了很多工作。我以为我已经尝试了所有可能,包括下面的答案,但仍然导致异常。 - Frank
2个回答

5

您的onTouchEvent对我没有起作用,我将调查原因。但同时,我已经找到了另一个解决方法。我深入研究了ViewPager代码,并发现可以使用以下方法:

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {

    if (ev.getPointerCount() > 1){
        ev.setAction(MotionEvent.ACTION_CANCEL);
    }

    return super.onInterceptTouchEvent(ev);

}

getPointerCount() 对我来说可以正常工作。使用上述代码,ViewPager 也会处理 ACTION_DOWN 步骤,并且其中的错误永远不会发生。


这终于解决了我遇到的类似问题,但不幸的是,我必须通过艰难的方式找到它,因为搜索没有出现你的答案。我将在下面的答案中再写一点。 - Igor Čordaš

0

所以我终于找到了如何解决相同问题并且知道为什么它首先会发生的方法。我没有扩展ViewPager而是像示例中一样设置了触摸事件监听器来解决这个问题:

viewPager.setOnTouchListener(new OnTouchListener() {
        // TODO This breaks sometimes in compatibility library code, try to fix
        @Override
        public boolean onTouch(View v, MotionEvent event) {

            currentFragment.view.dispatchTouchEvent(event);
            if (!currentFragment.view.whole && event.getPointerCount() > 1) {

                event.setAction(MotionEvent.ACTION_CANCEL);

            }

            return false;
        }
    });

所以你需要做的就是将事件标记为已取消而不是将其消耗掉。当你在onTouch方法中返回true时,事件被消耗掉并且不会冒泡到ViewPager,所以它停止滚动。但是当你处理多个指针事件时,它会在第二个触摸后切断事件,但第一个仍然发送,所以ViewPager和触摸处理程序尝试对多点触控进行操作,并因为没有第二个元素而中断第一次触摸。
我同意这不应该发生,这应该是支持库中的一个错误,已在此处报告(我认为是这个) https://code.google.com/p/android/issues/detail?id=18990 它在SupportLibrary V4的最新版本中仍然存在,尽管已经被标记为解决。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接