Example usage for android.view VelocityTracker getYVelocity

List of usage examples for android.view VelocityTracker getYVelocity

Introduction

In this page you can find the example usage for android.view VelocityTracker getYVelocity.

Prototype

public float getYVelocity(int id) 

Source Link

Document

Retrieve the last computed Y velocity.

Usage

From source file:Main.java

public static void velocityTrackerPointerUpCleanUpIfNecessary(MotionEvent ev, VelocityTracker tracker) {

    // Check the dot product of current velocities.
    // If the pointer that left was opposing another velocity vector, clear.
    tracker.computeCurrentVelocity(1000, mMaximumFlingVelocity);
    final int upIndex = ev.getActionIndex();
    final int id1 = ev.getPointerId(upIndex);
    final float x1 = tracker.getXVelocity(id1);
    final float y1 = tracker.getYVelocity(id1);
    for (int i = 0, count = ev.getPointerCount(); i < count; i++) {
        if (i == upIndex)
            continue;

        final int id2 = ev.getPointerId(i);
        final float x = x1 * tracker.getXVelocity(id2);
        final float y = y1 * tracker.getYVelocity(id2);

        final float dot = x + y;
        if (dot < 0) {
            tracker.clear();// w  w  w  . j av a2 s . com
            break;
        }
    }
}

From source file:com.gu.swiperefresh.SwipeRefreshPlush.java

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    ensureTarget();//from   w  w  w  .  j a  v  a  2 s.  c  om

    final int action = MotionEventCompat.getActionMasked(ev);
    int pointerIndex;

    if (mReturningToStart && action == MotionEvent.ACTION_DOWN) {
        mReturningToStart = false;
    }
    if (!isEnabled() || (!canLoadMore() && !canRefresh()) || mReturningToStart || mRefreshController.isRefresh()
            || mNestedScrollInProgress) {
        // Fail fast if we're not in a state where a swipe is possible
        return false;
    }

    switch (action) {
    case MotionEvent.ACTION_DOWN:
        mRefreshController.setTargetOffsetTopAndBottom(
                mRefreshController.getCurrentTargetOffsetTop() - mRefreshView.getTop(), true);
        mActivePointerId = ev.getPointerId(0);
        mIsBeingDragUp = false;
        mIsBeingDragDown = false;

        pointerIndex = ev.findPointerIndex(mActivePointerId);
        if (pointerIndex < 0) {
            return false;
        }
        mInitialDownY = ev.getY(pointerIndex);
        initOrResetVelocityTracker();
        mVelocityTracker.addMovement(ev);
        break;

    case MotionEvent.ACTION_MOVE:
        if (mActivePointerId == INVALID_POINTER) {
            return false;
        }
        mVelocityTracker.addMovement(ev);
        pointerIndex = ev.findPointerIndex(mActivePointerId);
        if (pointerIndex < 0) {
            return false;
        }
        final float y = ev.getY(pointerIndex);
        startDragging(y);
        break;

    case MotionEventCompat.ACTION_POINTER_UP:
        onSecondaryPointerUp(ev);
        break;

    case MotionEvent.ACTION_UP:
        final VelocityTracker velocityTracker = mVelocityTracker;
        velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
        float initialVelocity = velocityTracker.getYVelocity(mActivePointerId);
        Log.d(TAG, "fling:" + initialVelocity);
        if (Math.abs(initialVelocity) > mMinimumVelocity) {
            flingWithNestedDispatch(0, -initialVelocity);
        }
        releaseVelocityTracker();
        break;
    case MotionEvent.ACTION_CANCEL:
        mIsBeingDragUp = false;
        mActivePointerId = INVALID_POINTER;
        break;
    }

    return mIsBeingDragUp || mIsBeingDragDown;
}

From source file:com.hippo.widget.BothScrollView.java

@Override
public boolean onTouchEvent(MotionEvent ev) {
    initVelocityTrackerIfNotExists();// www .  j a v  a 2  s.c  om
    mVelocityTracker.addMovement(ev);

    final int action = ev.getAction();

    switch (action & MotionEvent.ACTION_MASK) {
    case MotionEvent.ACTION_DOWN: {
        if (getChildCount() == 0) {
            return false;
        }
        if ((mIsBeingDragged = !mScroller.isFinished())) {
            final ViewParent parent = getParent();
            if (parent != null) {
                parent.requestDisallowInterceptTouchEvent(true);
            }
        }

        /*
         * 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 = (int) ev.getX();
        mLastMotionY = (int) ev.getY();
        mActivePointerId = ev.getPointerId(0);
        break;
    }
    case MotionEvent.ACTION_MOVE:
        final int activePointerIndex = ev.findPointerIndex(mActivePointerId);
        if (activePointerIndex == -1) {
            Log.e(TAG, "Invalid pointerId=" + mActivePointerId + " in onTouchEvent");
            break;
        }
        final int x = (int) ev.getX(activePointerIndex);
        final int y = (int) ev.getY(activePointerIndex);
        int deltaX = mLastMotionX - x;
        int deltaY = mLastMotionY - y;
        if (!mIsBeingDragged && (Math.abs(deltaX) > mTouchSlop || Math.abs(deltaY) > mTouchSlop)) {
            final ViewParent parent = getParent();
            if (parent != null) {
                parent.requestDisallowInterceptTouchEvent(true);
            }
            mIsBeingDragged = true;
            if (deltaX > 0) {
                deltaX -= mTouchSlop;
                deltaX = Math.max(0, deltaX);
            } else {
                deltaX += mTouchSlop;
                deltaX = Math.min(0, deltaX);
            }
            if (deltaY > 0) {
                deltaY -= mTouchSlop;
                deltaY = Math.max(0, deltaY);
            } else {
                deltaY += mTouchSlop;
                deltaY = Math.min(0, deltaY);
            }
        }
        if (mIsBeingDragged) {
            // Scroll to follow the motion event
            mLastMotionX = x;
            mLastMotionY = y;

            final int oldX = getScrollX();
            final int oldY = getScrollY();
            final int horizontalRange = getHorizontalScrollRange();
            final int verticalRange = getVerticalScrollRange();
            final int overscrollMode = getOverScrollMode();
            final boolean canOverscroll = overscrollMode == OVER_SCROLL_ALWAYS
                    || (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS
                            && (horizontalRange > 0 || verticalRange > 0));

            // Calling overScrollBy will call onOverScrolled, which
            // calls onScrollChanged if applicable.
            overScrollBy(deltaX, deltaY, oldX, oldY, horizontalRange, verticalRange, mOverscrollDistance,
                    mOverscrollDistance, true);

            if (canOverscroll) {
                final int pulledToX = oldX + deltaX;
                final int pulledToY = oldY + deltaY;
                if (pulledToX < 0) {
                    mEdgeGlowLeft.onPull((float) deltaX / getWidth());
                    if (!mEdgeGlowRight.isFinished()) {
                        mEdgeGlowRight.onRelease();
                    }
                } else if (pulledToX > horizontalRange) {
                    mEdgeGlowRight.onPull((float) deltaX / getWidth());
                    if (!mEdgeGlowLeft.isFinished()) {
                        mEdgeGlowLeft.onRelease();
                    }
                }
                if (pulledToY < 0) {
                    mEdgeGlowTop.onPull((float) deltaY / getHeight());
                    if (!mEdgeGlowBottom.isFinished()) {
                        mEdgeGlowBottom.onRelease();
                    }
                } else if (pulledToY > verticalRange) {
                    mEdgeGlowBottom.onPull((float) deltaY / getHeight());
                    if (!mEdgeGlowTop.isFinished()) {
                        mEdgeGlowTop.onRelease();
                    }
                }
                if (mEdgeGlowLeft != null && (!mEdgeGlowLeft.isFinished() || !mEdgeGlowRight.isFinished()
                        || !mEdgeGlowTop.isFinished() || !mEdgeGlowBottom.isFinished())) {
                    ViewCompat.postInvalidateOnAnimation(this);
                }
            }
        }
        break;
    case MotionEvent.ACTION_UP:
        if (mIsBeingDragged) {
            final VelocityTracker velocityTracker = mVelocityTracker;
            velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
            int initialVelocityX = (int) velocityTracker.getXVelocity(mActivePointerId);
            int initialVelocityY = (int) velocityTracker.getYVelocity(mActivePointerId);

            if (getChildCount() > 0) {
                if (Math.abs(initialVelocityX) > mMinimumVelocity
                        || Math.abs(initialVelocityY) > mMinimumVelocity) {
                    fling(-initialVelocityX, -initialVelocityY);
                } else {
                    if (mScroller.springBack(getScrollX(), getScrollY(), 0, getHorizontalScrollRange(), 0,
                            getVerticalScrollRange())) {
                        ViewCompat.postInvalidateOnAnimation(this);
                    }
                }
            }

            mActivePointerId = INVALID_POINTER;
            endDrag();
        }
        break;
    case MotionEvent.ACTION_CANCEL:
        if (mIsBeingDragged && getChildCount() > 0) {
            if (mScroller.springBack(getScrollX(), getScrollY(), 0, getHorizontalScrollRange(), 0,
                    getVerticalScrollRange())) {
                ViewCompat.postInvalidateOnAnimation(this);
            }
            mActivePointerId = INVALID_POINTER;
            endDrag();
        }
        break;
    case MotionEvent.ACTION_POINTER_DOWN: {
        final int index = ev.getActionIndex();
        mLastMotionX = (int) ev.getX(index);
        mLastMotionY = (int) ev.getY(index);
        mActivePointerId = ev.getPointerId(index);
        break;
    }
    case MotionEvent.ACTION_POINTER_UP:
        onSecondaryPointerUp(ev);
        final int index = ev.findPointerIndex(mActivePointerId);
        mLastMotionX = (int) ev.getX(index);
        mLastMotionY = (int) ev.getY(index);
        break;
    }
    return true;
}

From source file:com.bulletnoid.android.widget.StaggeredGridView.StaggeredGridView3.java

@Override
public boolean onTouchEvent(MotionEvent ev) {
    if (!isEnabled()) {
        // A disabled view that is clickable still consumes the touch
        // events, it just doesn't respond to them.
        return isClickable() || isLongClickable();
    }// ww w.  java 2  s .  co m

    final int action = ev.getAction();

    View v;
    int deltaY;

    if (mVelocityTracker == null) {
        mVelocityTracker = VelocityTracker.obtain();
    }
    mVelocityTracker.addMovement(ev);

    switch (action & MotionEvent.ACTION_MASK) {
    case MotionEvent.ACTION_DOWN: {
        mActivePointerId = ev.getPointerId(0);
        final int x = (int) ev.getX();
        final int y = (int) ev.getY();
        int motionPosition = pointToPosition(x, y);
        if (!mDataChanged) {
            if ((mTouchMode != TOUCH_MODE_FLINGING) && (motionPosition >= 0)
                    && (getAdapter().isEnabled(motionPosition))) {
                // User clicked on an actual view (and was not stopping a fling). It might be a
                // click or a scroll. Assume it is a click until proven otherwise
                mTouchMode = TOUCH_MODE_DOWN;
                // FIXME Debounce
                if (mPendingCheckForTap == null) {
                    mPendingCheckForTap = new CheckForTap();
                }
                postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
            } else {
                if (ev.getEdgeFlags() != 0 && motionPosition < 0) {
                    // If we couldn't find a view to click on, but the down event was touching
                    // the edge, we will bail out and try again. This allows the edge correcting
                    // code in ViewRoot to try to find a nearby view to select
                    return false;
                }

                if (mTouchMode == TOUCH_MODE_FLINGING) {
                    // Stopped a fling. It is a scroll.
                    //createScrollingCache();
                    mTouchMode = TOUCH_MODE_DRAGGING;
                    mMotionCorrection = 0;
                    motionPosition = findMotionRow(y);
                    reportScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
                }
            }
        }

        if (motionPosition >= 0) {
            // Remember where the motion event started
            v = getChildAt(motionPosition - mFirstPosition);
            //mMotionViewOriginalTop=v.getTop();
        }
        mLastTouchX = x;
        mLastTouchY = y;
        mMotionPosition = motionPosition;
        mTouchRemainderY = Integer.MIN_VALUE;
        break;
    }

    case MotionEvent.ACTION_MOVE: {
        final int pointerIndex = ev.findPointerIndex(mActivePointerId);
        final int y = (int) ev.getY(pointerIndex);
        deltaY = (int) (y - mLastTouchY);
        switch (mTouchMode) {
        case TOUCH_MODE_DOWN:
        case TOUCH_MODE_TAP:
        case TOUCH_MODE_DONE_WAITING:
            // Check if we have moved far enough that it looks more like a
            // scroll than a tap
            startScrollIfNeeded(deltaY);
            break;
        case TOUCH_MODE_DRAGGING:
            /*if (PROFILE_SCROLLING) {
                if (!mScrollProfilingStarted) {
                    Debug.startMethodTracing("AbsListViewScroll");
                    mScrollProfilingStarted=true;
                }
            }*/

            if (y != mTouchRemainderY) {
                deltaY -= mMotionCorrection;
                int incrementalDeltaY = mTouchRemainderY != Integer.MIN_VALUE ? (int) (y - mTouchRemainderY)
                        : deltaY;

                // No need to do all this work if we're not going to move anyway
                boolean atEdge = false;
                if (incrementalDeltaY != 0) {
                    atEdge = trackMotionScroll(deltaY, true);
                }

                // Check to see if we have bumped into the scroll limit
                if (atEdge && getChildCount() > 0) {
                    // Treat this like we're starting a new scroll from the current
                    // position. This will let the user start scrolling back into
                    // content immediately rather than needing to scroll back to the
                    // point where they hit the limit first.
                    int motionPosition = findMotionRow(y);
                    if (motionPosition >= 0) {
                        final View motionView = getChildAt(motionPosition - mFirstPosition);
                        //mMotionViewOriginalTop=motionView.getTop();
                    }
                    mLastTouchY = y;
                    mMotionPosition = motionPosition;
                    invalidate();
                }
                mTouchRemainderY = y;
            }
            break;
        }

        break;
    }

    case MotionEvent.ACTION_UP: {
        switch (mTouchMode) {
        case TOUCH_MODE_DOWN:
        case TOUCH_MODE_TAP:
        case TOUCH_MODE_DONE_WAITING:
            final int motionPosition = mMotionPosition;
            final View child = getChildAt(motionPosition - mFirstPosition);
            System.out.println("child:" + child + " motionPosition:" + motionPosition);
            if (child != null && !child.hasFocusable()) {
                if (mTouchMode != TOUCH_MODE_DOWN) {
                    child.setPressed(false);
                }

                if (mPerformClick == null) {
                    mPerformClick = new PerformClick();
                }

                final PerformClick performClick = mPerformClick;
                //performClick.mChild=child;
                performClick.mClickMotionPosition = motionPosition;
                performClick.rememberWindowAttachCount();

                //mResurrectToPosition=motionPosition;

                if (mTouchMode == TOUCH_MODE_DOWN || mTouchMode == TOUCH_MODE_TAP) {
                    //mLayoutMode=LAYOUT_NORMAL;
                    if (!mDataChanged && mAdapter.isEnabled(motionPosition)) {
                        mTouchMode = TOUCH_MODE_TAP;
                        layoutChildren(mDataChanged);
                        child.setPressed(true);
                        positionSelector(mMotionPosition, child);
                        setPressed(true);
                        if (mSelector != null) {
                            Drawable d = mSelector.getCurrent();
                            if (d != null && d instanceof TransitionDrawable) {
                                ((TransitionDrawable) d).resetTransition();
                            }
                        }
                        postDelayed(new Runnable() {
                            public void run() {
                                child.setPressed(false);
                                setPressed(false);
                                if (!mDataChanged) {
                                    post(performClick);
                                }
                                mTouchMode = TOUCH_MODE_REST;
                            }
                        }, ViewConfiguration.getPressedStateDuration());
                    } else {
                        mTouchMode = TOUCH_MODE_REST;
                    }
                    return true;
                } else if (!mDataChanged && mAdapter.isEnabled(motionPosition)) {
                    post(performClick);
                }
            }
            mTouchMode = TOUCH_MODE_REST;
            break;
        case TOUCH_MODE_DRAGGING:
            final int childCount = getChildCount();
            if (childCount > 0) {
                /*int top=getFillChildTop();
                int bottom=getFillChildBottom();
                if (mFirstPosition==0&&top>=mListPadding.top&&
                    mFirstPosition+childCount<mItemCount&&
                    bottom<=getHeight()-getPaddingBottom()mListPadding.bottom) {
                    mTouchMode=TOUCH_MODE_REST;
                    reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
                } else*/ {
                    final VelocityTracker velocityTracker = mVelocityTracker;
                    velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
                    final int initialVelocity = (int) velocityTracker.getYVelocity(mActivePointerId);

                    if (Math.abs(initialVelocity) > mMinimumVelocity) {
                        if (mFlingRunnable == null) {
                            mFlingRunnable = new FlingRunnable();
                        }
                        reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);

                        mFlingRunnable.start(-initialVelocity);
                    } else {
                        mTouchMode = TOUCH_MODE_REST;
                        reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
                    }
                }
            } else {
                mTouchMode = TOUCH_MODE_REST;
                reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
            }
            break;
        }

        setPressed(false);

        // Need to redraw since we probably aren't drawing the selector anymore
        invalidate();

        if (mVelocityTracker != null) {
            mVelocityTracker.recycle();
            mVelocityTracker = null;
        }

        mActivePointerId = INVALID_POINTER;

        /*if (PROFILE_SCROLLING) {
            if (mScrollProfilingStarted) {
                Debug.stopMethodTracing();
                mScrollProfilingStarted=false;
            }
        }*/
        break;
    }

    case MotionEvent.ACTION_CANCEL: {
        mTouchMode = TOUCH_MODE_REST;
        setPressed(false);
        View motionView = this.getChildAt(mMotionPosition - mFirstPosition);
        if (motionView != null) {
            motionView.setPressed(false);
        }
        clearScrollingCache();

        if (mVelocityTracker != null) {
            mVelocityTracker.recycle();
            mVelocityTracker = null;
        }

        mActivePointerId = INVALID_POINTER;
        break;
    }

    case MotionEvent.ACTION_POINTER_UP: {
        onSecondaryPointerUp(ev);
        final int x = (int) mLastTouchX;
        final int y = (int) mLastTouchY;
        final int motionPosition = pointToPosition(x, y);
        if (motionPosition >= 0) {
            // Remember where the motion event started
            v = getChildAt(motionPosition - mFirstPosition);
            //mMotionViewOriginalTop=v.getTop();
            mMotionPosition = motionPosition;
        }
        mTouchRemainderY = y;
        break;
    }
    }

    return true;
}

From source file:com.bulletnoid.android.widget.StaggeredGridView.StaggeredGridView2.java

private void onTouchUp(MotionEvent ev) {
    switch (mTouchMode) {
    case TOUCH_MODE_DOWN:
    case TOUCH_MODE_TAP:
    case TOUCH_MODE_DONE_WAITING:
        final int motionPosition = mMotionPosition;
        final View child = getChildAt(motionPosition - mFirstPosition);
        if (child != null) {
            if (mTouchMode != TOUCH_MODE_DOWN) {
                child.setPressed(false);
            }/* w  w  w  .  jav a2  s .  c  om*/

            final float x = ev.getX();
            final boolean inList = x > getPaddingLeft()
                    /*mListPadding.left*/ && x < getWidth() - getPaddingRight()/*mListPadding.right*/;
            if (inList && !child.hasFocusable()) {
                if (mPerformClick == null) {
                    mPerformClick = new PerformClick();
                }

                final PerformClick performClick = mPerformClick;
                performClick.mClickMotionPosition = motionPosition;
                performClick.rememberWindowAttachCount();

                //mResurrectToPosition = motionPosition;
                Log.d(TAG, "up:" + mTouchMode + "");
                if (mTouchMode == TOUCH_MODE_DOWN || mTouchMode == TOUCH_MODE_TAP) {
                    removeCallbacks(
                            mTouchMode == TOUCH_MODE_DOWN ? mPendingCheckForTap : mPendingCheckForLongPress);
                    //mLayoutMode = LAYOUT_NORMAL;
                    if (!mDataChanged && mAdapter.isEnabled(motionPosition)) {
                        mTouchMode = TOUCH_MODE_TAP;
                        //setSelectedPositionInt(mMotionPosition);
                        layoutChildren(mDataChanged);
                        child.setPressed(true);
                        positionSelector(mMotionPosition, child);
                        setPressed(true);
                        if (mSelector != null) {
                            Drawable d = mSelector.getCurrent();
                            if (d != null && d instanceof TransitionDrawable) {
                                ((TransitionDrawable) d).resetTransition();
                            }
                        }
                        if (mTouchModeReset != null) {
                            removeCallbacks(mTouchModeReset);
                        }
                        mTouchModeReset = new Runnable() {
                            @Override
                            public void run() {
                                mTouchModeReset = null;
                                mTouchMode = TOUCH_MODE_REST;
                                child.setPressed(false);
                                setPressed(false);
                                if (!mDataChanged /*&& isAttachedToWindow()*/) {
                                    performClick.run();
                                }
                            }
                        };
                        postDelayed(mTouchModeReset, ViewConfiguration.getPressedStateDuration());
                    } else {
                        mTouchMode = TOUCH_MODE_REST;
                        updateSelectorState();
                    }
                    return;
                } else if (!mDataChanged && mAdapter.isEnabled(motionPosition)) {
                    performClick.run();
                }
            }
        }
        mTouchMode = TOUCH_MODE_REST;
        updateSelectorState();
        break;
    case TOUCH_MODE_DRAGGING:
        final int childCount = getChildCount();
        if (childCount > 0) {
            final int firstChildTop = getChildAt(0).getTop();
            final int lastChildBottom = getChildAt(childCount - 1).getBottom();
            final int contentTop = getPaddingTop();//mListPadding.top;
            final int contentBottom = getHeight() - getPaddingBottom();//mListPadding.bottom;
            if (mFirstPosition == 0 && firstChildTop >= contentTop && mFirstPosition + childCount < mItemCount
                    && lastChildBottom <= getHeight() - contentBottom) {
                mTouchMode = TOUCH_MODE_REST;
                reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
            } else {
                final VelocityTracker velocityTracker = mVelocityTracker;
                velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);

                final int initialVelocity = (int) (velocityTracker.getYVelocity(mActivePointerId)
                        * mVelocityScale);
                // Fling if we have enough velocity and we aren't at a boundary.
                // Since we can potentially overfling more than we can overscroll, don't
                // allow the weird behavior where you can scroll to a boundary then
                // fling further.
                if (Math.abs(initialVelocity) > mMinimumVelocity
                        && !((mFirstPosition == 0 && firstChildTop == contentTop - mOverscrollDistance)
                                || (mFirstPosition + childCount == mItemCount
                                        && lastChildBottom == contentBottom + mOverscrollDistance))) {
                    if (mFlingRunnable == null) {
                        mFlingRunnable = new FlingRunnable();
                    }
                    reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);

                    mFlingRunnable.start(-initialVelocity);
                } else {
                    mTouchMode = TOUCH_MODE_REST;
                    reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
                    if (mFlingRunnable != null) {
                        mFlingRunnable.endFling();
                    }
                    /*if (mPositionScroller != null) {
                        mPositionScroller.stop();
                    }*/
                }
            }
        } else {
            mTouchMode = TOUCH_MODE_REST;
            reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
        }
        break;

    case TOUCH_MODE_OVERSCROLL:
        if (mFlingRunnable == null) {
            mFlingRunnable = new FlingRunnable();
        }
        final VelocityTracker velocityTracker = mVelocityTracker;
        velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
        final int initialVelocity = (int) velocityTracker.getYVelocity(mActivePointerId);

        reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);
        if (Math.abs(initialVelocity) > mMinimumVelocity) {
            mFlingRunnable.startOverfling(-initialVelocity);
        } else {
            mFlingRunnable.startSpringback();
        }

        break;
    }

    setPressed(false);

    /*if (mEdgeGlowTop != null) {
    mEdgeGlowTop.onRelease();
    mEdgeGlowBottom.onRelease();
    }*/

    // Need to redraw since we probably aren't drawing the selector anymore
    invalidate();
    removeCallbacks(mPendingCheckForLongPress);
    recycleVelocityTracker();

    mActivePointerId = INVALID_POINTER;

    /*if (PROFILE_SCROLLING) {
    if (mScrollProfilingStarted) {
        Debug.stopMethodTracing();
        mScrollProfilingStarted = false;
    }
    }
            
    if (mScrollStrictSpan != null) {
    mScrollStrictSpan.finish();
    mScrollStrictSpan = null;
    }*/
}

From source file:com.glview.widget.AbsListView.java

private void onTouchUp(MotionEvent ev) {
    switch (mTouchMode) {
    case TOUCH_MODE_DOWN:
    case TOUCH_MODE_TAP:
    case TOUCH_MODE_DONE_WAITING:
        final int motionPosition = mMotionPosition;
        final View child = getChildAt(motionPosition - mFirstPosition);
        if (child != null) {
            if (mTouchMode != TOUCH_MODE_DOWN) {
                child.setPressed(false);
            }/*from   w  w  w.  j a va 2s.c om*/

            final float x = ev.getX();
            final boolean inList = x > mListPadding.left && x < getWidth() - mListPadding.right;
            if (inList && !child.hasFocusable()) {
                if (mPerformClick == null) {
                    mPerformClick = new PerformClick();
                }

                final AbsListView.PerformClick performClick = mPerformClick;
                performClick.mClickMotionPosition = motionPosition;
                performClick.rememberWindowAttachCount();

                mResurrectToPosition = motionPosition;

                if (mTouchMode == TOUCH_MODE_DOWN || mTouchMode == TOUCH_MODE_TAP) {
                    removeCallbacks(
                            mTouchMode == TOUCH_MODE_DOWN ? mPendingCheckForTap : mPendingCheckForLongPress);
                    mLayoutMode = LAYOUT_NORMAL;
                    if (!mDataChanged && mAdapter.isEnabled(motionPosition)) {
                        mTouchMode = TOUCH_MODE_TAP;
                        setSelectedPositionInt(mMotionPosition);
                        layoutChildren();
                        child.setPressed(true);
                        positionSelector(mMotionPosition, child);
                        setPressed(true);
                        if (mSelector != null) {
                            Drawable d = mSelector.getCurrent();
                            if (d != null && d instanceof TransitionDrawable) {
                                ((TransitionDrawable) d).resetTransition();
                            }
                            mSelector.setHotspot(x, ev.getY());
                        }
                        if (mTouchModeReset != null) {
                            removeCallbacks(mTouchModeReset);
                        }
                        mTouchModeReset = new Runnable() {
                            @Override
                            public void run() {
                                mTouchModeReset = null;
                                mTouchMode = TOUCH_MODE_REST;
                                child.setPressed(false);
                                setPressed(false);
                                if (!mDataChanged && !mIsDetaching && isAttachedToWindow()) {
                                    performClick.run();
                                }
                            }
                        };
                        postDelayed(mTouchModeReset, ViewConfiguration.getPressedStateDuration());
                    } else {
                        mTouchMode = TOUCH_MODE_REST;
                        updateSelectorState();
                    }
                    return;
                } else if (!mDataChanged && mAdapter.isEnabled(motionPosition)) {
                    performClick.run();
                }
            }
        }
        mTouchMode = TOUCH_MODE_REST;
        updateSelectorState();
        break;
    case TOUCH_MODE_SCROLL:
        final int childCount = getChildCount();
        if (childCount > 0) {
            final int firstChildTop = getChildAt(0).getTop();
            final int lastChildBottom = getChildAt(childCount - 1).getBottom();
            final int contentTop = mListPadding.top;
            final int contentBottom = getHeight() - mListPadding.bottom;
            if (mFirstPosition == 0 && firstChildTop >= contentTop && mFirstPosition + childCount < mItemCount
                    && lastChildBottom <= getHeight() - contentBottom) {
                mTouchMode = TOUCH_MODE_REST;
                reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
            } else {
                final VelocityTracker velocityTracker = mVelocityTracker;
                velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);

                final int initialVelocity = (int) (velocityTracker.getYVelocity(mActivePointerId)
                        * mVelocityScale);
                // Fling if we have enough velocity and we aren't at a boundary.
                // Since we can potentially overfling more than we can overscroll, don't
                // allow the weird behavior where you can scroll to a boundary then
                // fling further.
                boolean flingVelocity = Math.abs(initialVelocity) > mMinimumVelocity;
                if (flingVelocity
                        && !((mFirstPosition == 0 && firstChildTop == contentTop - mOverscrollDistance)
                                || (mFirstPosition + childCount == mItemCount
                                        && lastChildBottom == contentBottom + mOverscrollDistance))) {
                    if (!dispatchNestedPreFling(0, -initialVelocity)) {
                        if (mFlingRunnable == null) {
                            mFlingRunnable = new FlingRunnable();
                        }
                        reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);
                        mFlingRunnable.start(-initialVelocity);
                        dispatchNestedFling(0, -initialVelocity, true);
                    } else {
                        mTouchMode = TOUCH_MODE_REST;
                        reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
                    }
                } else {
                    mTouchMode = TOUCH_MODE_REST;
                    reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
                    if (mFlingRunnable != null) {
                        mFlingRunnable.endFling();
                    }
                    if (mPositionScroller != null) {
                        mPositionScroller.stop();
                    }
                    if (flingVelocity && !dispatchNestedPreFling(0, -initialVelocity)) {
                        dispatchNestedFling(0, -initialVelocity, false);
                    }
                }
            }
        } else {
            mTouchMode = TOUCH_MODE_REST;
            reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
        }
        break;

    case TOUCH_MODE_OVERSCROLL:
        if (mFlingRunnable == null) {
            mFlingRunnable = new FlingRunnable();
        }
        final VelocityTracker velocityTracker = mVelocityTracker;
        velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
        final int initialVelocity = (int) velocityTracker.getYVelocity(mActivePointerId);

        reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);
        if (Math.abs(initialVelocity) > mMinimumVelocity) {
            mFlingRunnable.startOverfling(-initialVelocity);
        } else {
            mFlingRunnable.startSpringback();
        }

        break;
    }

    setPressed(false);

    if (mEdgeGlowTop != null) {
        mEdgeGlowTop.onRelease();
        mEdgeGlowBottom.onRelease();
    }

    // Need to redraw since we probably aren't drawing the selector anymore
    invalidate();
    removeCallbacks(mPendingCheckForLongPress);
    recycleVelocityTracker();

    mActivePointerId = INVALID_POINTER;

    if (PROFILE_SCROLLING) {
        if (mScrollProfilingStarted) {
            Debug.stopMethodTracing();
            mScrollProfilingStarted = false;
        }
    }
}

From source file:com.example.libwidgettv.bak.AbsListView.java

@Override
public boolean onTouchEvent(MotionEvent ev) {
    if (!isEnabled()) {
        // A disabled view that is clickable still consumes the touch
        // events, it just doesn't respond to them.
        return isClickable() || isLongClickable();
    }/*from  ww w.j ava 2s  . c om*/

    if (mFastScroller != null) {
        boolean intercepted = mFastScroller.onTouchEvent(ev);
        if (intercepted) {
            return true;
        }
    }

    final int action = ev.getAction();

    View v;

    initVelocityTrackerIfNotExists();
    mVelocityTracker.addMovement(ev);

    switch (action & MotionEvent.ACTION_MASK) {
    case MotionEvent.ACTION_DOWN: {
        switch (mTouchMode) {
        case TOUCH_MODE_OVERFLING: {
            mFlingRunnable.endFling();
            if (mPositionScroller != null) {
                mPositionScroller.stop();
            }
            mTouchMode = TOUCH_MODE_OVERSCROLL;
            mMotionX = (int) ev.getX();
            mMotionY = mLastY = (int) ev.getY();
            mMotionCorrection = 0;
            mActivePointerId = ev.getPointerId(0);
            mDirection = 0;
            break;
        }

        default: {
            mActivePointerId = ev.getPointerId(0);
            final int x = (int) ev.getX();
            final int y = (int) ev.getY();
            int motionPosition = pointToPosition(x, y);
            if (!mDataChanged) {
                if ((mTouchMode != TOUCH_MODE_FLING) && (motionPosition >= 0)
                        && (getAdapter().isEnabled(motionPosition))) {
                    // User clicked on an actual view (and was not stopping
                    // a fling).
                    // It might be a click or a scroll. Assume it is a click
                    // until
                    // proven otherwise
                    mTouchMode = TOUCH_MODE_DOWN;
                    // FIXME Debounce
                    if (mPendingCheckForTap == null) {
                        mPendingCheckForTap = new CheckForTap();
                    }
                    postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
                } else {
                    if (mTouchMode == TOUCH_MODE_FLING) {
                        // Stopped a fling. It is a scroll.
                        createScrollingCache();
                        mTouchMode = TOUCH_MODE_SCROLL;
                        mMotionCorrection = 0;
                        motionPosition = findMotionRow(y);
                        mFlingRunnable.flywheelTouch();
                    }
                }
            }

            if (motionPosition >= 0) {
                // Remember where the motion event started
                v = getChildAt(motionPosition - mFirstPosition);
                mMotionViewOriginalTop = v.getTop();
            }
            mMotionX = x;
            mMotionY = y;
            mMotionPosition = motionPosition;
            mLastY = Integer.MIN_VALUE;
            break;
        }
        }

        // if (performButtonActionOnTouchDown(ev)) {
        // if (mTouchMode == TOUCH_MODE_DOWN) {
        // removeCallbacks(mPendingCheckForTap);
        // }
        // }
        break;
    }

    case MotionEvent.ACTION_MOVE: {
        int pointerIndex = ev.findPointerIndex(mActivePointerId);
        if (pointerIndex == -1) {
            pointerIndex = 0;
            mActivePointerId = ev.getPointerId(pointerIndex);
        }
        final int y = (int) ev.getY(pointerIndex);
        switch (mTouchMode) {
        case TOUCH_MODE_DOWN:
        case TOUCH_MODE_TAP:
        case TOUCH_MODE_DONE_WAITING:
            // Check if we have moved far enough that it looks more like a
            // scroll than a tap
            startScrollIfNeeded(y);
            break;
        case TOUCH_MODE_SCROLL:
        case TOUCH_MODE_OVERSCROLL:
            scrollIfNeeded(y);
            break;
        }
        break;
    }

    case MotionEvent.ACTION_UP: {
        switch (mTouchMode) {
        case TOUCH_MODE_DOWN:
        case TOUCH_MODE_TAP:
        case TOUCH_MODE_DONE_WAITING:
            final int motionPosition = mMotionPosition;
            final View child = getChildAt(motionPosition - mFirstPosition);

            final float x = ev.getX();
            final boolean inList = x > mListPadding.left && x < getWidth() - mListPadding.right;

            if (child != null && !child.hasFocusable() && inList) {
                if (mTouchMode != TOUCH_MODE_DOWN) {
                    child.setPressed(false);
                }

                if (mPerformClick == null) {
                    mPerformClick = new PerformClick();
                }

                final AbsListView.PerformClick performClick = mPerformClick;
                performClick.mClickMotionPosition = motionPosition;
                performClick.rememberWindowAttachCount();

                mResurrectToPosition = motionPosition;

                if (mTouchMode == TOUCH_MODE_DOWN || mTouchMode == TOUCH_MODE_TAP) {
                    final Handler handler = getHandler();
                    if (handler != null) {
                        handler.removeCallbacks(mTouchMode == TOUCH_MODE_DOWN ? mPendingCheckForTap
                                : mPendingCheckForLongPress);
                    }
                    mLayoutMode = LAYOUT_NORMAL;
                    if (!mDataChanged && mAdapter.isEnabled(motionPosition)) {
                        mTouchMode = TOUCH_MODE_TAP;
                        setSelectedPositionInt(mMotionPosition);
                        layoutChildren();
                        child.setPressed(true);
                        positionSelector(mMotionPosition, child);
                        setPressed(true);
                        if (mSelector != null) {
                            Drawable d = mSelector.getCurrent();
                            if (d != null && d instanceof TransitionDrawable) {
                                ((TransitionDrawable) d).resetTransition();
                            }
                        }
                        if (mTouchModeReset != null) {
                            removeCallbacks(mTouchModeReset);
                        }
                        mTouchModeReset = new Runnable() {
                            @Override
                            public void run() {
                                mTouchMode = TOUCH_MODE_REST;
                                child.setPressed(false);
                                setPressed(false);
                                if (!mDataChanged) {
                                    performClick.run();
                                }
                            }
                        };
                        postDelayed(mTouchModeReset, ViewConfiguration.getPressedStateDuration());
                    } else {
                        mTouchMode = TOUCH_MODE_REST;
                        updateSelectorState();
                    }
                    return true;
                } else if (!mDataChanged && mAdapter.isEnabled(motionPosition)) {
                    performClick.run();
                }
            }
            mTouchMode = TOUCH_MODE_REST;
            updateSelectorState();
            break;
        case TOUCH_MODE_SCROLL:
            final int childCount = getChildCount();
            if (childCount > 0) {
                final int firstChildTop = getChildAt(0).getTop();
                final int lastChildBottom = getChildAt(childCount - 1).getBottom();
                final int contentTop = mListPadding.top;
                final int contentBottom = getHeight() - mListPadding.bottom;
                if (mFirstPosition == 0 && firstChildTop >= contentTop
                        && mFirstPosition + childCount < mItemCount
                        && lastChildBottom <= getHeight() - contentBottom) {
                    mTouchMode = TOUCH_MODE_REST;
                    reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
                } else {
                    final VelocityTracker velocityTracker = mVelocityTracker;
                    velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);

                    final int initialVelocity = (int) (velocityTracker.getYVelocity(mActivePointerId)
                            * mVelocityScale);
                    // Fling if we have enough velocity and we aren't at a
                    // boundary.
                    // Since we can potentially overfling more than we can
                    // overscroll, don't
                    // allow the weird behavior where you can scroll to a
                    // boundary then
                    // fling further.
                    if (Math.abs(initialVelocity) > mMinimumVelocity
                            && !((mFirstPosition == 0 && firstChildTop == contentTop - mOverscrollDistance)
                                    || (mFirstPosition + childCount == mItemCount
                                            && lastChildBottom == contentBottom + mOverscrollDistance))) {
                        if (mFlingRunnable == null) {
                            mFlingRunnable = new FlingRunnable();
                        }
                        reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);

                        mFlingRunnable.start(-initialVelocity);
                    } else {
                        mTouchMode = TOUCH_MODE_REST;
                        reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
                        if (mFlingRunnable != null) {
                            mFlingRunnable.endFling();
                        }
                        if (mPositionScroller != null) {
                            mPositionScroller.stop();
                        }
                    }
                }
            } else {
                mTouchMode = TOUCH_MODE_REST;
                reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
            }
            break;

        case TOUCH_MODE_OVERSCROLL:
            if (mFlingRunnable == null) {
                mFlingRunnable = new FlingRunnable();
            }
            final VelocityTracker velocityTracker = mVelocityTracker;
            velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
            final int initialVelocity = (int) velocityTracker.getYVelocity(mActivePointerId);

            reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);
            if (Math.abs(initialVelocity) > mMinimumVelocity) {
                mFlingRunnable.startOverfling(-initialVelocity);
            } else {
                mFlingRunnable.startSpringback();
            }

            break;
        }

        setPressed(false);

        // Need to redraw since we probably aren't drawing the selector
        // anymore
        invalidate();

        final Handler handler = getHandler();
        if (handler != null) {
            handler.removeCallbacks(mPendingCheckForLongPress);
        }

        recycleVelocityTracker();

        mActivePointerId = INVALID_POINTER;

        if (PROFILE_SCROLLING) {
            if (mScrollProfilingStarted) {
                Debug.stopMethodTracing();
                mScrollProfilingStarted = false;
            }
        }
        break;
    }

    case MotionEvent.ACTION_CANCEL: {
        switch (mTouchMode) {
        case TOUCH_MODE_OVERSCROLL:
            if (mFlingRunnable == null) {
                mFlingRunnable = new FlingRunnable();
            }
            mFlingRunnable.startSpringback();
            break;

        case TOUCH_MODE_OVERFLING:
            // Do nothing - let it play out.
            break;

        default:
            mTouchMode = TOUCH_MODE_REST;
            setPressed(false);
            View motionView = this.getChildAt(mMotionPosition - mFirstPosition);
            if (motionView != null) {
                motionView.setPressed(false);
            }
            clearScrollingCache();

            final Handler handler = getHandler();
            if (handler != null) {
                handler.removeCallbacks(mPendingCheckForLongPress);
            }

            recycleVelocityTracker();
        }

        mActivePointerId = INVALID_POINTER;
        break;
    }

    case MotionEvent.ACTION_POINTER_UP: {
        onSecondaryPointerUp(ev);
        final int x = mMotionX;
        final int y = mMotionY;
        final int motionPosition = pointToPosition(x, y);
        if (motionPosition >= 0) {
            // Remember where the motion event started
            v = getChildAt(motionPosition - mFirstPosition);
            mMotionViewOriginalTop = v.getTop();
            mMotionPosition = motionPosition;
        }
        mLastY = y;
        break;
    }

    case MotionEvent.ACTION_POINTER_DOWN: {
        // New pointers take over dragging duties
        final int index = ev.getActionIndex();
        final int id = ev.getPointerId(index);
        final int x = (int) ev.getX(index);
        final int y = (int) ev.getY(index);
        mMotionCorrection = 0;
        mActivePointerId = id;
        mMotionX = x;
        mMotionY = y;
        final int motionPosition = pointToPosition(x, y);
        if (motionPosition >= 0) {
            // Remember where the motion event started
            v = getChildAt(motionPosition - mFirstPosition);
            mMotionViewOriginalTop = v.getTop();
            mMotionPosition = motionPosition;
        }
        mLastY = y;
        break;
    }
    }

    return true;
}

From source file:com.appunite.list.AbsListView.java

@Override
public boolean onTouchEvent(MotionEvent ev) {
    if (!isEnabled()) {
        // A disabled view that is clickable still consumes the touch
        // events, it just doesn't respond to them.
        return isClickable() || isLongClickable();
    }//from  www .j a va 2s.  c om

    if (mPositionScroller != null) {
        mPositionScroller.stop();
    }

    if (!mIsAttached) {
        // Something isn't right.
        // Since we rely on being attached to get data set change notifications,
        // don't risk doing anything where we might try to resync and find things
        // in a bogus state.
        return false;
    }

    if (mFastScroller != null) {
        boolean intercepted = mFastScroller.onTouchEvent(ev);
        if (intercepted) {
            return true;
        }
    }

    final int action = ev.getAction();

    View v;

    initVelocityTrackerIfNotExists();
    mVelocityTracker.addMovement(ev);

    switch (action & MotionEvent.ACTION_MASK) {
    case MotionEvent.ACTION_DOWN: {
        switch (mTouchMode) {
        case TOUCH_MODE_OVERFLING: {
            mFlingRunnable.endFling();
            if (mPositionScroller != null) {
                mPositionScroller.stop();
            }
            mTouchMode = TOUCH_MODE_OVERSCROLL;
            mMotionX = (int) ev.getX();
            mMotionY = mLastY = (int) ev.getY();
            mMotionCorrection = 0;
            mActivePointerId = ev.getPointerId(0);
            mDirection = 0;
            break;
        }

        default: {
            mActivePointerId = ev.getPointerId(0);
            final int x = (int) ev.getX();
            final int y = (int) ev.getY();
            int motionPosition = pointToPosition(x, y);
            if (!mDataChanged) {
                if ((mTouchMode != TOUCH_MODE_FLING) && (motionPosition >= 0)
                        && (getAdapter().isEnabled(motionPosition))) {
                    // User clicked on an actual view (and was not stopping a fling).
                    // It might be a click or a scroll. Assume it is a click until
                    // proven otherwise
                    mTouchMode = TOUCH_MODE_DOWN;
                    // FIXME Debounce
                    if (mPendingCheckForTap == null) {
                        mPendingCheckForTap = new CheckForTap();
                    }
                    postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
                } else {
                    if (mTouchMode == TOUCH_MODE_FLING) {
                        // Stopped a fling. It is a scroll.
                        createScrollingCache();
                        mTouchMode = TOUCH_MODE_SCROLL;
                        mMotionCorrection = 0;
                        motionPosition = findMotionRow(y);
                        mFlingRunnable.flywheelTouch();
                    }
                }
            }

            if (motionPosition >= 0) {
                // Remember where the motion event started
                v = getChildAt(motionPosition - mFirstPosition);
                mMotionViewOriginalTop = v.getTop();
            }
            mMotionX = x;
            mMotionY = y;
            mMotionPosition = motionPosition;
            mLastY = Integer.MIN_VALUE;
            break;
        }
        }

        if (performButtonActionOnTouchDownUnhide(ev)) {
            if (mTouchMode == TOUCH_MODE_DOWN) {
                removeCallbacks(mPendingCheckForTap);
            }
        }
        break;
    }

    case MotionEvent.ACTION_MOVE: {
        int pointerIndex = ev.findPointerIndex(mActivePointerId);
        if (pointerIndex == -1) {
            pointerIndex = 0;
            mActivePointerId = ev.getPointerId(pointerIndex);
        }
        final int y = (int) ev.getY(pointerIndex);

        if (mDataChanged) {
            // Re-sync everything if data has been changed
            // since the scroll operation can query the adapter.
            layoutChildren();
        }

        switch (mTouchMode) {
        case TOUCH_MODE_DOWN:
        case TOUCH_MODE_TAP:
        case TOUCH_MODE_DONE_WAITING:
            // Check if we have moved far enough that it looks more like a
            // scroll than a tap
            startScrollIfNeeded(y);
            break;
        case TOUCH_MODE_SCROLL:
        case TOUCH_MODE_OVERSCROLL:
            scrollIfNeeded(y);
            break;
        }
        break;
    }

    case MotionEvent.ACTION_UP: {
        switch (mTouchMode) {
        case TOUCH_MODE_DOWN:
        case TOUCH_MODE_TAP:
        case TOUCH_MODE_DONE_WAITING:
            final int motionPosition = mMotionPosition;
            final View child = getChildAt(motionPosition - mFirstPosition);

            final float x = ev.getX();
            final boolean inList = x > mListPadding.left && x < getWidth() - mListPadding.right;

            if (child != null && !child.hasFocusable() && inList) {
                if (mTouchMode != TOUCH_MODE_DOWN) {
                    child.setPressed(false);
                }

                if (mPerformClick == null) {
                    mPerformClick = new PerformClick();
                }

                final AbsListView.PerformClick performClick = mPerformClick;
                performClick.mClickMotionPosition = motionPosition;
                performClick.rememberWindowAttachCount();

                mResurrectToPosition = motionPosition;

                if (mTouchMode == TOUCH_MODE_DOWN || mTouchMode == TOUCH_MODE_TAP) {
                    final Handler handler = getHandler();
                    if (handler != null) {
                        handler.removeCallbacks(mTouchMode == TOUCH_MODE_DOWN ? mPendingCheckForTap
                                : mPendingCheckForLongPress);
                    }
                    mLayoutMode = LAYOUT_NORMAL;
                    if (!mDataChanged && mAdapter.isEnabled(motionPosition)) {
                        mTouchMode = TOUCH_MODE_TAP;
                        setSelectedPositionInt(mMotionPosition);
                        layoutChildren();
                        child.setPressed(true);
                        positionSelector(mMotionPosition, child);
                        setPressed(true);
                        if (mSelector != null) {
                            Drawable d = mSelector.getCurrent();
                            if (d != null && d instanceof TransitionDrawable) {
                                ((TransitionDrawable) d).resetTransition();
                            }
                        }
                        if (mTouchModeReset != null) {
                            removeCallbacks(mTouchModeReset);
                        }
                        mTouchModeReset = new Runnable() {
                            @Override
                            public void run() {
                                mTouchModeReset = null;
                                mTouchMode = TOUCH_MODE_REST;
                                child.setPressed(false);
                                setPressed(false);
                                if (!mDataChanged) {
                                    performClick.run();
                                }
                            }
                        };
                        postDelayed(mTouchModeReset, ViewConfiguration.getPressedStateDuration());
                    } else {
                        mTouchMode = TOUCH_MODE_REST;
                        updateSelectorState();
                    }
                    return true;
                } else if (!mDataChanged && mAdapter.isEnabled(motionPosition)) {
                    performClick.run();
                }
            }
            mTouchMode = TOUCH_MODE_REST;
            updateSelectorState();
            break;
        case TOUCH_MODE_SCROLL:
            final int childCount = getChildCount();
            if (childCount > 0) {
                final int firstChildTop = getChildAt(0).getTop();
                final int lastChildBottom = getChildAt(childCount - 1).getBottom();
                final int contentTop = mListPadding.top;
                final int contentBottom = getHeight() - mListPadding.bottom;
                if (mFirstPosition == 0 && firstChildTop >= contentTop
                        && mFirstPosition + childCount < mItemCount
                        && lastChildBottom <= getHeight() - contentBottom) {
                    mTouchMode = TOUCH_MODE_REST;
                    reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
                } else {
                    final VelocityTracker velocityTracker = mVelocityTracker;
                    velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);

                    final int initialVelocity = (int) (velocityTracker.getYVelocity(mActivePointerId)
                            * mVelocityScale);
                    // Fling if we have enough velocity and we aren't at a boundary.
                    // Since we can potentially overfling more than we can overscroll, don't
                    // allow the weird behavior where you can scroll to a boundary then
                    // fling further.
                    if (Math.abs(initialVelocity) > mMinimumVelocity
                            && !((mFirstPosition == 0 && firstChildTop == contentTop - mOverscrollDistance)
                                    || (mFirstPosition + childCount == mItemCount
                                            && lastChildBottom == contentBottom + mOverscrollDistance))) {
                        if (mFlingRunnable == null) {
                            mFlingRunnable = new FlingRunnable();
                        }
                        reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);

                        mFlingRunnable.start(-initialVelocity);
                    } else {
                        mTouchMode = TOUCH_MODE_REST;
                        reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
                        if (mFlingRunnable != null) {
                            mFlingRunnable.endFling();
                        }
                        if (mPositionScroller != null) {
                            mPositionScroller.stop();
                        }
                    }
                }
            } else {
                mTouchMode = TOUCH_MODE_REST;
                reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
            }
            break;

        case TOUCH_MODE_OVERSCROLL:
            if (mFlingRunnable == null) {
                mFlingRunnable = new FlingRunnable();
            }
            final VelocityTracker velocityTracker = mVelocityTracker;
            velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
            final int initialVelocity = (int) velocityTracker.getYVelocity(mActivePointerId);

            reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);
            if (Math.abs(initialVelocity) > mMinimumVelocity) {
                mFlingRunnable.startOverfling(-initialVelocity);
            } else {
                mFlingRunnable.startSpringback();
            }

            break;
        }

        setPressed(false);

        if (mEdgeGlowTop != null) {
            mEdgeGlowTop.onRelease();
            mEdgeGlowBottom.onRelease();
        }

        // Need to redraw since we probably aren't drawing the selector anymore
        invalidate();

        final Handler handler = getHandler();
        if (handler != null) {
            handler.removeCallbacks(mPendingCheckForLongPress);
        }

        recycleVelocityTracker();

        mActivePointerId = INVALID_POINTER;

        if (PROFILE_SCROLLING) {
            if (mScrollProfilingStarted) {
                Debug.stopMethodTracing();
                mScrollProfilingStarted = false;
            }
        }

        // FIXME not needed bacaues we could not implement strict span (j.m.)
        //            if (mScrollStrictSpan != null) {
        //                mScrollStrictSpan.finish();
        //                mScrollStrictSpan = null;
        //            }
        break;
    }

    case MotionEvent.ACTION_CANCEL: {
        switch (mTouchMode) {
        case TOUCH_MODE_OVERSCROLL:
            if (mFlingRunnable == null) {
                mFlingRunnable = new FlingRunnable();
            }
            mFlingRunnable.startSpringback();
            break;

        case TOUCH_MODE_OVERFLING:
            // Do nothing - let it play out.
            break;

        default:
            mTouchMode = TOUCH_MODE_REST;
            setPressed(false);
            View motionView = this.getChildAt(mMotionPosition - mFirstPosition);
            if (motionView != null) {
                motionView.setPressed(false);
            }
            clearScrollingCache();

            final Handler handler = getHandler();
            if (handler != null) {
                handler.removeCallbacks(mPendingCheckForLongPress);
            }

            recycleVelocityTracker();
        }

        if (mEdgeGlowTop != null) {
            mEdgeGlowTop.onRelease();
            mEdgeGlowBottom.onRelease();
        }
        mActivePointerId = INVALID_POINTER;
        break;
    }

    case MotionEvent.ACTION_POINTER_UP: {
        onSecondaryPointerUp(ev);
        final int x = mMotionX;
        final int y = mMotionY;
        final int motionPosition = pointToPosition(x, y);
        if (motionPosition >= 0) {
            // Remember where the motion event started
            v = getChildAt(motionPosition - mFirstPosition);
            mMotionViewOriginalTop = v.getTop();
            mMotionPosition = motionPosition;
        }
        mLastY = y;
        break;
    }

    case MotionEvent.ACTION_POINTER_DOWN: {
        // New pointers take over dragging duties
        final int index = MotionEventCompat.getActionIndex(ev);
        final int id = ev.getPointerId(index);
        final int x = (int) ev.getX(index);
        final int y = (int) ev.getY(index);
        mMotionCorrection = 0;
        mActivePointerId = id;
        mMotionX = x;
        mMotionY = y;
        final int motionPosition = pointToPosition(x, y);
        if (motionPosition >= 0) {
            // Remember where the motion event started
            v = getChildAt(motionPosition - mFirstPosition);
            mMotionViewOriginalTop = v.getTop();
            mMotionPosition = motionPosition;
        }
        mLastY = y;
        break;
    }
    }

    return true;
}