protected virtual void OnFlingDetected(SKFlingDetectedEventArgs e) => FlingDetected?.Invoke(this, e);
private bool OnTouchReleased(SKTouchEventArgs e) { var handled = false; var ticks = DateTime.Now.Ticks; var location = e.Location; var releasedTouch = touches[e.Id]; touches.Remove(e.Id); var points = GetInContactTouchPoints(); // no more fingers on the screen if (points.Length == 0) { // check to see if it was a fling var velocity = flingTracker.CalculateVelocity(e.Id, ticks); if (Math.Abs(velocity.X * velocity.Y) > (flingVelocityThreshold * flingVelocityThreshold)) { var args = new SKFlingDetectedEventArgs(velocity.X, velocity.Y); OnFlingDetected(args); handled = args.Handled; } // when tapping, the finger never goes to exactly the same location var isAround = SKPoint.Distance(releasedTouch.Location, initialTouch) < touchSlopPixels; if (isAround && (ticks - releasedTouch.Tick) < (e.DeviceType == SKTouchDeviceType.Mouse ? shortClickTicks : longTapTicks)) { // add a timer to detect the type of tap (single or multi) void TimerHandler(object state) { var l = (SKPoint)state; if (!handled) { if (tapCount > 1) { var args = new SKTapDetectedEventArgs(location, tapCount); OnDoubleTapDetected(args); handled = args.Handled; } else { var args = new SKTapDetectedEventArgs(l); OnSingleTapDetected(args); handled = args.Handled; } } tapCount = 1; multiTapTimer?.Dispose(); multiTapTimer = null; }; multiTapTimer = new Timer(TimerHandler, location, delayTapMilliseconds, -1); } else if (isAround && (ticks - releasedTouch.Tick) >= longTapTicks) { // if the finger was down for a long time, then it is a long tap if (!handled) { var args = new SKTapDetectedEventArgs(location); OnLongPressDetected(args); handled = args.Handled; } } } // update the fling tracker flingTracker.RemoveId(e.Id); if (points.Length == 1) { // if there is still 1 finger on the screen, then try start a new gesture var args = new SKGestureEventArgs(points); OnGestureStarted(args); handled = args.Handled; // if no gesture was started, then we will handle it if (!handled) { touchMode = TouchMode.Single; previousValues.Center = points[0]; handled = true; } } if (!handled) { // the gesture was not handled, so end it var args = new SKGestureEventArgs(points); OnGestureEnded(args); handled = args.Handled; if (points.Length == 0) { touchMode = TouchMode.None; } } return(handled); }