23 private readonly Dictionary<int, SwipeState> _activeSwipes =
new();
24 private readonly HashSet<int> _activeContacts =
new();
25 private bool _isMultiTouchSequence;
26 private bool _isDisposed;
45 public event EventHandler<SwipedEventArgs>?
Swiped;
59 _touchInput = touchInput ??
throw new ArgumentNullException(nameof(touchInput));
60 _touchInput.TouchBegan += OnTouchBegan;
61 _touchInput.TouchEnded += OnTouchEnded;
66 _activeContacts.Add(e.
Touch.Id);
68 if (_activeContacts.Count > 1)
70 _isMultiTouchSequence =
true;
71 _activeSwipes.Clear();
75 if (!_isMultiTouchSequence)
76 _activeSwipes[e.
Touch.Id] =
new SwipeState(e.
Touch.Position, e.
Tick);
79 private void OnTouchEnded(
object? sender, TouchEventArgs e)
81 _activeContacts.Remove(e.Touch.Id);
83 if (_isMultiTouchSequence)
85 _activeSwipes.Remove(e.Touch.Id);
86 if (_activeContacts.Count == 0)
87 _isMultiTouchSequence =
false;
91 if (!_activeSwipes.TryGetValue(e.Touch.Id, out var state))
94 _activeSwipes.Remove(e.Touch.Id);
100 var endPos = e.Touch.Position;
101 var dx = endPos.X - state.StartPosition.X;
102 var dy = endPos.Y - state.StartPosition.Y;
104 var distance = Math.Sqrt(dx * dx + dy * dy);
105 var elapsed = HighResTimer.GetDuration(state.StartTick, e.Tick);
110 var speed = distance / elapsed;
112 if (!WouldRecognize(distance, elapsed))
115 var direction = Math.Abs(dx) >= Math.Abs(dy)
119 Swiped?.Invoke(
this,
new SwipedEventArgs(direction, state.StartPosition, endPos, speed));
128 if (_isDisposed)
return;
131 _touchInput.TouchBegan -= OnTouchBegan;
132 _touchInput.TouchEnded -= OnTouchEnded;
136 internal void Reset()
138 _activeSwipes.Clear();
139 _activeContacts.Clear();
140 _isMultiTouchSequence =
false;
143 internal bool WouldRecognize(
double distance,
double elapsedSeconds)
144 => elapsedSeconds > 0 &&
148 private readonly record
struct SwipeState(Point StartPosition, long StartTick);