@Override public boolean dispatchTouchEvent(@NonNull MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_MOVE: float deltaX = prevX - ev.getX(); if (!drag && Math.abs(deltaX) > mTouchSlop) { final ViewParent parent = getParent(); if (parent != null) { parent.requestDisallowInterceptTouchEvent(true); } drag = true; if (deltaX > 0) { deltaX -= mTouchSlop; } else { deltaX += mTouchSlop; } } if (drag) { final int oldX = getScrollX(); final int range = getScrollRange(); boolean canOverscroll = overscrollMode == OVER_SCROLL_ALWAYS || (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && range > 0); if (canOverscroll) { float pulledToY = oldX + deltaX; if (pulledToY < 0) { leftGlow.onPull(deltaX / getWidth(), 1.f - ev.getY() / getHeight()); if (!rightGlow.isFinished()) rightGlow.onRelease(); } else if (pulledToY > range) { rightGlow.onPull(deltaX / getWidth(), ev.getY() / getHeight()); if (!leftGlow.isFinished()) leftGlow.onRelease(); } if (leftGlow != null && (!leftGlow.isFinished() || !rightGlow.isFinished())) postInvalidate(); } } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: if (drag) { drag = false; if (leftGlow != null) { leftGlow.onRelease(); rightGlow.onRelease(); } } break; } prevX = ev.getX(); return super.dispatchTouchEvent(ev); }