synchronized boolean handleTouchEvent(MotionEvent event, boolean isOnTouchEvent) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // remember page we started on... lastPageIndex = getPageIndexFromAngle(accumulatedAngle); lastPosition = orientationVertical ? event.getY() : event.getX(); return isOnTouchEvent; case MotionEvent.ACTION_MOVE: float delta = orientationVertical ? (lastPosition - event.getY()) : (lastPosition - event.getX()); if (Math.abs(delta) > controller.getTouchSlop()) { setState(STATE_TOUCH); forward = delta > 0; } if (state == STATE_TOUCH) { if (Math.abs(delta) > minMovement) // ignore small movements forward = delta > 0; controller.showFlipAnimation(); float angleDelta; if (orientationVertical) angleDelta = 180 * delta / controller.getContentHeight() * movementRate; else angleDelta = 180 * delta / controller.getContentWidth() * movementRate; if (Math.abs(angleDelta) > maxTouchMoveAngle) // prevent // large // delta // when // moving // too fast angleDelta = Math.signum(angleDelta) * maxTouchMoveAngle; // do not flip more than one page with one touch... if (Math.abs(getPageIndexFromAngle(accumulatedAngle + angleDelta) - lastPageIndex) <= 1) { accumulatedAngle += angleDelta; } // Bounce the page for the first and the last page if (frontCards.getIndex() == maxIndex - 1) { // the last page if (accumulatedAngle > frontCards.getIndex() * 180 + maxTipAngle) accumulatedAngle = frontCards.getIndex() * 180 + maxTipAngle; } else if (accumulatedAngle < -maxTipAngle) accumulatedAngle = -maxTipAngle; int anglePageIndex = getPageIndexFromAngle(accumulatedAngle); if (accumulatedAngle >= 0) { if (anglePageIndex != frontCards.getIndex()) { if (anglePageIndex == frontCards.getIndex() - 1) { // moved // to // previous // page swapCards(); // frontCards becomes the backCards frontCards.resetWithIndex(backCards.getIndex() - 1); controller.flippedToView(anglePageIndex, false); } else if (anglePageIndex == frontCards.getIndex() + 1) { // moved // to // next // page swapCards(); backCards.resetWithIndex(frontCards.getIndex() + 1); controller.flippedToView(anglePageIndex, false); } else throw new RuntimeException( String.format( "Inconsistent states: anglePageIndex: %d, accumulatedAngle %.1f, frontCards %d, backCards %d", anglePageIndex, accumulatedAngle, frontCards.getIndex(), backCards.getIndex())); } } lastPosition = orientationVertical ? event.getY() : event.getX(); controller.getSurfaceView().requestRender(); return true; } return isOnTouchEvent; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: if (state == STATE_TOUCH) { if (accumulatedAngle < 0) forward = true; else if (accumulatedAngle > frontCards.getIndex() * 180 && frontCards.getIndex() == maxIndex - 1) forward = false; setState(STATE_AUTO_ROTATE); controller.getSurfaceView().requestRender(); } return isOnTouchEvent; } return false; }