Java 禁用在ViewPager中的某些片段上滑动

Java 禁用在ViewPager中的某些片段上滑动,java,android,android-viewpager,swipe,touch-event,Java,Android,Android Viewpager,Swipe,Touch Event,我有一个ViewPager,可以禁用或启用滑动触摸: public class ConfigurablePager extends ViewPager { private final AtomicBoolean touchesAllowed = new AtomicBoolean(); ... private boolean touchesAllowed() { return touchesAllowed.get(); } publ

我有一个
ViewPager
,可以禁用或启用滑动触摸:

public class ConfigurablePager extends ViewPager {

    private final AtomicBoolean touchesAllowed = new AtomicBoolean();

    ...

    private boolean touchesAllowed() {
        return touchesAllowed.get();
    }

    public void enableTouches() {
        touchesAllowed.set(true);
    }

    public void disableTouches() {
        touchesAllowed.set(false);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        return touchesAllowed() && super.onTouchEvent(ev);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return touchesAllowed() && super.onInterceptTouchEvent(ev);
    }
}
有些碎片可以刷卡,但另一些不能。寻呼机适配器知道每个片段的滑动行为。此行为可以在
ViewPager.OnPageChangeListener
中更改:

@Override
public void onPageSelected(int position) {
    if (adapter.isTouchesAllowed(position)) {
        views.pager.enableTouches();
    } else {
        views.pager.disableTouches();
    }
}
问题
有时,当我快速滑动片段并同时单击其他片段的选项卡时,viewpager会抛出
IllegalArgumentException

致命异常:
main java.lang.IllegalArgumentException:指针索引超出范围
在android.view.MotionEvent.nativeGetAxisValue(本机方法)
在android.view.MotionEvent.getX(MotionEvent.java:1979)
在android.support.v4.view.MotionEventCompatEclair.getX(MotionEventCompatEclair.java:32)上
在android.support.v4.view.MotionEventCompat$EclairMotionEventVersionImpl.getX(MotionEventCompat.java:110)
位于android.support.v4.view.MotionEventCompat.getX(MotionEventCompat.java:462)
在android.support.v4.view.ViewPager.onTouchEvent(ViewPager.java:2080)上
在com.test.debugpager.ConfigurablePager.onTouchEvent(ConfigurablePager.java:39)上
在android.view.view.dispatchTouchEvent(view.java:7384)
在android.view.ViewGroup.DispatchTransformedToucheEvent(ViewGroup.java:2203)上
在android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1938)
在android.view.ViewGroup.DispatchTransformedToucheEvent(ViewGroup.java:2231)上
在android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1952)上
在android.view.ViewGroup.DispatchTransformedToucheEvent(ViewGroup.java:2209)上

这是因为
ViewPager
保存最后一个指针ID并获得不一致的状态(一些触摸事件由
onInterceptTouchEvent
删除),例如,上次触摸事件中的
ACTION\u MOVE
带有不正确的
MacTivePointId
(请参阅ViewPager.java的来源)

问题
是否可以以其他方式禁用某些片段上的滑动,可能无需覆盖InterceptTouchEvent上的

ViewPager源(onTouchEvent):

解决了的 我仔细阅读了
ViewGroup
中的手势识别,并分析了
ViewPager
onTouchEvent
来源。在这里,我认识到
ViewPager
只对
ACTION\u MOVE
事件进行滑动,因此我们不应该只对该操作调用touch回调,我们应该在调用基类
ontochevent
之前,遵循base
ViewGroup
oninterceptochevent
的oninterceptochevent结果。

根据此规则,我更改了我的
ViewPager
code:

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    if (touchesAllowed()) {
        return super.onInterceptTouchEvent(ev);
    } else {
        if (MotionEventCompat.getActionMasked(ev) == MotionEvent.ACTION_MOVE) {
            // ignore move action
        } else {
            if (super.onInterceptTouchEvent(ev)) {
                super.onTouchEvent(ev);
            }
        }
        return false;
    }
}

@Override
public boolean onTouchEvent(MotionEvent ev) {
    if (touchesAllowed()) {
        return super.onTouchEvent(ev);
    } else {
        return MotionEventCompat.getActionMasked(ev) != MotionEvent.ACTION_MOVE && super.onTouchEvent(ev);
    }
}

@托德萨尔彭:它应该会起作用。当你说有些东西不起作用时,你必须提供一些案例和环境,在这些案例和环境中,这个解决方案不适合你。没有这一点,这一评论毫无用处。
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    if (touchesAllowed()) {
        return super.onInterceptTouchEvent(ev);
    } else {
        if (MotionEventCompat.getActionMasked(ev) == MotionEvent.ACTION_MOVE) {
            // ignore move action
        } else {
            if (super.onInterceptTouchEvent(ev)) {
                super.onTouchEvent(ev);
            }
        }
        return false;
    }
}

@Override
public boolean onTouchEvent(MotionEvent ev) {
    if (touchesAllowed()) {
        return super.onTouchEvent(ev);
    } else {
        return MotionEventCompat.getActionMasked(ev) != MotionEvent.ACTION_MOVE && super.onTouchEvent(ev);
    }
}