public override bool OnTouchEvent(MotionEvent ev)
        {
            if (_velocityTracker == null)
            {
                _velocityTracker = VelocityTracker.Obtain();
            }
            _velocityTracker.AddMovement(ev);

            var action = ev.Action;
            var x      = ev.GetX();

            switch (action)
            {
            case MotionEventActions.Down:
                /*
                 * If being flinged and user touches, stop the fling. isFinished will be false if being flinged.
                 */
                if (!_scroller.IsFinished)
                {
                    _scroller.AbortAnimation();
                }

                // Remember where the motion event started
                _lastMotionX = x;

                _touchState = _scroller.IsFinished ? TOUCH_STATE_REST : TOUCH_STATE_SCROLLING;

                break;

            case MotionEventActions.Move:
                var xDiff = (int)Math.Abs(x - _lastMotionX);

                var xMoved = xDiff > _touchSlop;

                if (xMoved)
                {
                    // Scroll if the user moved far enough along the X axis
                    _touchState = TOUCH_STATE_SCROLLING;
                }

                if (_touchState == TOUCH_STATE_SCROLLING)
                {
                    // Scroll to follow the motion event
                    var deltaX = (int)(_lastMotionX - x);
                    _lastMotionX = x;

                    var scrollX = ScrollX;
                    if (deltaX < 0)
                    {
                        if (scrollX > 0)
                        {
                            ScrollBy(Math.Max(-scrollX, deltaX), 0);
                        }
                    }
                    else if (deltaX > 0)
                    {
                        var availableToScroll = GetChildAt(ChildCount - 1).Right - scrollX - Width;
                        if (availableToScroll > 0)
                        {
                            ScrollBy(Math.Min(availableToScroll, deltaX), 0);
                        }
                    }
                }
                break;

            case MotionEventActions.Up:
                if (_touchState == TOUCH_STATE_SCROLLING)
                {
                    var velocityTracker = _velocityTracker;
                    velocityTracker.ComputeCurrentVelocity(1000, _maximumVelocity);
                    var velocityX = (int)velocityTracker.XVelocity;

                    if (velocityX > SNAP_VELOCITY && _currentScreen > 0)
                    {
                        // Fling hard enough to move left
                        SnapToScreen(_currentScreen - 1);
                    }
                    else if (velocityX < -SNAP_VELOCITY && _currentScreen < ChildCount - 1)
                    {
                        // Fling hard enough to move right
                        SnapToScreen(_currentScreen + 1);
                    }
                    else
                    {
                        SnapToDestination();
                    }

                    if (_velocityTracker != null)
                    {
                        _velocityTracker.Recycle();
                        _velocityTracker = null;
                    }
                }

                _touchState = TOUCH_STATE_REST;

                break;

            case MotionEventActions.Cancel:
                _touchState = TOUCH_STATE_REST;
                break;
            }

            return(true);
        }
Example #2
0
        public override bool DispatchTouchEvent(MotionEvent e)
        {
            var index     = e.ActionIndex;
            var action    = e.ActionMasked;
            var pointerId = e.GetPointerId(index);

            switch (action & MotionEventActions.Mask)
            {
            case MotionEventActions.PointerDown:
                MultiTouchGesture?.Invoke(this, EventArgs.Empty);
                break;

            case MotionEventActions.Up:
                if ((DateTime.Now - _downTime).TotalMilliseconds < 200)
                {
                    SingleTapGesture?.Invoke(this, EventArgs.Empty);
                }

                break;
            }

            switch (action)
            {
            case MotionEventActions.Down:
                _downTime = DateTime.Now;

                if (_velocityTracker == null)
                {
                    _velocityTracker = VelocityTracker.Obtain();
                }
                else
                {
                    // Reset the velocity tracker back to its initial state.
                    _velocityTracker.Clear();
                }

                if (IfVelocityTrackerIsNull())
                {
                    return(true);
                }

                _velocityTracker.AddMovement(e);
                break;

            case MotionEventActions.Move:
                if (IfVelocityTrackerIsNull())
                {
                    return(true);
                }

                _velocityTracker.AddMovement(e);
                _velocityTracker.ComputeCurrentVelocity(Sensitivity);
                TryExportVelocity(_velocityTracker.GetXVelocity(pointerId), _velocityTracker.GetYVelocity(pointerId));

                break;

            case MotionEventActions.Up:
            case MotionEventActions.Cancel:
                if (IfVelocityTrackerIsNull())
                {
                    return(true);
                }

                _velocityTracker.Recycle();
                _velocityTracker = null;
                break;
            }

            return(true);
        }
Example #3
0
        public override bool OnInterceptTouchEvent(
            CoordinatorLayout parent, Java.Lang.Object childObject, MotionEvent @event)
        {
            View child = Android.Runtime.Extensions.JavaCast <View>(childObject);

            if (!child.IsShown)
            {
                Debug.WriteLineIf(DebugTrace, $"OnInterceptTouchEvent: return false");
                return(false);
            }

            int action = MotionEventCompat.GetActionMasked(@event);

            // Record the velocity
            if (action == (int)MotionEventActions.Down)
            {
                reset();
            }

            if (mVelocityTracker == null || mVelocityTracker.Handle == IntPtr.Zero)
            {
                mVelocityTracker = VelocityTracker.Obtain();
            }

            mVelocityTracker.AddMovement(@event);
            switch (action)
            {
            case (int)MotionEventActions.Up:
            case (int)MotionEventActions.Cancel:
                mTouchingScrollingChild = false;
                mActivePointerId        = MotionEvent.InvalidPointerId;
                // Reset the ignore flag
                if (mIgnoreEvents)
                {
                    mIgnoreEvents = false;
                    return(false);
                }
                break;

            case (int)MotionEventActions.Down:
                int initialX = (int)@event.GetX();
                mInitialY = (int)@event.GetY();
                View nestedScroll;

                if (mNestedScrollingChildRef.TryGetTarget(out nestedScroll) && parent.IsPointInChildBounds(nestedScroll, initialX, mInitialY))
                {
                    mActivePointerId = @event.GetPointerId(@event.ActionIndex);
                    //mTouchingScrollingChild = true;
                }
                mIgnoreEvents =
                    mActivePointerId == MotionEvent.InvalidPointerId &&
                    !parent.IsPointInChildBounds(child, initialX, mInitialY);
                break;
            }
            if (!mIgnoreEvents && mViewDragHelper.ShouldInterceptTouchEvent(@event))
            {
                Debug.WriteLineIf(DebugTrace, $"OnInterceptTouchEvent: return true");
                return(true);
            }
            // We have to handle cases that the ViewDragHelper does not capture the bottom sheet because
            // it is not the top most view of its parent. This is not necessary when the touch event is
            // happening over the scrolling content as nested scrolling logic handles that case.
            View scroll;
            var  result = action == (int)MotionEventActions.Move &&
                          mNestedScrollingChildRef.TryGetTarget(out scroll) &&
                          !mIgnoreEvents && mState != STATE_DRAGGING &&
                          !parent.IsPointInChildBounds(scroll, (int)@event.GetX(), (int)@event.GetY()) &&
                          Math.Abs(mInitialY - @event.GetY()) > mViewDragHelper.TouchSlop;

            Debug.WriteLineIf(DebugTrace, $"OnInterceptTouchEvent: return {result}");
            return(result);
        }
Example #4
0
        public override bool OnTouchEvent(MotionEvent ev)
        {
            if (_mVelocityTracker == null)
            {
                _mVelocityTracker = VelocityTracker.Obtain();
            }
            _mVelocityTracker.AddMovement(ev);


            MotionEventActions action = ev.Action;
            float x = ev.GetX();


            switch (action)
            {
            case MotionEventActions.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 = x;


                _mTouchState = _mScroller.IsFinished ? TOUCH_STATE_REST : TOUCH_STATE_HORIZONTAL_SCROLLING;


                break;

            case MotionEventActions.Move:
                var  xDiff  = (int)Math.Abs(x - _mLastMotionX);
                bool xMoved = xDiff > _mTouchSlop;


                if (xMoved)
                {
                    // Scroll if the user moved far enough along the X axis
                    _mTouchState = TOUCH_STATE_HORIZONTAL_SCROLLING;
                }


                if (_mTouchState == TOUCH_STATE_HORIZONTAL_SCROLLING)
                {
                    // Scroll to follow the motion event
                    var deltaX = (int)(_mLastMotionX - x);
                    _mLastMotionX = x;
                    int scrollX = ScrollX;


                    if (deltaX < 0)
                    {
                        if (scrollX > 0)
                        {
                            ScrollBy(Math.Max(-scrollX, deltaX), 0);
                        }
                    }
                    else if (deltaX > 0)
                    {
                        int availableToScroll =
                            GetChildAt(ChildCount - 1).Right - scrollX - Width;


                        if (availableToScroll > 0)
                        {
                            ScrollBy(Math.Min(availableToScroll, deltaX), 0);
                        }
                    }
                }


                break;


            case MotionEventActions.Up:
                if (_mTouchState == TOUCH_STATE_HORIZONTAL_SCROLLING)
                {
                    VelocityTracker velocityTracker = _mVelocityTracker;
                    velocityTracker.ComputeCurrentVelocity(VELOCITY_UNIT_PIXELS_PER_SECOND,
                                                           _mMaximumVelocity);
                    var velocityX = (int)velocityTracker.XVelocity;


                    if (velocityX > mDensityAdjustedSnapVelocity && _mCurrentScreen > 0)
                    {
                        // Fling hard enough to move left
                        SnapToScreen(_mCurrentScreen - 1);
                    }
                    else if (velocityX < -mDensityAdjustedSnapVelocity &&
                             _mCurrentScreen < ChildCount - 1)
                    {
                        // Fling hard enough to move right
                        SnapToScreen(_mCurrentScreen + 1);
                    }
                    else
                    {
                        SnapToDestination();
                    }


                    if (_mVelocityTracker != null)
                    {
                        _mVelocityTracker.Recycle();
                        _mVelocityTracker = null;
                    }
                }


                _mTouchState = TOUCH_STATE_REST;


                break;

            case MotionEventActions.Cancel:
                _mTouchState = TOUCH_STATE_REST;
                break;
            }


            return(true);
        }
Example #5
0
        public override bool OnInterceptTouchEvent(MotionEvent ev)
        {
            if (!_enabled)
            {
                return(false);
            }

            var action = (int)ev.Action & MotionEventCompat.ActionMask;

#if DEBUG
            if (action == (int)MotionEventActions.Down)
            {
                Log.Verbose(Tag, "Recieved ACTION_DOWN");
            }
#endif
            if (action == (int)MotionEventActions.Cancel || action == (int)MotionEventActions.Up ||
                (action != (int)MotionEventActions.Down && _isUnableToDrag))
            {
                EndDrag();
                return(false);
            }

            switch (action)
            {
            case (int)MotionEventActions.Move:
                DetermineDrag(ev);
                break;

            case (int)MotionEventActions.Down:
                var index = MotionEventCompat.GetActionIndex(ev);
                ActivePointerId = MotionEventCompat.GetPointerId(ev, index);
                if (ActivePointerId == InvalidPointer)
                {
                    break;
                }
                _lastMotionX = _initialMotionX = MotionEventCompat.GetX(ev, index);
                _lastMotionY = MotionEventCompat.GetY(ev, index);
                if (ThisTouchAllowed(ev))
                {
                    _isBeingDragged = false;
                    _isUnableToDrag = false;
                    if (IsMenuOpen && _viewBehind.MenuTouchInQuickReturn(_content, _curItem,
                                                                         ev.GetX() + _scrollX))
                    {
                        _quickReturn = true;
                    }
                }
                else
                {
                    _isUnableToDrag = true;
                }
                break;

            case (int)MotionEventActions.PointerUp:
                OnSecondaryPointerUp(ev);
                break;
            }

            if (!_isBeingDragged)
            {
                if (VelocityTracker == null)
                {
                    VelocityTracker = VelocityTracker.Obtain();
                }
                VelocityTracker.AddMovement(ev);
            }
            return(_isBeingDragged || _quickReturn);
        }
Example #6
0
        public override bool OnTouchEvent(MotionEvent e)
        {
            if (mVelocityTracker == null)
            {
                mVelocityTracker = VelocityTracker.Obtain();
            }
            mVelocityTracker.AddMovement(e);

            MotionEventActions action = e.Action;
            float x = e.GetX();

            switch (action)
            {
            case MotionEventActions.Down:
                if (!mScroller.IsFinished)
                {
                    mScroller.AbortAnimation();
                }

                mLastMotionX = x;

                if (mScroller.IsFinished)
                {
                    mTouchState = TOUCH_STATE_REST;
                }
                else
                {
                    mTouchState = TOUCH_STATE_HORIZONTAL_SCROLLING;
                }
                break;

            case MotionEventActions.Move:
                int  xDiff  = (int)Math.Abs(x - mLastMotionX);
                bool xMoved = xDiff > mTouchSlop;

                if (xMoved)
                {
                    mTouchState = TOUCH_STATE_HORIZONTAL_SCROLLING;
                }

                if (mTouchState == TOUCH_STATE_HORIZONTAL_SCROLLING)
                {
                    int deltaX = (int)(mLastMotionX - x);
                    mLastMotionX = x;
                    int scrollX = this.ScrollX;

                    if (deltaX < 0)
                    {
                        if (scrollX > 0)
                        {
                            ScrollBy(Math.Max(-scrollX, deltaX), 0);
                        }
                    }
                    else if (deltaX > 0)
                    {
                        if (this.ChildCount >= 1)
                        {
                            int avalableToScroll = this.GetChildAt(this.ChildCount - 1).Right - scrollX - Width;

                            if (avalableToScroll > 0)
                            {
                                ScrollBy(Math.Min(avalableToScroll, deltaX), 0);
                            }
                        }
                    }
                }
                break;

            case MotionEventActions.Up:
                if (mTouchState == TOUCH_STATE_HORIZONTAL_SCROLLING)
                {
                    VelocityTracker velocityTracker = mVelocityTracker;
                    velocityTracker.ComputeCurrentVelocity(VELOCITY_UNIT_PIXELS_PER_SECOND, mMaximumVelocity);
                    int velocityX = (int)velocityTracker.XVelocity;

                    if (velocityX > mDensityAdjustedSnapVelocity && mCurrentScreen > 0)
                    {
                        SnapToScreen(mCurrentScreen - 1);
                    }
                    else if (velocityX < -mDensityAdjustedSnapVelocity && mCurrentScreen < this.ChildCount - 1)
                    {
                        SnapToScreen(mCurrentScreen + 1);
                    }
                    else
                    {
                        SnapToDestination();
                    }

                    if (mVelocityTracker != null)
                    {
                        mVelocityTracker.Recycle();
                        mVelocityTracker = null;
                    }
                    mTouchState = TOUCH_STATE_REST;
                }
                break;

            case MotionEventActions.Cancel:
                mTouchState = TOUCH_STATE_REST;
                break;

            default:
                break;
            }
            return(true);
        }
Example #7
0
        public override bool OnTouchEvent(MotionEvent ev)
        {
            if (ev.Action == MotionEventActions.Down && ev.EdgeFlags != 0)
            {
                // Don't handle edge touches immediately -- they may actually belong to one of our
                // descendants.
                return(false);
            }

            if (!CanScroll)
            {
                return(false);
            }

            if (mVelocityTracker == null)
            {
                mVelocityTracker = VelocityTracker.Obtain();
            }
            mVelocityTracker.AddMovement(ev);

            MotionEventActions action = ev.Action;
            float y = ev.GetY();
            float x = ev.GetX();

            switch (action)
            {
            case MotionEventActions.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
                mLastMotionY = y;
                mLastMotionX = x;
                break;

            case MotionEventActions.Move:
                // Scroll to follow the motion event
                int deltaX = (int)(mLastMotionX - x);
                int deltaY = (int)(mLastMotionY - y);
                mLastMotionX = x;
                mLastMotionY = y;

                if (deltaX < 0)
                {
                    if (ScrollX < 0)
                    {
                        deltaX = 0;
                    }
                }
                else if (deltaX > 0)
                {
                    int rightEdge         = Width - PaddingRight;
                    int availableToScroll = GetChildAt(0).Right - ScrollX - rightEdge;
                    if (availableToScroll > 0)
                    {
                        deltaX = System.Math.Min(availableToScroll, deltaX);
                    }
                    else
                    {
                        deltaX = 0;
                    }
                }
                if (deltaY < 0)
                {
                    if (ScrollY < 0)
                    {
                        deltaY = 0;
                    }
                }
                else if (deltaY > 0)
                {
                    int bottomEdge        = Height - PaddingBottom;
                    int availableToScroll = GetChildAt(0).Bottom - ScrollY - bottomEdge;
                    if (availableToScroll > 0)
                    {
                        deltaY = System.Math.Min(availableToScroll, deltaY);
                    }
                    else
                    {
                        deltaY = 0;
                    }
                }
                if (deltaY != 0 || deltaX != 0)
                {
                    ScrollBy(deltaX, deltaY);
                }
                break;

            case MotionEventActions.Up:
                VelocityTracker velocityTracker = mVelocityTracker;
                velocityTracker.ComputeCurrentVelocity(1000, mMaximumVelocity);
                int initialXVelocity = (int)velocityTracker.XVelocity;
                int initialYVelocity = (int)velocityTracker.YVelocity;
                if ((System.Math.Abs(initialXVelocity) + System.Math.Abs(initialYVelocity) > mMinimumVelocity) && ChildCount > 0)
                {
                    Fling(-initialXVelocity, -initialYVelocity);
                }
                if (mVelocityTracker != null)
                {
                    mVelocityTracker.Recycle();
                    mVelocityTracker = null;
                }
                break;
            }
            return(true);
        }
Example #8
0
 public ScrollHelper(GestureHelper gestureHelper)
 {
     this.GestureHelper   = gestureHelper;
     this.VelocityTracker = VelocityTracker.Obtain();
 }
        /// <summary>
        /// Called when a touch event has been passed to the list view for processing.
        /// Process according to the event type
        /// </summary>
        /// <param name="touchedView">The view given the event - not used assumed to be owner ShoppingListView</param>
        /// <param name="touchEvent">THe touch event</param>
        /// <returns>True if the event has been consumed and should not be further processed</returns>
        public bool OnTouch(View touchedView, MotionEvent touchEvent)
        {
            // Assume the event is not consumed
            bool touchConsumed = false;

            switch (touchEvent.Action)
            {
            case MotionEventActions.Down:
            {
                // Adjust touch position to be relative to the parent view
                int[] viewCoords = new int[2];
                monitoredView.GetLocationOnScreen(viewCoords);
                int relX = ( int )touchEvent.RawX - viewCoords[0];
                int relY = ( int )touchEvent.RawY - viewCoords[1];

                // Work out if a child of the parent view has been selected
                // This is a bit of a brute force way of doing this but can cope with different height items.
                int  childIndex = 0;
                bool childFound = false;
                Rect hitRect    = new Rect();

                while ((childIndex < monitoredView.ChildCount) && (childFound == false))
                {
                    View child = monitoredView.GetChildAt(childIndex);
                    child.GetHitRect(hitRect);

                    // Check if this child has been selected - all coordinates relative to the parent
                    if (hitRect.Contains(relX, relY) == true)
                    {
                        childFound = true;

                        // Save the view
                        selectedView     = child;
                        selectedPosition = monitoredView.GetPositionForView(child);

                        // Check if this child can be selected
                        if (ItemSelectionHandler != null)
                        {
                            SelectionEventArgs args = new SelectionEventArgs {
                                Position = selectedPosition, ViewSelected = child
                            };
                            ItemSelectionHandler.Invoke(this, args);
                            if (args.Cancel == true)
                            {
                                selectedView = null;
                            }
                        }
                    }
                    else
                    {
                        childIndex++;
                    }
                }

                // If a child hasn't been selected check whether or not group swipes are allowed
                if (childFound == false)
                {
                    selectedPosition = -1;

                    // If group swiping is allowed (in either direction) then specify the parent view as the selected view
                    if ((RightGroupSwipe == true) || (LeftGroupSwipe == true))
                    {
                        selectedView = monitoredView;
                    }
                }

                // If a view has been selected then set up a velocity tracker and record the initial x coordinate
                if (selectedView != null)
                {
                    velocity = VelocityTracker.Obtain();
                    velocity.AddMovement(touchEvent);

                    // Record the raw starting X position to determine how far to translate the view in response to user
                    // moves
                    initialDownX = touchEvent.RawX;

                    touchConsumed = true;
                }

                break;
            }

            case MotionEventActions.Move:
            {
                // If a view has been selected then determine how far it has been moved
                if (selectedView != null)
                {
                    // Add the current movement to those held by the tracker
                    velocity.AddMovement(touchEvent);

                    float deltaX = touchEvent.RawX - initialDownX;

                    if (swiping == false)
                    {
                        // Not already swiping. Check if the movement is deliberate and is more horizontal than vertical
                        // Get the velocity in pixels / sec

                        // Check if swiping is actually allowed
                        if (SwipingAllowed(deltaX) == true)
                        {
                            velocity.ComputeCurrentVelocity(1000);

                            if ((Math.Abs(deltaX) > wander) &&
                                (Math.Abs(velocity.XVelocity) > Math.Abs(velocity.YVelocity)))
                            {
                                swiping = true;
                            }
                        }
                    }

                    if (swiping == true)
                    {
                        // Move the view unless swiping is not allowed
                        if (SwipingAllowed(deltaX) == true)
                        {
                            // Move the selected view
                            // If this is a group swipe then move the parent view instead
                            if (((deltaX > 0) && (RightGroupSwipe == true)) ||
                                ((deltaX < 0) && (LeftGroupSwipe == true)))
                            {
                                monitoredView.TranslationX = deltaX;

                                // If moving left and there is a right reveal view then move it as well
                                if ((deltaX < 0) && (RightRevealView != null))
                                {
                                    RightRevealView.TranslationX = monitoredView.Width + deltaX;
                                    RightRevealView.Visibility   = ViewStates.Visible;
                                }

                                // If moving right and there is a left reveal view then move it as well
                                if ((deltaX > 0) && (LeftRevealView != null))
                                {
                                    LeftRevealView.TranslationX = deltaX - monitoredView.Width;
                                    LeftRevealView.Visibility   = ViewStates.Visible;
                                }

                                // If we've been moving an individual child then make sure it is put back where
                                // we found it. Don't so this if the selected child is the parent
                                if ((selectedView != monitoredView) && (selectedView.TranslationX != 0))
                                {
                                    selectedView.TranslationX = 0;
                                }
                            }
                            else
                            {
                                // Only move this view if it is not the parent view
                                if (selectedView != monitoredView)
                                {
                                    selectedView.TranslationX = deltaX;
                                }
                            }
                        }

                        touchConsumed = true;
                    }
                }

                break;
            }

            case MotionEventActions.Up:
            {
                if (swiping == true)
                {
                    // Assume no fling detected
                    bool flingRightDetected = false;
                    bool flingLeftDetected  = false;

                    // Assume a slow drag rather than a fast fling
                    bool wasFlung = false;

                    // Add the current movement to those held by the tracker and detemine the curent velocities
                    velocity.AddMovement(touchEvent);
                    velocity.ComputeCurrentVelocity(1000);

                    float absXVelocity = Math.Abs(velocity.XVelocity);
                    float absYVelocity = Math.Abs(velocity.YVelocity);

                    float deltaX = touchEvent.RawX - initialDownX;

                    // First of all detect a fling.
                    // If the absolute velocity is greater than the fling minimum and the movement is still
                    // in a mainly horizontal direction then its a fling.
                    // Also ensure that the current delta is in the same direction as the fling, i.e. make sure that
                    // the view has been repositioned back to where it started before processing a fling in the opposite
                    // direction
                    if ((absXVelocity > minimumFlingVelocity) && (absXVelocity > (absYVelocity * 2)))
                    {
                        // Check if the fling is in an allowed direction - may have changed direction since last move
                        if (SwipingAllowed(velocity.XVelocity) == true)
                        {
                            // Make sure that the fling direction agrees with the current position of the view
                            if (Math.Sign(velocity.XVelocity) == Math.Sign(deltaX))
                            {
                                flingRightDetected = (velocity.XVelocity > 0);
                                flingLeftDetected  = (velocity.XVelocity < 0);
                                wasFlung           = true;
                            }
                        }
                    }
                    // More than half the width moved?
                    else if ((SwipingAllowed(deltaX) == true) && (Math.Abs(deltaX) > (monitoredView.Width / 2)))
                    {
                        flingRightDetected = (deltaX > 0);
                        flingLeftDetected  = (deltaX < 0);
                    }

                    // Animate the selected view either to the right, left or back to the start
                    // Work out whether the selected child or the parent view needs to be animated
                    // Assume the child
                    View animatedView = selectedView;
                    if (((deltaX > 0) && (RightGroupSwipe == true)) ||
                        ((deltaX < 0) && (LeftGroupSwipe == true)))
                    {
                        animatedView = monitoredView;
                    }

                    // If the animated view has not changed position then skip the animation processing
                    // Thius assumes that a velocity based fling will only occur after the view has
                    // moved a little first TBD
                    if (animatedView.TranslationX != 0)
                    {
                        if (flingRightDetected == true)
                        {
                            // Animate the view fully off to the right and report the event back to the view at the
                            // end of the animation
                            SimpleAnimate(animatedView, monitoredView.Width,
                                          new ObjectAnimatorListenerAdapter((animation) =>
                                {
                                    FlingRightHandler?.Invoke(this, new SwipeEventArgs {
                                        Position = selectedPosition, WasFlung = wasFlung
                                    });
                                    if (animatedView != monitoredView)
                                    {
                                        animatedView.TranslationX = 0;
                                    }
                                }));

                            // If this is a parent view swipe and there's a left reveal then animate it across as well
                            if ((animatedView == monitoredView) && (LeftRevealView != null))
                            {
                                SimpleAnimate(LeftRevealView, 0, null);
                            }
                        }
                        else if (flingLeftDetected == true)
                        {
                            // Animate the view fully off to the left and report the event back to the view at the
                            // end of the animation
                            SimpleAnimate(animatedView, -monitoredView.Width,
                                          new ObjectAnimatorListenerAdapter((animation) =>
                                {
                                    FlingLeftHandler?.Invoke(this, new SwipeEventArgs {
                                        Position = selectedPosition, WasFlung = wasFlung
                                    });
                                    if (animatedView != monitoredView)
                                    {
                                        animatedView.TranslationX = 0;
                                    }
                                }));

                            // If this is a parent view swipe and there's a right reveal then animate it across as well
                            if ((animatedView == monitoredView) && (RightRevealView != null))
                            {
                                SimpleAnimate(RightRevealView, 0, null);
                            }
                        }
                        else
                        {
                            // No fling so animate the views back to their starting positions
                            SimpleAnimate(animatedView, 0, null);

                            // If the parent view was being moved and there's a left or right review then animate them back
                            // to their starting positions as well
                            if (animatedView == monitoredView)
                            {
                                if ((deltaX > 0) && (LeftRevealView != null))
                                {
                                    // Animate the view back to the left
                                    SimpleAnimate(LeftRevealView, -monitoredView.Width, null);
                                }

                                if ((deltaX < 0) && (RightRevealView != null))
                                {
                                    // Animate the view back to the right
                                    SimpleAnimate(RightRevealView, monitoredView.Width, null);
                                }
                            }
                        }
                    }
                }

                // Reset state variables
                selectedView = null;
                swiping      = false;

                // Free up the VelocityTracker
                if (velocity != null)
                {
                    velocity.Recycle();
                    velocity = null;
                }

                break;
            }
            }

            return(touchConsumed);
        }
Example #10
0
        public override bool OnTouchEvent(MotionEvent e)
        {
            if (mVelocityTracker == null)
            {
                mVelocityTracker = VelocityTracker.Obtain();
            }
            mVelocityTracker.AddMovement(e);
            MotionEventActions action = e.Action;

            if (action == MotionEventActions.Down)
            {
                x = e.GetX();

                if (IsSlided())
                {
                    dispatched = DispatchTouchEventToView(GetChildAt(0), e);
                }
                else
                {
                    dispatched = DispatchTouchEventToView(GetChildAt(1), e);
                }
            }
            else if (action == MotionEventActions.Move)
            {
                if (dispatched)
                {
                    if (IsSlided())
                    {
                        DispatchTouchEventToView(GetChildAt(0), e);
                    }
                    else
                    {
                        DispatchTouchEventToView(GetChildAt(1), e);
                    }
                }
                else
                {
                    float dx   = e.GetX() - x;
                    View  view = this.GetChildAt(1);
                    int   left = (int)(view.Left + dx);
                    if (left >= 0)
                    {
                        view.Layout(left, view.Top, view.Width + left,
                                    view.Top + view.Height);
                    }
                }
                x = e.GetX();
            }
            else if (action == MotionEventActions.Cancel ||
                     action == MotionEventActions.Up)
            {
                if (dispatched)
                {
                    if (IsSlided())
                    {
                        DispatchTouchEventToView(GetChildAt(0), e);
                    }
                    else
                    {
                        DispatchTouchEventToView(GetChildAt(1), e);
                    }
                }
                else
                {
                    mVelocityTracker.ComputeCurrentVelocity(1000);
                    int velocityX = (int)mVelocityTracker.GetXVelocity(0);
                    if (velocityX > VELOCITY_X_SPEED)
                    {
                        SetSlided(true);
                    }
                    else if (velocityX < -VELOCITY_X_SPEED)
                    {
                        SetSlided(false);
                    }
                    else
                    {
                        View view = GetChildAt(1);
                        if (view.Left >= view.Width / 2)
                        {
                            SetSlided(true);
                        }
                        else
                        {
                            SetSlided(false);
                        }
                    }
                    if (mVelocityTracker != null)
                    {
                        try
                        {
                            mVelocityTracker.Recycle();
                        }
                        catch
                        { }
                    }
                }
            }
            else if (!IsSlided())
            {
                DispatchTouchEventToView(GetChildAt(1), e);
            }
            return(true);
        }
Example #11
0
        public override bool OnTouchEvent(MotionEvent ev)
        {
            if (mIsVerbose)
            {
                Log.Verbose(TAG, "onTouchEvent: " + ((int)ev.Action & MotionEventCompat.ActionMask));
            }

            if (mVelocityTracker == null)
            {
                mVelocityTracker = VelocityTracker.Obtain();
            }
            mVelocityTracker.AddMovement(ev);

            var action = ev.Action;

            switch ((int)action & MotionEventCompat.ActionMask)
            {
            case (int)MotionEventActions.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
                mDownMotionX     = ev.GetX();
                mDownMotionY     = ev.GetY();
                mDownScrollX     = ScrollX;
                mActivePointerId = MotionEventCompat.GetPointerId(ev, 0);
                break;

            case (int)MotionEventActions.Move:
                if (mIsVerbose)
                {
                    Log.Verbose(TAG, "mTouchState=" + mTouchState);
                }

                if (mTouchState == TOUCH_STATE_SCROLLING)
                {
                    // Scroll to follow the motion event
                    int   pointerIndex = MotionEventCompat.FindPointerIndex(ev, mActivePointerId);
                    float x            = MotionEventCompat.GetX(ev, pointerIndex);

                    View lastChild  = GetChildAt(ChildCount - 1);
                    int  maxScrollX = lastChild.Right - Width;
                    ScrollTo(Math.Max(0, Math.Min(maxScrollX,
                                                  (int)(mDownScrollX + mDownMotionX - x
                                                        ))), 0);
                    if (mOnScrollListener != null)
                    {
                        mOnScrollListener.OnScroll(GetCurrentScreenFraction());
                    }
                }
                else if (mTouchState == TOUCH_STATE_REST)
                {
                    if (mLocked)
                    {
                        // we're locked on the current screen, don't allow moving
                        break;
                    }

                    /*
                     * Locally do absolute value. mLastMotionX is set to the y value
                     * of the down event.
                     */
                    int   pointerIndex = MotionEventCompat.FindPointerIndex(ev, mActivePointerId);
                    float x            = MotionEventCompat.GetX(ev, pointerIndex);
                    float y            = MotionEventCompat.GetY(ev, pointerIndex);
                    int   xDiff        = (int)Math.Abs(x - mDownMotionX);
                    int   yDiff        = (int)Math.Abs(y - mDownMotionY);

                    bool xPaged = xDiff > mPagingTouchSlop;
                    bool xMoved = xDiff > mTouchSlop;
                    bool yMoved = yDiff > mTouchSlop;

                    if (xMoved || yMoved)
                    {
                        if (xPaged)
                        {
                            // Scroll if the user moved far enough along the X axis
                            mTouchState = TOUCH_STATE_SCROLLING;
                        }
                        // Either way, cancel any pending longpress
                        if (mAllowLongPress)
                        {
                            mAllowLongPress = false;
                            // Try canceling the long press. It could also have been scheduled
                            // by a distant descendant, so use the mAllowLongPress flag to block
                            // everything
                            View currentScreen = GetScreenAt(mCurrentScreen);
                            if (currentScreen != null)
                            {
                                currentScreen.CancelLongPress();
                            }
                        }
                    }
                }
                break;

            case (int)MotionEventActions.Up:
                if (mTouchState == TOUCH_STATE_SCROLLING)
                {
                    int             activePointerId = mActivePointerId;
                    int             pointerIndex    = MotionEventCompat.FindPointerIndex(ev, activePointerId);
                    float           x = MotionEventCompat.GetX(ev, pointerIndex);
                    VelocityTracker velocityTracker = mVelocityTracker;
                    velocityTracker.ComputeCurrentVelocity(1000, mMaximumVelocity);
                    //TODO(minsdk8): int velocityX = (int) MotionEventUtils.getXVelocity(velocityTracker, activePointerId);
                    int  velocityX = (int)velocityTracker.XVelocity;
                    bool isFling   = Math.Abs(mDownMotionX - x) > MIN_LENGTH_FOR_FLING;

                    float scrolledPos = GetCurrentScreenFraction();
                    int   whichScreen = Math.Round(scrolledPos);

                    if (isFling && mIsVerbose)
                    {
                        Log.Verbose(TAG, "isFling, whichScreen=" + whichScreen
                                    + " scrolledPos=" + scrolledPos
                                    + " mCurrentScreen=" + mCurrentScreen
                                    + " velocityX=" + velocityX);
                    }
                    if (isFling && velocityX > SNAP_VELOCITY && mCurrentScreen > 0)
                    {
                        // Fling hard enough to move left
                        // Don't fling across more than one screen at a time.
                        int bound = scrolledPos <= whichScreen ?
                                    mCurrentScreen - 1 : mCurrentScreen;
                        SnapToScreen(Math.Min(whichScreen, bound));
                    }
                    else if (isFling && velocityX < -SNAP_VELOCITY &&
                             mCurrentScreen < ChildCount - 1)
                    {
                        // Fling hard enough to move right
                        // Don't fling across more than one screen at a time.
                        int bound = scrolledPos >= whichScreen ?
                                    mCurrentScreen + 1 : mCurrentScreen;
                        SnapToScreen(Math.Max(whichScreen, bound));
                    }
                    else
                    {
                        SnapToDestination();
                    }
                }
                else
                {
                    PerformClick();
                }
                mTouchState      = TOUCH_STATE_REST;
                mActivePointerId = INVALID_POINTER;
                // Can't do this -> // Intentially fall through to cancel
                mTouchState      = TOUCH_STATE_REST;
                mActivePointerId = INVALID_POINTER;
                if (mVelocityTracker != null)
                {
                    mVelocityTracker.Recycle();
                    mVelocityTracker = null;
                }
                break;

            case (int)MotionEventActions.Cancel:
                mTouchState      = TOUCH_STATE_REST;
                mActivePointerId = INVALID_POINTER;
                if (mVelocityTracker != null)
                {
                    mVelocityTracker.Recycle();
                    mVelocityTracker = null;
                }
                break;


            case (int)MotionEventCompat.ActionPointerUp:
                OnSecondaryPointerUp(ev);
                break;
            }

            return(true);
        }
Example #12
0
        public override bool OnInterceptTouchEvent(MotionEvent ev)
        {
            /*
             * This method JUST determines whether we want to intercept the motion.
             * If we return true, onTouchEvent will be called and we do the actual
             * scrolling there.
             */

            // Begin tracking velocity even before we have intercepted touch events.
            if (mVelocityTracker == null)
            {
                mVelocityTracker = VelocityTracker.Obtain();
            }
            mVelocityTracker.AddMovement(ev);

            /*
             * Shortcut the most recurring case: the user is in the dragging
             * state and he is moving his finger.  We want to intercept this
             * motion.
             */
            var action = ev.Action;

            if (mIsVerbose)
            {
                Log.Verbose(TAG, "onInterceptTouchEvent: " + (ev.Action & MotionEventActions.Mask));
            }
            if (((action & MotionEventActions.Mask) == MotionEventActions.Move) &&
                (mTouchState == TOUCH_STATE_SCROLLING))
            {
                if (mIsVerbose)
                {
                    Log.Verbose(TAG, "Intercepting touch events");
                }
                return(true);
            }

            switch (action & MotionEventActions.Mask)
            {
            case MotionEventActions.Move: {
                if (mLocked)
                {
                    // we're locked on the current screen, don't allow moving
                    break;
                }

                /*
                 * Locally do absolute value. mDownMotionX is set to the y value
                 * of the down event.
                 */
                int   pointerIndex = MotionEventCompat.FindPointerIndex(ev, mActivePointerId);
                float x            = MotionEventCompat.GetX(ev, pointerIndex);
                float y            = MotionEventCompat.GetY(ev, pointerIndex);
                int   xDiff        = (int)Java.Lang.Math.Abs(x - mDownMotionX);
                int   yDiff        = (int)Java.Lang.Math.Abs(y - mDownMotionY);

                bool xPaged = xDiff > mPagingTouchSlop;
                bool xMoved = xDiff > mTouchSlop;
                bool yMoved = yDiff > mTouchSlop;

                if (xMoved || yMoved)
                {
                    if (xPaged)
                    {
                        // Scroll if the user moved far enough along the X axis
                        mTouchState = TOUCH_STATE_SCROLLING;
                    }
                    // Either way, cancel any pending longpress
                    if (mAllowLongPress)
                    {
                        mAllowLongPress = false;
                        // Try canceling the long press. It could also have been scheduled
                        // by a distant descendant, so use the mAllowLongPress flag to block
                        // everything
                        View currentScreen = GetScreenAt(mCurrentScreen);
                        if (currentScreen != null)
                        {
                            currentScreen.CancelLongPress();
                        }
                    }
                }
                break;
            }

            case MotionEventActions.Down: {
                float x = ev.GetX();
                float y = ev.GetY();
                // Remember location of down touch
                mDownMotionX     = x;
                mDownMotionY     = y;
                mDownScrollX     = ScrollX;
                mActivePointerId = MotionEventCompat.GetPointerId(ev, 0);
                mAllowLongPress  = true;

                /*
                 * If being flinged and user touches the screen, initiate drag;
                 * otherwise don't.  mScroller.isFinished should be false when
                 * being flinged.
                 */
                mTouchState = mScroller.IsFinished ? TOUCH_STATE_REST : TOUCH_STATE_SCROLLING;
                break;
            }

            case MotionEventActions.Cancel:
            case MotionEventActions.Up:
                // Release the drag
                mTouchState      = TOUCH_STATE_REST;
                mAllowLongPress  = false;
                mActivePointerId = INVALID_POINTER;
                if (mVelocityTracker == null)
                {
                    mVelocityTracker.Recycle();
                    mVelocityTracker = null;
                }
                break;



            case MotionEventActions.PointerUp:
                OnSecondaryPointerUp(ev);
                break;
            }

            /*
             * The only time we want to intercept motion events is if we are in the
             * drag mode.
             */
            bool intercept = mTouchState != TOUCH_STATE_REST;

            if (mIsVerbose)
            {
                Log.Verbose(TAG, "Intercepting touch events: " + intercept);
            }
            return(intercept);
        }
        public virtual bool OnTouchEvent(Android.Views.MotionEvent ev)
        {
            switch (ev.Action)
            {
            case MotionEventActions.Down:
            {
                mVelocityTracker = VelocityTracker.Obtain();
                if (null != mVelocityTracker)
                {
                    mVelocityTracker.AddMovement(ev);
                }
                else
                {
                    Log.Info(LOG_TAG, "Velocity tracker is null");
                }

                mLastTouchX = GetActiveX(ev);
                mLastTouchY = GetActiveY(ev);
                mIsDragging = false;
                break;
            }

            case MotionEventActions.Move: {
                float x = GetActiveX(ev);
                float y = GetActiveY(ev);
                float dx = x - mLastTouchX, dy = y - mLastTouchY;

                if (!mIsDragging)
                {
                    // Use Pythagoras to see if drag length is larger than
                    // touch slop
                    mIsDragging = FloatMath.Sqrt((dx * dx) + (dy * dy)) >= mTouchSlop;
                }

                if (mIsDragging)
                {
                    mListener.OnDrag(dx, dy);
                    mLastTouchX = x;
                    mLastTouchY = y;

                    if (null != mVelocityTracker)
                    {
                        mVelocityTracker.AddMovement(ev);
                    }
                }
                break;
            }

            case MotionEventActions.Cancel: {
                // Recycle Velocity Tracker
                if (null != mVelocityTracker)
                {
                    mVelocityTracker.Recycle();
                    mVelocityTracker = null;
                }
                break;
            }

            case MotionEventActions.Up: {
                if (mIsDragging)
                {
                    if (null != mVelocityTracker)
                    {
                        mLastTouchX = GetActiveX(ev);
                        mLastTouchY = GetActiveY(ev);

                        // Compute velocity within the last 1000ms
                        mVelocityTracker.AddMovement(ev);
                        mVelocityTracker.ComputeCurrentVelocity(1000);

                        float vX = mVelocityTracker.GetXVelocity(0), vY = mVelocityTracker
                                                                          .GetYVelocity(0);

                        // If the velocity is greater than minVelocity, call
                        // listener
                        if (Math.Max(Math.Abs(vX), Math.Abs(vY)) >= mMinimumVelocity)
                        {
                            mListener.OnFling(mLastTouchX, mLastTouchY, -vX,
                                              -vY);
                        }
                    }
                }

                // Recycle Velocity Tracker
                if (null != mVelocityTracker)
                {
                    mVelocityTracker.Recycle();
                    mVelocityTracker = null;
                }
                break;
            }
            }

            return(true);
        }