У меня есть ViewPager
, которые можно отключить или включить мазковые штрихи:Отключить салфетки на некоторых фрагментов в 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
:
FATAL ИСКЛЮЧЕНИЕ:
main java.lang.IllegalArgumentException: pointerIndex вне допустимого диапазона
на android.view.Moti onEvent.nativeGetAxisValue (Родной метод)
в android.view.MotionEvent.getX (MotionEvent.java:1979)
в android.support.v4.view.MotionEventCompatEclair.getX (MotionEventCompatEclair.java:32)
на андроид. 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)
at com.test.debugpager.ConfigurablePager.onTouchEvent (ConfigurablePager.java:39)
по android.view.View.dispatchTouchEvent (Vi ew.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
сохранить последний pointerId и получить несогласованное состояние (некоторые t ouch события, упавшие на 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);
}
}
}