private void OnTouch(object sender, SKTouchEventArgs e) { // Save time, when the event occures long ticks = DateTime.Now.Ticks; var location = GetScreenPosition(e.Location); if (e.ActionType == SKTouchAction.Pressed) { _firstTouch = location; _touches[e.Id] = new TouchEvent(e.Id, location, ticks); _velocityTracker.Clear(); // Do we have a doubleTapTestTimer running? // If yes, stop it and increment _numOfTaps if (_doubleTapTestTimer != null) { _doubleTapTestTimer.Dispose(); _doubleTapTestTimer = null; _numOfTaps++; } else { _numOfTaps = 1; } e.Handled = OnTouchStart(_touches.Select(t => t.Value.Location).ToList()); } if (e.ActionType == SKTouchAction.Released) { // Delete e.Id from _touches, because finger is released var releasedTouch = _touches[e.Id]; _touches.Remove(e.Id); double velocityX; double velocityY; (velocityX, velocityY) = _velocityTracker.CalcVelocity(e.Id, ticks); // Is this a fling or swipe? if (_touches.Count == 0) { if (velocityX > 10000 || velocityY > 10000) { // This was the last finger on screen, so this is a fling e.Handled = OnFlinged(velocityX, velocityY); } // Do we have a tap event if (releasedTouch == null) { e.Handled = false; return; } // While tapping on screen, there could be a small movement of the finger // (especially on Samsungs). So check, if touch start location isn't more // than 2 pixels away from touch end location. var isAround = Math.Abs(releasedTouch.Location.X - _firstTouch.X) < 2 && Math.Abs(releasedTouch.Location.Y - _firstTouch.Y) < 2; // If touch start and end is in the same area and the touch time is shorter // than longTap, than we have a tap. if (isAround && ticks - releasedTouch.Tick < (e.DeviceType == SKTouchDeviceType.Mouse ? shortClick : longTap) * 10000) { // Start a timer with timeout delayTap ms. If than isn't arrived another tap, than it is a single _doubleTapTestTimer = new System.Threading.Timer((l) => { if (_numOfTaps > 1) { if (!e.Handled) { e.Handled = OnDoubleTapped(location, _numOfTaps); } } else if (!e.Handled) { e.Handled = OnSingleTapped((Geometries.Point)l); } _numOfTaps = 1; if (_doubleTapTestTimer != null) { _doubleTapTestTimer.Dispose(); } _doubleTapTestTimer = null; }, location, UseDoubleTap ? delayTap : 0, -1); } else if (releasedTouch.Location.Equals(_firstTouch) && ticks - releasedTouch.Tick >= longTap * 10000) { if (!e.Handled) { e.Handled = OnLongTapped(location); } } } if (_touches.Count == 1) { e.Handled = OnTouchStart(_touches.Select(t => t.Value.Location).ToList()); } if (!e.Handled) { e.Handled = OnTouchEnd(_touches.Select(t => t.Value.Location).ToList(), releasedTouch.Location); } } if (e.ActionType == SKTouchAction.Moved) { _touches[e.Id] = new TouchEvent(e.Id, location, ticks); if (e.InContact) { _velocityTracker.AddEvent(e.Id, location, ticks); } if (e.InContact && !e.Handled) { e.Handled = OnTouchMove(_touches.Select(t => t.Value.Location).ToList()); } else { e.Handled = OnHovered(_touches.Select(t => t.Value.Location).FirstOrDefault()); } } if (e.ActionType == SKTouchAction.Cancelled) { _touches.Remove(e.Id); } if (e.ActionType == SKTouchAction.Exited) { } if (e.ActionType == SKTouchAction.Entered) { } }
private void OnTouch(object sender, SKTouchEventArgs e) { // Save time, when the event occures long ticks = DateTime.Now.Ticks; var location = GetScreenPosition(e.Location); // Get finger/handler for this event if (!_fingers.Keys.Contains(e.Id)) { if (_fingers.Count < 10) { _fingers.Add(e.Id, _fingers.Count); } } var id = _fingers[e.Id]; if (e.ActionType == SKTouchAction.Pressed) { _firstTouch = location; _touches[id] = new TouchEvent(id, location, ticks); _velocityTracker.Clear(); // Do we have a doubleTapTestTimer running? // If yes, stop it and increment _numOfTaps if (_doubleTapTestTimer != null) { _doubleTapTestTimer.Dispose(); _doubleTapTestTimer = null; _numOfTaps++; } else { _numOfTaps = 1; } e.Handled = OnTouchStart(_touches.Select(t => t.Value.Location).ToList()); } if (e.ActionType == SKTouchAction.Released) { // Delete e.Id from _fingers, because finger is released _fingers.Remove(e.Id); double velocityX; double velocityY; (velocityX, velocityY) = _velocityTracker.CalcVelocity(id, ticks); // Is this a fling or swipe? if (velocityX > 10000 || velocityY > 10000) { System.Diagnostics.Debug.WriteLine($"Velocity X = {velocityX}, Velocity Y = {velocityY}"); e.Handled = OnFlinged(velocityX, velocityY); } // Do we have a tap event if (_touches.Count == 0 || _touches[id] == null) { e.Handled = false; return; } if (_touches[id].Location.Equals(_firstTouch) && ticks - _touches[id].Tick < (e.DeviceType == SKTouchDeviceType.Mouse ? shortClick : longTap) * 10000) { // Start a timer with timeout delayTap ms. If than isn't arrived another tap, than it is a single _doubleTapTestTimer = new System.Threading.Timer((l) => { if (_numOfTaps > 1) { if (!e.Handled) { e.Handled = OnDoubleTapped(location, _numOfTaps); } } else if (!e.Handled) { e.Handled = OnSingleTapped((Geometries.Point)l); } _numOfTaps = 1; if (_doubleTapTestTimer != null) { _doubleTapTestTimer.Dispose(); } _doubleTapTestTimer = null; }, location, UseDoubleTap ? delayTap : 0, -1); } else if (_touches[id].Location.Equals(_firstTouch) && ticks - _touches[id].Tick >= longTap * 10000) { if (!e.Handled) { e.Handled = OnLongTapped(location); } } var releasedTouch = _touches[id]; _touches.Remove(id); if (!e.Handled) { e.Handled = OnTouchEnd(_touches.Select(t => t.Value.Location).ToList(), releasedTouch.Location); } } if (e.ActionType == SKTouchAction.Moved) { _touches[id] = new TouchEvent(id, location, ticks); if (e.InContact) { _velocityTracker.AddEvent(id, location, ticks); } if (e.InContact && !e.Handled) { e.Handled = OnTouchMove(_touches.Select(t => t.Value.Location).ToList()); } else { e.Handled = OnHovered(_touches.Select(t => t.Value.Location).FirstOrDefault()); } } }