onInterceptTouchEvent指针数不正确

时间:2012-12-11 01:30:54

标签: android android-viewpager

我希望我的ViewPager只在单指时滑动。所以我扩展了类并实现了onInterceptTouchEvent,如下所示:

@Override
public boolean onInterceptTouchEvent(MotionEvent ev)
{
    if(ev.getPointerCount() > 1)
    {
        return false;
    }
    return true;
}

但无论屏幕上有多少点,getPointerCount()总是返回'1'。当我覆盖onTouchEvent时,我得到了正确的数字,但是当我这样做时,一个错误就是当你从多点触控中抬起你的第一根手指时,通过抛出app杀死异常来阻止寻呼机工作(http://code.google.com/p/android/issues/detail?id=18990):java .lang.IllegalArgumentException:pointerIndex超出范围

我还能怎么做呢?

修改

指针计数问题仍然存在,但我能够解决在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;
}

2 个答案:

答案 0 :(得分:4)

你的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步骤,并且它中的错误永远不会发生。

答案 1 :(得分: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和触摸处理程序会尝试对多点触摸进行操作并中断,因为手指2没有事件的第二个元素。

我同意这不应该发生,这是这里报告的支持库中的一个错误(我认为是一个) https://code.google.com/p/android/issues/detail?id=18990 它在不久前被标记为已解决,但仍然发生在最新版本的SupportLibrary V4