ViewPagerのsetEnabledを設定してもスワイプを無効化できない。
そこでググったら
様々な方法を編み出してて笑った。
みんなViewPager好き過ぎ。
結局ViewPagerを継承し、setPagingEnabledを追加する方法を採用した。
//引用元 https://code-examples.net/ja/q/773b81 private boolean isPagingEnabled = true; @Override public boolean onTouchEvent(MotionEvent event) { return this.isPagingEnabled && super.onTouchEvent(event); //読み間違いに注意 } @Override public boolean onInterceptTouchEvent(MotionEvent event) { return this.isPagingEnabled && super.onInterceptTouchEvent(event); //読み間違いに注意 }
fakeDragやonTouch{return true}も試したが、Androidの流儀に従ってinterceptを制御した方が他のViewとの連携がスマートにできた。
2019/10/21追記
onTouchの最中にスワイプを無効化し、いくつかタッチ操作の後に、有効化された場合、ViewPagerの内部で保持していたポインタID(ViewPagerのメンバ変数actionPointerId)がMotionEventに存在しないと
//ViewPager#onInterceptTouchEvent(MotionEvent ev)内
//switch case ACTION_MOVE節
final int pointerIndex = ev.findPointerIndex(activePointerId);
で例外が発生する。
これは、ACTION_DOWNイベントを生成してViewPagerの内部状態を変化させることで回避できた。
private boolean isPagingEnabled = true; private boolean onEnable = false;
@Override public boolean onInterceptTouchEvent(MotionEvent ev) { if(onEnable){ //有効にされた直後に一度だけ通る onEnable = false; //以下の条件の時にsuper#onInterceptTouchEvent内で例外が発生するのを阻止 if(ev.getActionMasked() == MotionEvent.ACTION_MOVE){ MotionEvent.PointerProperties properties = new MotionEvent.PointerProperties(); properties.id = ev.getPointerId(0); MotionEvent.PointerCoords coords = new MotionEvent.PointerCoords(); ev.getPointerCoords(0, coords); //ViewPagerにダミーTouchEventを流し込んで、ViewPager内で保持するPointerIDを更新する super.onInterceptTouchEvent( MotionEvent.obtain(ev.getDownTime(), ev.getEventTime(), MotionEvent.ACTION_DOWN, ev.getPointerCount(), new MotionEvent.PointerProperties[]{properties}, new MotionEvent.PointerCoords[]{coords}, ev.getMetaState(), ev.getButtonState(), ev.getXPrecision(), ev.getYPrecision(), ev.getDeviceId(), ev.getEdgeFlags(), ev.getSource(), ev.getFlags()) ); } } return this.isPagingEnabled && super.onInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent ev) { return this.isPagingEnabled && super.onTouchEvent(ev); } public void setPagingEnabled(boolean isPagingEnabled) { if(this.isPagingEnabled != isPagingEnabled){ onEnable = isPagingEnabled; //有効化された、直後のonInterceptTouchで処理 } this.isPagingEnabled = isPagingEnabled; } public boolean getPagingEnabled(){ return isPagingEnabled; }