禁用在ViewPager中滑动某些片段

时间:2016-04-11 14:54:50

标签: 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();
    }

    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:pointerIndex超出范围
      在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.dispatchTransformedTouchEvent(ViewGroup.java:2203)
      在android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1938)
      在android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2231)
      在android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1952)
      在android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2209)

它发生了,因为ViewPager保存了最后一个指针ID并且获得了不一致状态(某些触摸事件被onInterceptTouchEvent丢弃),例如ACTION_MOVE上次触摸事件的mActivePointerId不正确(请参阅ViewPager.java的来源)

问题
是否可以通过其他方式禁用某些片段的滑动,也可以不覆盖onInterceptTouchEvent

ViewPager来源(onTouchEvent):

case MotionEvent.ACTION_MOVE:
    if (!mIsBeingDragged) {
        final int pointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId);
        final float x = MotionEventCompat.getX(ev, pointerIndex);
        final float xDiff = Math.abs(x - mLastMotionX);
        final float y = MotionEventCompat.getY(ev, pointerIndex);
        final float yDiff = Math.abs(y - mLastMotionY);
        if (DEBUG) Log.v(TAG, "Moved x to " + x + "," + y + " diff=" + xDiff + "," + yDiff);
        if (xDiff > mTouchSlop && xDiff > yDiff) {
            if (DEBUG) Log.v(TAG, "Starting drag!");
            mIsBeingDragged = true;
            requestParentDisallowInterceptTouchEvent(true);
            mLastMotionX = x - mInitialMotionX > 0 ? mInitialMotionX + mTouchSlop :
            mInitialMotionX - mTouchSlop;
            mLastMotionY = y;
            setScrollState(SCROLL_STATE_DRAGGING);
            setScrollingCacheEnabled(true);

            // Disallow Parent Intercept, just in case
            ViewParent parent = getParent();
            if (parent != null) {
                parent.requestDisallowInterceptTouchEvent(true);
            }
        }
    }

1 个答案:

答案 0 :(得分:1)

解决

我已专心阅读android guide关于std::ifstream file("text.txt"); std::string str; while (std::getline(file, str)) { cout << str; //call function to to retrieve words of str in memory not in file } 和已分析ViewGroup ViewPager来源的手势识别问题。在此我认识到onTouchEvent仅针对ViewPager事件进行了细分,因此我们不应仅针对此操作调用触控回调,我们应先遵守基本ACTION_MOVE ViewGroup结果调用基类onInterceptTouchEvent

根据这条规则,我更改了onTouchEvent代码:

ViewPager