Example usage for android.view MotionEvent getX

List of usage examples for android.view MotionEvent getX

Introduction

In this page you can find the example usage for android.view MotionEvent getX.

Prototype

public final float getX() 

Source Link

Document

#getX(int) for the first pointer index (may be an arbitrary pointer identifier).

Usage

From source file:com.bizcom.vc.widget.cus.SubsamplingScaleImageView.java

private void setGestureDetector(final Context context) {
    this.detector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
        @Override/*  w w w . j  av a 2 s  .  c om*/
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            if (panEnabled && readySent && vTranslate != null && e1 != null && e2 != null
                    && (Math.abs(e1.getX() - e2.getX()) > 50 || Math.abs(e1.getY() - e2.getY()) > 50)
                    && (Math.abs(velocityX) > 500 || Math.abs(velocityY) > 500) && !isZooming) {
                PointF vTranslateEnd = new PointF(vTranslate.x + (velocityX * 0.25f),
                        vTranslate.y + (velocityY * 0.25f));
                float sCenterXEnd = ((getWidth() / 2) - vTranslateEnd.x) / scale;
                float sCenterYEnd = ((getHeight() / 2) - vTranslateEnd.y) / scale;
                new AnimationBuilder(new PointF(sCenterXEnd, sCenterYEnd)).withEasing(EASE_OUT_QUAD)
                        .withPanLimited(false).start();
                return true;
            }
            return super.onFling(e1, e2, velocityX, velocityY);
        }

        @Override
        public boolean onSingleTapConfirmed(MotionEvent e) {
            if (doubleTapListener != null) {
                return doubleTapListener.onSingleTapConfirmed(e);
            }
            performClick();
            return true;
        }

        @Override
        public boolean onDoubleTap(MotionEvent e) {
            if (zoomEnabled && readySent && vTranslate != null) {
                float doubleTapZoomScale = Math.min(maxScale,
                        SubsamplingScaleImageView.this.doubleTapZoomScale);
                boolean zoomIn = scale <= doubleTapZoomScale * 0.9;
                float targetScale = zoomIn ? doubleTapZoomScale
                        : Math.min(getWidth() / (float) sWidth(), getHeight() / (float) sHeight());
                PointF targetSCenter = viewToSourceCoord(new PointF(e.getX(), e.getY()));
                if (doubleTapZoomStyle == ZOOM_FOCUS_CENTER_IMMEDIATE) {
                    setScaleAndCenter(targetScale, targetSCenter);
                } else if (doubleTapZoomStyle == ZOOM_FOCUS_CENTER || !zoomIn) {
                    new AnimationBuilder(targetScale, targetSCenter).withInterruptible(false).start();
                } else if (doubleTapZoomStyle == ZOOM_FOCUS_FIXED) {
                    new AnimationBuilder(targetScale, targetSCenter, new PointF(e.getX(), e.getY()))
                            .withInterruptible(false).start();
                }

                // Hacky solution for #15 - after a double tap the
                // GestureDetector gets in a state where the next
                // fling is ignored, so here we replace it with a
                // new one.
                setGestureDetector(context);

                invalidate();
                return true;
            }
            return super.onDoubleTapEvent(e);
        }
    });
}

From source file:com.android.launcher3.ItemTouchHelper.java

View findChildView(MotionEvent event) {
    // first check elevated views, if none, then call RV
    final float x = event.getX();
    final float y = event.getY();
    if (mSelected != null) {
        final View selectedView = mSelected.itemView;
        if (hitTest(selectedView, x, y, mSelectedStartX + mDx, mSelectedStartY + mDy)) {
            return selectedView;
        }/*from  w w w.j ava2s  .  co  m*/
    }
    for (int i = mRecoverAnimations.size() - 1; i >= 0; i--) {
        final RecoverAnimation anim = mRecoverAnimations.get(i);
        final View view = anim.mViewHolder.itemView;
        if (hitTest(view, x, y, anim.mX, anim.mY)) {
            return view;
        }
    }
    return mRecyclerView.findChildViewUnder(x, y);
}

From source file:com.aviary.android.feather.sdk.widget.AviaryWorkspace.java

@Override
public boolean onTouchEvent(MotionEvent ev) {

    final int action = ev.getAction();

    if (!isEnabled()) {
        if (!mScroller.isFinished()) {
            mScroller.abortAnimation();/*www  . j  a v  a 2 s  .  c  o m*/
        }
        snapToScreen(mCurrentScreen);
        return false; // We don't want the events. Let them fall through to the all
                      // apps view.
    }

    acquireVelocityTrackerAndAddMovement(ev);

    switch (action & MotionEvent.ACTION_MASK) {
    case MotionEvent.ACTION_DOWN:
        /*
         * If being flinged and user touches, stop the fling. isFinished will be
         * false if being flinged.
         */

        if (!mScroller.isFinished()) {
            mScroller.abortAnimation();
        }

        // Remember where the motion event started
        mLastMotionX = ev.getX();
        mLastMotionX2 = ev.getX();
        mActivePointerId = ev.getPointerId(0);
        if (mTouchState == TOUCH_STATE_SCROLLING) {
            enableChildrenCache(mCurrentScreen - 1, mCurrentScreen + 1);
        }
        break;
    case MotionEvent.ACTION_MOVE:
        if (mTouchState == TOUCH_STATE_SCROLLING) {
            // Scroll to follow the motion event
            final int pointerIndex = ev.findPointerIndex(mActivePointerId);
            final float x = ev.getX(pointerIndex);
            final float deltaX = mLastMotionX - x;
            final float deltaX2 = mLastMotionX2 - x;
            final int mode = mOverScrollMode;

            mLastMotionX = x;

            if (deltaX < 0) {
                mTouchX += deltaX;
                mSmoothingTime = System.nanoTime() / NANOTIME_DIV;

                if (mTouchX < 0 && mode != OVER_SCROLL_NEVER) {
                    mTouchX = mLastMotionX = 0;
                    // mLastMotionX = x;

                    if (mEdgeGlowLeft != null && deltaX2 < 0) {
                        mEdgeGlowLeft.onPull((float) deltaX / getWidth());
                        if (!mEdgeGlowRight.isFinished()) {
                            mEdgeGlowRight.onRelease();
                        }
                    }
                }

                invalidate();

            } else if (deltaX > 0) {
                final int totalWidth = getScreenScrollPositionX(mItemCount - 1);
                final float availableToScroll = getScreenScrollPositionX(mItemCount) - mTouchX;
                mSmoothingTime = System.nanoTime() / NANOTIME_DIV;

                mTouchX += Math.min(availableToScroll, deltaX);

                if (availableToScroll <= getWidth() && mode != OVER_SCROLL_NEVER) {
                    mTouchX = mLastMotionX = totalWidth;
                    // mLastMotionX = x;

                    if (mEdgeGlowLeft != null && deltaX2 > 0) {
                        mEdgeGlowRight.onPull((float) deltaX / getWidth());
                        if (!mEdgeGlowLeft.isFinished()) {
                            mEdgeGlowLeft.onRelease();
                        }
                    }
                }
                invalidate();

            } else {
                awakenScrollBars();
            }
        }
        break;
    case MotionEvent.ACTION_UP:
        if (mTouchState == TOUCH_STATE_SCROLLING) {
            final VelocityTracker velocityTracker = mVelocityTracker;
            velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
            final int velocityX = (int) velocityTracker.getXVelocity(mActivePointerId);

            final int screenWidth = getWidth();
            final int whichScreen = (getScrollX() + (screenWidth / 2)) / screenWidth;
            final float scrolledPos = (float) getScrollX() / screenWidth;

            if (velocityX > SNAP_VELOCITY && mCurrentScreen > 0) {
                // Fling hard enough to move left.
                // Don't fling across more than one screen at a time.
                final int bound = scrolledPos < whichScreen ? mCurrentScreen - 1 : mCurrentScreen;
                snapToScreen(Math.min(whichScreen, bound), velocityX, true);
            } else if (velocityX < -SNAP_VELOCITY && mCurrentScreen < mItemCount - 1) {
                // Fling hard enough to move right
                // Don't fling across more than one screen at a time.
                final int bound = scrolledPos > whichScreen ? mCurrentScreen + 1 : mCurrentScreen;
                snapToScreen(Math.max(whichScreen, bound), velocityX, true);
            } else {
                snapToScreen(whichScreen, 0, true);
            }

            if (mEdgeGlowLeft != null) {
                mEdgeGlowLeft.onRelease();
                mEdgeGlowRight.onRelease();
            }
        }
        mTouchState = TOUCH_STATE_REST;
        mActivePointerId = INVALID_POINTER;
        releaseVelocityTracker();
        break;
    case MotionEvent.ACTION_CANCEL:
        if (mTouchState == TOUCH_STATE_SCROLLING) {
            final int screenWidth = getWidth();
            final int whichScreen = (getScrollX() + (screenWidth / 2)) / screenWidth;
            snapToScreen(whichScreen, 0, true);
        }
        mTouchState = TOUCH_STATE_REST;
        mActivePointerId = INVALID_POINTER;
        releaseVelocityTracker();

        if (mEdgeGlowLeft != null) {
            mEdgeGlowLeft.onRelease();
            mEdgeGlowRight.onRelease();
        }

        break;
    case MotionEvent.ACTION_POINTER_UP:
        onSecondaryPointerUp(ev);
        break;
    }

    return true;
}

From source file:cn.oddcloud.www.navigationtabbar.ntb.NavigationTabBar.java

@Override
public boolean onTouchEvent(final MotionEvent event) {
    // Return if animation is running
    if (mAnimator.isRunning())
        return true;
    // If is not idle state, return
    if (mScrollState != ViewPager.SCROLL_STATE_IDLE)
        return true;

    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
        // Action down touch
        mIsActionDown = true;/*from   w ww. java2  s . c  o m*/
        if (!mIsViewPagerMode)
            break;
        if (!mIsSwiped)
            break;
        // Detect if we touch down on pointer, later to move
        if (mIsHorizontalOrientation)
            mIsPointerActionDown = (int) (event.getX() / mModelSize) == mIndex;
        else
            mIsPointerActionDown = (int) (event.getY() / mModelSize) == mIndex;
        break;
    case MotionEvent.ACTION_MOVE:
        // If pointer touched, so move
        if (mIsPointerActionDown) {
            if (mIsHorizontalOrientation)
                mViewPager.setCurrentItem((int) (event.getX() / mModelSize), true);
            else
                mViewPager.setCurrentItem((int) (event.getY() / mModelSize), true);
            break;
        }
        if (mIsActionDown)
            break;
    case MotionEvent.ACTION_UP:
        // Press up and set model index relative to current coordinate
        if (mIsActionDown) {
            playSoundEffect(SoundEffectConstants.CLICK);
            if (mIsHorizontalOrientation)
                setModelIndex((int) (event.getX() / mModelSize));
            else
                setModelIndex((int) (event.getY() / mModelSize));
        }
    case MotionEvent.ACTION_CANCEL:
    case MotionEvent.ACTION_OUTSIDE:
    default:
        // Reset action touch variables
        mIsPointerActionDown = false;
        mIsActionDown = false;
        break;
    }

    return true;
}

From source file:cn.bingoogolapple.swipebacklayout.BGASwipeBackLayout.java

@Override
public boolean onTouchEvent(MotionEvent ev) {
    // ========================  START ========================
    if (!isSwipeBackEnable()) {
        return super.onTouchEvent(ev);
    }/*  ww  w. j  a  v  a 2s  .co m*/
    // ========================  END ========================

    if (!mCanSlide) {
        return super.onTouchEvent(ev);
    }

    mDragHelper.processTouchEvent(ev);

    final int action = ev.getAction();
    boolean wantTouchEvents = true;

    switch (action & MotionEventCompat.ACTION_MASK) {
    case MotionEvent.ACTION_DOWN: {
        mMoveState = MOVE_STATE_LEFT;
        final float x = ev.getX();
        final float y = ev.getY();
        mInitialMotionX = x;
        mInitialMotionY = y;
        break;
    }

    case MotionEvent.ACTION_UP: {
        if (mSlideableView.getLeft() > mSlideRange * mSwipeBackThreshold) {
            mMoveState = MOVE_STATE_RIGHT;
        } else {
            mMoveState = MOVE_STATE_LEFT;
        }
        if (isDimmed(mSlideableView)) {
            final float x = ev.getX();
            final float y = ev.getY();
            final float dx = x - mInitialMotionX;
            final float dy = y - mInitialMotionY;
            final int slop = mDragHelper.getTouchSlop();
            if (dx * dx + dy * dy < slop * slop && mDragHelper.isViewUnder(mSlideableView, (int) x, (int) y)) {
                // Taps close a dimmed open pane.
                closePane(mSlideableView, 0);
                break;
            }
        }
        break;
    }

    case MotionEvent.ACTION_CANCEL: {
        if (mSlideableView.getLeft() > mSlideRange * mSwipeBackThreshold) {
            mMoveState = MOVE_STATE_RIGHT;
        } else {
            mMoveState = MOVE_STATE_LEFT;
        }
        break;
    }

    default:
        break;
    }

    return wantTouchEvents;
}

From source file:cn.org.eshow.framwork.view.slidingmenu.CustomViewAbove.java

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {

    if (!mEnabled)
        return false;

    final int action = ev.getAction() & MotionEventCompat.ACTION_MASK;

    if (DEBUG)//from   www.  j a v  a 2  s .c om
        if (action == MotionEvent.ACTION_DOWN)
            Log.v(TAG, "Received ACTION_DOWN");

    if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP
            || (action != MotionEvent.ACTION_DOWN && mIsUnableToDrag)) {
        endDrag();
        return false;
    }

    switch (action) {
    case MotionEvent.ACTION_MOVE:
        determineDrag(ev);
        break;
    case MotionEvent.ACTION_DOWN:
        int index = MotionEventCompat.getActionIndex(ev);
        mActivePointerId = MotionEventCompat.getPointerId(ev, index);
        if (mActivePointerId == INVALID_POINTER)
            break;
        mLastMotionX = mInitialMotionX = MotionEventCompat.getX(ev, index);
        mLastMotionY = MotionEventCompat.getY(ev, index);
        if (thisTouchAllowed(ev)) {
            mIsBeingDragged = false;
            mIsUnableToDrag = false;
            if (isMenuOpen() && mViewBehind.menuTouchInQuickReturn(mContent, mCurItem, ev.getX() + mScrollX)) {
                mQuickReturn = true;
            }
        } else {
            mIsUnableToDrag = true;
        }
        break;
    case MotionEventCompat.ACTION_POINTER_UP:
        onSecondaryPointerUp(ev);
        break;
    }

    if (!mIsBeingDragged) {
        if (mVelocityTracker == null) {
            mVelocityTracker = VelocityTracker.obtain();
        }
        mVelocityTracker.addMovement(ev);
    }
    return mIsBeingDragged || mQuickReturn;
}

From source file:com.aidy.bottomdrawerlayout.AllDrawerLayout.java

@Override
public boolean onTouchEvent(MotionEvent ev) {
    Log.i(TAG, "onTouchEvent()");
    final int action = ev.getAction();
    boolean wantTouchEvents = true;
    try {// www . j a  v a  2  s  . co m

        mLeftDragger.processTouchEvent(ev);
        mRightDragger.processTouchEvent(ev);
        mTopDragger.processTouchEvent(ev);
        mBottomDragger.processTouchEvent(ev);

        switch (action & MotionEventCompat.ACTION_MASK) {
        case MotionEvent.ACTION_DOWN: {
            Log.i(TAG, "onTouchEvent() -- ACTION_DOWN");
            final float x = ev.getX();
            final float y = ev.getY();
            mInitialMotionX = x;
            mInitialMotionY = y;
            mDisallowInterceptRequested = false;
            mChildrenCanceledTouch = false;
            break;
        }

        case MotionEvent.ACTION_UP: {
            Log.i(TAG, "onTouchEvent() -- ACTION_UP");
            final float x = ev.getX();
            final float y = ev.getY();
            boolean peekingOnly = true;
            final View touchedView = mLeftDragger.findTopChildUnder((int) x, (int) y);
            if (touchedView != null && isContentView(touchedView)) {
                final float dx = x - mInitialMotionX;
                final float dy = y - mInitialMotionY;
                final int slop = mLeftDragger.getTouchSlop();
                if (dx * dx + dy * dy < slop * slop) {
                    // Taps close a dimmed open drawer but only if it isn't
                    // locked open.
                    final View openDrawer = findOpenDrawer();
                    if (openDrawer != null) {
                        peekingOnly = getDrawerLockMode(openDrawer) == LOCK_MODE_LOCKED_OPEN;
                    }
                }
            }
            closeDrawers(peekingOnly);
            mDisallowInterceptRequested = false;
            break;
        }

        case MotionEvent.ACTION_CANCEL: {
            Log.i(TAG, "onTouchEvent() -- ACTION_CANCEL");
            closeDrawers(true);
            mDisallowInterceptRequested = false;
            mChildrenCanceledTouch = false;
            break;
        }
        }
    } catch (IllegalArgumentException e) {
        // TODO: handle exception
    }
    boolean result = wantTouchEvents;
    Log.i(TAG, "onTouchEvent() -- result = " + result);
    return result;
}

From source file:com.aidy.bottomdrawerlayout.AllDrawerLayout.java

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    Log.i(TAG, "onInterceptTouchEvent()");
    final int action = MotionEventCompat.getActionMasked(ev);

    // "|" used deliberately here; both methods should be invoked.
    final boolean interceptForDrag = mLeftDragger.shouldInterceptTouchEvent(ev)
            | mRightDragger.shouldInterceptTouchEvent(ev) | mTopDragger.shouldInterceptTouchEvent(ev)
            | mBottomDragger.shouldInterceptTouchEvent(ev);
    boolean interceptForTap = false;
    switch (action) {
    case MotionEvent.ACTION_DOWN: {
        Log.i(TAG, "onInterceptTouchEvent() -- ACTION_DOWN");
        final float x = ev.getX();
        final float y = ev.getY();
        mInitialMotionX = x;/*from  ww w  .ja v  a2  s. c  om*/
        mInitialMotionY = y;
        if (mScrimOpacity > 0 && isContentView(mLeftDragger.findTopChildUnder((int) x, (int) y))) {
            interceptForTap = true;
        }
        mDisallowInterceptRequested = false;
        mChildrenCanceledTouch = false;
        break;
    }

    case MotionEvent.ACTION_MOVE: {
        Log.i(TAG, "onInterceptTouchEvent() -- ACTION_MOVE");
        // If we cross the touch slop, don't perform the delayed peek for an
        // edge touch.
        if (mLeftDragger.checkTouchSlop(ViewDragHelper.DIRECTION_ALL)) {
            Log.i(TAG, "onInterceptTouchEvent() -- ACTION_MOVE -- 2");
            mLeftCallback.removeCallbacks();
            mRightCallback.removeCallbacks();
            mTopCallback.removeCallbacks();
            mBottomCallback.removeCallbacks();
        }
        break;
    }

    case MotionEvent.ACTION_CANCEL:
    case MotionEvent.ACTION_UP: {
        Log.i(TAG, "onInterceptTouchEvent() -- ACTION_CANCEL | ACTION_UP");
        closeDrawers(true);
        mDisallowInterceptRequested = false;
        mChildrenCanceledTouch = false;
    }
    }

    boolean result = interceptForDrag || interceptForTap || hasPeekingDrawer() || mChildrenCanceledTouch;
    Log.i(TAG, "onInterceptTouchEvent() -- result = " + result);
    return result;
}

From source file:com.android.ex.chips.RecipientEditTextView.java

@Override
public void onLongPress(final MotionEvent event) {
    if (mSelectedChip != null)
        return;/*from   ww  w .  j  ava  2 s .  com*/
    final float x = event.getX();
    final float y = event.getY();
    final int offset = putOffsetInRange(x, y);
    final DrawableRecipientChip currentChip = findChip(offset);
    if (currentChip != null)
        // Copy the selected chip email address.
        showCopyDialog(currentChip.getEntry().getDestination());
}

From source file:com.android.launcher2.PagedView.java

@Override
public boolean onTouchEvent(MotionEvent ev) {
    // Skip touch handling if there are no pages to swipe
    if (getChildCount() <= 0)
        return super.onTouchEvent(ev);

    acquireVelocityTrackerAndAddMovement(ev);

    final int action = ev.getAction();

    switch (action & MotionEvent.ACTION_MASK) {
    case MotionEvent.ACTION_DOWN:
        /*/*from ww w  . j  a v  a2s  .  com*/
         * If being flinged and user touches, stop the fling. isFinished
         * will be false if being flinged.
         */
        if (!mScroller.isFinished()) {
            mScroller.abortAnimation();
        }

        // Remember where the motion event started
        mDownMotionX = mLastMotionX = ev.getX();
        mLastMotionXRemainder = 0;
        mTotalMotionX = 0;
        mActivePointerId = ev.getPointerId(0);
        if (mTouchState == TOUCH_STATE_SCROLLING) {
            pageBeginMoving();
        }
        break;

    case MotionEvent.ACTION_MOVE:
        if (mTouchState == TOUCH_STATE_SCROLLING) {
            // Scroll to follow the motion event
            final int pointerIndex = ev.findPointerIndex(mActivePointerId);
            final float x = ev.getX(pointerIndex);
            final float deltaX = mLastMotionX + mLastMotionXRemainder - x;

            mTotalMotionX += Math.abs(deltaX);

            // Only scroll and update mLastMotionX if we have moved some discrete amount.  We
            // keep the remainder because we are actually testing if we've moved from the last
            // scrolled position (which is discrete).
            if (Math.abs(deltaX) >= 1.0f) {
                mTouchX += deltaX;
                mSmoothingTime = System.nanoTime() / NANOTIME_DIV;
                if (!mDeferScrollUpdate) {
                    scrollBy((int) deltaX, 0);
                    if (DEBUG)
                        Log.d(TAG, "onTouchEvent().Scrolling: " + deltaX);
                } else {
                    invalidate();
                }
                mLastMotionX = x;
                mLastMotionXRemainder = deltaX - (int) deltaX;
            } else {
                awakenScrollBars();
            }
        } else {
            determineScrollingStart(ev);
        }
        break;

    case MotionEvent.ACTION_UP:
        if (mTouchState == TOUCH_STATE_SCROLLING) {
            final int activePointerId = mActivePointerId;
            final int pointerIndex = ev.findPointerIndex(activePointerId);
            final float x = ev.getX(pointerIndex);
            final VelocityTracker velocityTracker = mVelocityTracker;
            velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
            int velocityX = (int) velocityTracker.getXVelocity(activePointerId);
            final int deltaX = (int) (x - mDownMotionX);
            final int pageWidth = getScaledMeasuredWidth(getPageAt(mCurrentPage));
            boolean isSignificantMove = Math.abs(deltaX) > pageWidth * SIGNIFICANT_MOVE_THRESHOLD;

            mTotalMotionX += Math.abs(mLastMotionX + mLastMotionXRemainder - x);

            boolean isFling = mTotalMotionX > MIN_LENGTH_FOR_FLING
                    && Math.abs(velocityX) > mFlingThresholdVelocity;

            // In the case that the page is moved far to one direction and then is flung
            // in the opposite direction, we use a threshold to determine whether we should
            // just return to the starting page, or if we should skip one further.
            boolean returnToOriginalPage = false;
            if (Math.abs(deltaX) > pageWidth * RETURN_TO_ORIGINAL_PAGE_THRESHOLD
                    && Math.signum(velocityX) != Math.signum(deltaX) && isFling) {
                returnToOriginalPage = true;
            }

            int finalPage;
            // We give flings precedence over large moves, which is why we short-circuit our
            // test for a large move if a fling has been registered. That is, a large
            // move to the left and fling to the right will register as a fling to the right.
            if (((isSignificantMove && deltaX > 0 && !isFling) || (isFling && velocityX > 0))
                    && mCurrentPage > 0) {
                finalPage = returnToOriginalPage ? mCurrentPage : mCurrentPage - 1;
                snapToPageWithVelocity(finalPage, velocityX);
            } else if (((isSignificantMove && deltaX < 0 && !isFling) || (isFling && velocityX < 0))
                    && mCurrentPage < getChildCount() - 1) {
                finalPage = returnToOriginalPage ? mCurrentPage : mCurrentPage + 1;
                snapToPageWithVelocity(finalPage, velocityX);
            } else {
                snapToDestination();
            }
        } else if (mTouchState == TOUCH_STATE_PREV_PAGE) {
            // at this point we have not moved beyond the touch slop
            // (otherwise mTouchState would be TOUCH_STATE_SCROLLING), so
            // we can just page
            int nextPage = Math.max(0, mCurrentPage - 1);
            if (nextPage != mCurrentPage) {
                snapToPage(nextPage);
            } else {
                snapToDestination();
            }
        } else if (mTouchState == TOUCH_STATE_NEXT_PAGE) {
            // at this point we have not moved beyond the touch slop
            // (otherwise mTouchState would be TOUCH_STATE_SCROLLING), so
            // we can just page
            int nextPage = Math.min(getChildCount() - 1, mCurrentPage + 1);
            if (nextPage != mCurrentPage) {
                snapToPage(nextPage);
            } else {
                snapToDestination();
            }
        } else {
            onUnhandledTap(ev);
        }
        mTouchState = TOUCH_STATE_REST;
        mActivePointerId = INVALID_POINTER;
        releaseVelocityTracker();
        break;

    case MotionEvent.ACTION_CANCEL:
        if (mTouchState == TOUCH_STATE_SCROLLING) {
            snapToDestination();
        }
        mTouchState = TOUCH_STATE_REST;
        mActivePointerId = INVALID_POINTER;
        releaseVelocityTracker();
        break;

    case MotionEvent.ACTION_POINTER_UP:
        onSecondaryPointerUp(ev);
        break;
    }

    return true;
}