Esempio n. 1
0
        /// <summary>
        /// Analyzes the given motion event and if applicable triggers the
        /// appropriate callbacks on the
        /// <see cref="OnGestureListener">OnGestureListener</see>
        /// supplied.
        /// </summary>
        /// <param name="ev">The current motion event.</param>
        /// <returns>
        /// true if the
        /// <see cref="OnGestureListener">OnGestureListener</see>
        /// consumed the event,
        /// else false.
        /// </returns>
        public virtual bool onTouchEvent(android.view.MotionEvent ev)
        {
            if (mInputEventConsistencyVerifier != null)
            {
                mInputEventConsistencyVerifier.onTouchEvent(ev, 0);
            }
            int   action = ev.getAction();
            float y      = ev.getY();
            float x      = ev.getX();

            if (mVelocityTracker == null)
            {
                mVelocityTracker = android.view.VelocityTracker.obtain();
            }
            mVelocityTracker.addMovement(ev);
            bool handled = false;

            switch (action & android.view.MotionEvent.ACTION_MASK)
            {
            case android.view.MotionEvent.ACTION_POINTER_DOWN:
            {
                if (mIgnoreMultitouch)
                {
                    // Multitouch event - abort.
                    cancel();
                }
                break;
            }

            case android.view.MotionEvent.ACTION_POINTER_UP:
            {
                // Ending a multitouch gesture and going back to 1 finger
                if (mIgnoreMultitouch && ev.getPointerCount() == 2)
                {
                    int index = (((action & android.view.MotionEvent.ACTION_POINTER_INDEX_MASK) >> android.view.MotionEvent
                                  .ACTION_POINTER_INDEX_SHIFT) == 0) ? 1 : 0;
                    mLastMotionX = ev.getX(index);
                    mLastMotionY = ev.getY(index);
                    mVelocityTracker.recycle();
                    mVelocityTracker = android.view.VelocityTracker.obtain();
                }
                break;
            }

            case android.view.MotionEvent.ACTION_DOWN:
            {
                if (mDoubleTapListener != null)
                {
                    bool hadTapMessage = mHandler.hasMessages(TAP);
                    if (hadTapMessage)
                    {
                        mHandler.removeMessages(TAP);
                    }
                    if ((mCurrentDownEvent != null) && (mPreviousUpEvent != null) && hadTapMessage &&
                        isConsideredDoubleTap(mCurrentDownEvent, mPreviousUpEvent, ev))
                    {
                        // This is a second tap
                        mIsDoubleTapping = true;
                        // Give a callback with the first tap of the double-tap
                        handled |= mDoubleTapListener.onDoubleTap(mCurrentDownEvent);
                        // Give a callback with down event of the double-tap
                        handled |= mDoubleTapListener.onDoubleTapEvent(ev);
                    }
                    else
                    {
                        // This is a first tap
                        mHandler.sendEmptyMessageDelayed(TAP, DOUBLE_TAP_TIMEOUT);
                    }
                }
                mLastMotionX = x;
                mLastMotionY = y;
                if (mCurrentDownEvent != null)
                {
                    mCurrentDownEvent.recycle();
                }
                mCurrentDownEvent        = android.view.MotionEvent.obtain(ev);
                mAlwaysInTapRegion       = true;
                mAlwaysInBiggerTapRegion = true;
                mStillDown   = true;
                mInLongPress = false;
                if (mIsLongpressEnabled)
                {
                    mHandler.removeMessages(LONG_PRESS);
                    mHandler.sendEmptyMessageAtTime(LONG_PRESS, mCurrentDownEvent.getDownTime() + TAP_TIMEOUT
                                                    + LONGPRESS_TIMEOUT);
                }
                mHandler.sendEmptyMessageAtTime(SHOW_PRESS, mCurrentDownEvent.getDownTime() + TAP_TIMEOUT
                                                );
                handled |= mListener.onDown(ev);
                break;
            }

            case android.view.MotionEvent.ACTION_MOVE:
            {
                if (mInLongPress || (mIgnoreMultitouch && ev.getPointerCount() > 1))
                {
                    break;
                }
                float scrollX = mLastMotionX - x;
                float scrollY = mLastMotionY - y;
                if (mIsDoubleTapping)
                {
                    // Give the move events of the double-tap
                    handled |= mDoubleTapListener.onDoubleTapEvent(ev);
                }
                else
                {
                    if (mAlwaysInTapRegion)
                    {
                        int deltaX   = (int)(x - mCurrentDownEvent.getX());
                        int deltaY   = (int)(y - mCurrentDownEvent.getY());
                        int distance = (deltaX * deltaX) + (deltaY * deltaY);
                        if (distance > mTouchSlopSquare)
                        {
                            handled            = mListener.onScroll(mCurrentDownEvent, ev, scrollX, scrollY);
                            mLastMotionX       = x;
                            mLastMotionY       = y;
                            mAlwaysInTapRegion = false;
                            mHandler.removeMessages(TAP);
                            mHandler.removeMessages(SHOW_PRESS);
                            mHandler.removeMessages(LONG_PRESS);
                        }
                        if (distance > mBiggerTouchSlopSquare)
                        {
                            mAlwaysInBiggerTapRegion = false;
                        }
                    }
                    else
                    {
                        if ((System.Math.Abs(scrollX) >= 1) || (System.Math.Abs(scrollY) >= 1))
                        {
                            handled      = mListener.onScroll(mCurrentDownEvent, ev, scrollX, scrollY);
                            mLastMotionX = x;
                            mLastMotionY = y;
                        }
                    }
                }
                break;
            }

            case android.view.MotionEvent.ACTION_UP:
            {
                mStillDown = false;
                android.view.MotionEvent currentUpEvent = android.view.MotionEvent.obtain(ev);
                if (mIsDoubleTapping)
                {
                    // Finally, give the up event of the double-tap
                    handled |= mDoubleTapListener.onDoubleTapEvent(ev);
                }
                else
                {
                    if (mInLongPress)
                    {
                        mHandler.removeMessages(TAP);
                        mInLongPress = false;
                    }
                    else
                    {
                        if (mAlwaysInTapRegion)
                        {
                            handled = mListener.onSingleTapUp(ev);
                        }
                        else
                        {
                            // A fling must travel the minimum tap distance
                            android.view.VelocityTracker velocityTracker = mVelocityTracker;
                            velocityTracker.computeCurrentVelocity(1000, mMaximumFlingVelocity);
                            float velocityY = velocityTracker.getYVelocity();
                            float velocityX = velocityTracker.getXVelocity();
                            if ((System.Math.Abs(velocityY) > mMinimumFlingVelocity) || (System.Math.Abs(velocityX
                                                                                                         ) > mMinimumFlingVelocity))
                            {
                                handled = mListener.onFling(mCurrentDownEvent, ev, velocityX, velocityY);
                            }
                        }
                    }
                }
                if (mPreviousUpEvent != null)
                {
                    mPreviousUpEvent.recycle();
                }
                // Hold the event we obtained above - listeners may have changed the original.
                mPreviousUpEvent = currentUpEvent;
                mVelocityTracker.recycle();
                mVelocityTracker = null;
                mIsDoubleTapping = false;
                mHandler.removeMessages(SHOW_PRESS);
                mHandler.removeMessages(LONG_PRESS);
                break;
            }

            case android.view.MotionEvent.ACTION_CANCEL:
            {
                cancel();
                break;
            }
            }
            if (!handled && mInputEventConsistencyVerifier != null)
            {
                mInputEventConsistencyVerifier.onUnhandledEvent(ev, 0);
            }
            return(handled);
        }