From 353001411e1da308428f9e64b5579a678ed83cf4 Mon Sep 17 00:00:00 2001 From: Rachel Kang Date: Tue, 18 Jul 2023 14:37:25 -0400 Subject: [PATCH 01/12] Implement on Windows and add unit tests --- .../GesturePlatformManager.Windows.cs | 10 ++++++- .../src/Core/PointerGestureRecognizer.cs | 26 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.Windows.cs b/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.Windows.cs index 55a5a2b1642d..b8da881ca119 100644 --- a/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.Windows.cs +++ b/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.Windows.cs @@ -487,7 +487,7 @@ void OnPointerReleased(object sender, PointerRoutedEventArgs e) { uint id = e.Pointer.PointerId; if (_fingers.Contains(id)) - _fingers.Remove(id); + _fingers.Remove(id); SwipeComplete(true); PinchComplete(true); PanComplete(true); @@ -518,6 +518,14 @@ void OnPgrPointerReleased(object sender, PointerRoutedEventArgs e) => recognizer.SendPointerReleased(view, (relativeTo) => GetPosition(relativeTo, e), _control is null ? null : new PlatformPointerEventArgs(_control, e))); + void OnPgrPointerPressed(object sender, PointerRoutedEventArgs e) + => HandlePgrPointerEvent(e, (view, recognizer) + => recognizer.SendPointerPressed(view, (relativeTo) => GetPosition(relativeTo, e))); + + void OnPgrPointerReleased(object sender, PointerRoutedEventArgs e) + => HandlePgrPointerEvent(e, (view, recognizer) + => recognizer.SendPointerReleased(view, (relativeTo) => GetPosition(relativeTo, e))); + private void HandlePgrPointerEvent(PointerRoutedEventArgs e, Action SendPointerEvent) { var view = Element as View; diff --git a/src/Controls/src/Core/PointerGestureRecognizer.cs b/src/Controls/src/Core/PointerGestureRecognizer.cs index c0003002b3dd..63620e314621 100644 --- a/src/Controls/src/Core/PointerGestureRecognizer.cs +++ b/src/Controls/src/Core/PointerGestureRecognizer.cs @@ -248,6 +248,32 @@ internal void SendPointerReleased(View sender, Func? getPosit handler?.Invoke(sender, new PointerEventArgs(getPosition, platformArgs)); } + /// + /// For internal use by the .NET MAUI platform. + /// + internal void SendPointerPressed(View sender, Func? getPosition) + { + ICommand cmd = PointerPressedCommand; + if (cmd?.CanExecute(PointerPressedCommandParameter) == true) + cmd.Execute(PointerPressedCommandParameter); + + EventHandler? handler = PointerPressed; + handler?.Invoke(sender, new PointerEventArgs(getPosition)); + } + + /// + /// For internal use by the .NET MAUI platform. + /// + internal void SendPointerReleased(View sender, Func? getPosition) + { + ICommand cmd = PointerReleasedCommand; + if (cmd?.CanExecute(PointerReleasedCommandParameter) == true) + cmd.Execute(PointerReleasedCommandParameter); + + EventHandler? handler = PointerReleased; + handler?.Invoke(sender, new PointerEventArgs(getPosition)); + } + internal static void SetupForPointerOverVSM( VisualElement element, Action updatePointerState, From 33b37004563f26b46fde3d48f20861e0e2300991 Mon Sep 17 00:00:00 2001 From: Rachel Kang Date: Thu, 3 Aug 2023 16:01:34 -0400 Subject: [PATCH 02/12] work in progress --- .../samples/Controls.Sample/MauiProgram.cs | 2 +- .../GesturePlatformManager.iOS.cs | 101 ++++++++++++------ .../iOS/CustomHoverGestureRecognizer.cs | 39 ++++--- .../iOS/CustomPressGestureRecognizer.cs | 86 +++++++++++++++ 4 files changed, 174 insertions(+), 54 deletions(-) create mode 100644 src/Controls/src/Core/Platform/iOS/CustomPressGestureRecognizer.cs diff --git a/src/Controls/samples/Controls.Sample/MauiProgram.cs b/src/Controls/samples/Controls.Sample/MauiProgram.cs index e9f5f12c0f43..c12de1f3a0ef 100644 --- a/src/Controls/samples/Controls.Sample/MauiProgram.cs +++ b/src/Controls/samples/Controls.Sample/MauiProgram.cs @@ -137,7 +137,7 @@ public static MauiApp CreateMauiApp() { PageType.Template => typeof(TemplatePage), PageType.Shell => typeof(AppShell), - PageType.Main => typeof(CustomNavigationPage), + PageType.Main => typeof(PointerGestureGalleryPage), PageType.FlyoutPage => typeof(CustomFlyoutPage), PageType.TabbedPage => typeof(Pages.TabbedPageGallery), PageType.Blazor => diff --git a/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs b/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs index 411c9bda451d..fc0951ad338a 100644 --- a/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs +++ b/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs @@ -221,7 +221,7 @@ public void Dispose() } - protected virtual UIGestureRecognizer? GetPlatformRecognizer(IGestureRecognizer recognizer) + protected virtual List? GetPlatformRecognizer(IGestureRecognizer recognizer) { if (recognizer == null) return null; @@ -229,45 +229,71 @@ public void Dispose() var weakRecognizer = new WeakReference(recognizer); var weakEventTracker = new WeakReference(this); - var tapGestureRecognizer = CreateTapRecognizer(weakEventTracker, weakRecognizer); if (tapGestureRecognizer != null) { - return tapGestureRecognizer; + return new List { tapGestureRecognizer }; } var pointerGestureRecognizer = recognizer as PointerGestureRecognizer; if (pointerGestureRecognizer != null && OperatingSystem.IsIOSVersionAtLeast(13)) { - var uiRecognizer = CreatePointerRecognizer(r => - { - if (weakRecognizer.Target is PointerGestureRecognizer pointerGestureRecognizer && - weakEventTracker.Target is GesturePlatformManager eventTracker && - eventTracker._handler?.VirtualView is View view && - eventTracker._handler?.MauiContext?.GetPlatformWindow() is UIWindow window) + var uiRecognizers = CreatePointerRecognizer( + hoverGesture => { - var originPoint = r.LocationInView(eventTracker?.PlatformView); - var platformPointerArgs = new PlatformPointerEventArgs(r.View, r); - - switch (r.State) + if (weakRecognizer.Target is PointerGestureRecognizer pointerGestureRecognizer && + weakEventTracker.Target is GesturePlatformManager eventTracker && + eventTracker._handler?.VirtualView is View view && + eventTracker._handler?.MauiContext?.GetPlatformWindow() is UIWindow window) { - case UIGestureRecognizerState.Began: - pointerGestureRecognizer.SendPointerEntered(view, (relativeTo) => CalculatePosition(relativeTo, originPoint, weakRecognizer, weakEventTracker), platformPointerArgs); - break; - case UIGestureRecognizerState.Changed: - pointerGestureRecognizer.SendPointerMoved(view, (relativeTo) => CalculatePosition(relativeTo, originPoint, weakRecognizer, weakEventTracker), platformPointerArgs); - break; - case UIGestureRecognizerState.Cancelled: - case UIGestureRecognizerState.Failed: - case UIGestureRecognizerState.Ended: - pointerGestureRecognizer.SendPointerExited(view, (relativeTo) => CalculatePosition(relativeTo, originPoint, weakRecognizer, weakEventTracker), platformPointerArgs); - break; + var originPoint = hoverGesture.LocationInView(eventTracker?.PlatformView); + + switch (hoverGesture.State) + { + case UIGestureRecognizerState.Began: + pointerGestureRecognizer.SendPointerEntered(view, (relativeTo) => CalculatePosition(relativeTo, originPoint, weakRecognizer, weakEventTracker), platformPointerArgs); + break; + case UIGestureRecognizerState.Changed: + pointerGestureRecognizer.SendPointerMoved(view, (relativeTo) => CalculatePosition(relativeTo, originPoint, weakRecognizer, weakEventTracker), platformPointerArgs); + break; + case UIGestureRecognizerState.Cancelled: + case UIGestureRecognizerState.Failed: + case UIGestureRecognizerState.Ended: + pointerGestureRecognizer.SendPointerExited(view, (relativeTo) => CalculatePosition(relativeTo, originPoint, weakRecognizer, weakEventTracker), platformPointerArgs); + break; + } + } + }, + pressGesture => + { + if (weakRecognizer.Target is PointerGestureRecognizer pointerGestureRecognizer && + weakEventTracker.Target is GesturePlatformManager eventTracker && + eventTracker._handler?.VirtualView is View view && + eventTracker._handler?.MauiContext?.GetPlatformWindow() is UIWindow window) + { + var originPoint = pressGesture.LocationInView(eventTracker?.PlatformView); + + switch (pressGesture.State) + { + case UIGestureRecognizerState.Began: + pointerGestureRecognizer.SendPointerPressed(view, (relativeTo) => CalculatePosition(relativeTo, originPoint, weakRecognizer, weakEventTracker), platformPointerArgs); + break; + case UIGestureRecognizerState.Changed: + pointerGestureRecognizer.SendPointerMoved(view, (relativeTo) => CalculatePosition(relativeTo, originPoint, weakRecognizer, weakEventTracker), platformPointerArgs); + break; + case UIGestureRecognizerState.Cancelled: + case UIGestureRecognizerState.Failed: + case UIGestureRecognizerState.Ended: + pointerGestureRecognizer.SendPointerReleased(view, (relativeTo) => CalculatePosition(relativeTo, originPoint, weakRecognizer, weakEventTracker), platformPointerArgs); + pointerGestureRecognizer.SendPointerEntered(view, (relativeTo) => CalculatePosition(relativeTo, originPoint, weakRecognizer, weakEventTracker), platformPointerArgs); + break; + } } } - }); - return uiRecognizer; + ); + return uiRecognizers; } var swipeRecognizer = recognizer as SwipeGestureRecognizer; @@ -283,7 +309,7 @@ public void Dispose() swipeGestureRecognizer.SendSwiped(view, direction); }); var uiRecognizer = CreateSwipeRecognizer(swipeRecognizer.Direction, returnAction, 1); - return uiRecognizer; + return new List { uiRecognizer }; } var pinchRecognizer = recognizer as IPinchGestureController; @@ -343,7 +369,7 @@ public void Dispose() } } }); - return uiRecognizer; + return new List { uiRecognizer }; } var panRecognizer = recognizer as PanGestureRecognizer; @@ -390,7 +416,7 @@ public void Dispose() } } }); - return uiRecognizer; + return new List { uiRecognizer }; } return null; @@ -424,10 +450,14 @@ UISwipeGestureRecognizer CreateSwipeRecognizer(SwipeDirection direction, Action< [SupportedOSPlatform("ios13.0")] [SupportedOSPlatform("maccatalyst13.0")] - CustomHoverGestureRecognizer CreatePointerRecognizer(Action action) + List? CreatePointerRecognizer(Action hoverAction, Action pressAction) { - var result = new CustomHoverGestureRecognizer(action); - return result; + var results = new List() + { + new CustomHoverGestureRecognizer(hoverAction), + new CustomPressGestureRecognizer(pressAction) + }; + return results; } UITapGestureRecognizer? CreateTapRecognizer( @@ -547,6 +577,13 @@ void LoadRecognizers() } } + var longPressGestureRecognizer = new CustomLongPressGestureRecognizer(() => + { + }); + longPressGestureRecognizer.ShouldRecognizeSimultaneously = (g, o) => true; + + PlatformView?.AddGestureRecognizer(longPressGestureRecognizer); + bool dragFound = false; bool dropFound = false; diff --git a/src/Controls/src/Core/Platform/iOS/CustomHoverGestureRecognizer.cs b/src/Controls/src/Core/Platform/iOS/CustomHoverGestureRecognizer.cs index 3704025548dc..563616ba0616 100644 --- a/src/Controls/src/Core/Platform/iOS/CustomHoverGestureRecognizer.cs +++ b/src/Controls/src/Core/Platform/iOS/CustomHoverGestureRecognizer.cs @@ -12,32 +12,29 @@ namespace Microsoft.Maui.Controls.Platform.iOS; [SupportedOSPlatform("maccatalyst13.0")] internal class CustomHoverGestureRecognizer : UIHoverGestureRecognizer { - NSObject _target; - - public CustomHoverGestureRecognizer(NSObject target, Selector action) : base(target, action) + public CustomHoverGestureRecognizer(Action action) : base(action) { - _target = target; + ShouldRecognizeSimultaneously = (_, __) => + { + return true; + }; } - internal CustomHoverGestureRecognizer(Action action) - : this(new Callback(action), Selector.FromHandle(Selector.GetHandle("target:"))!) { } - - [Register("__UIHoverGestureRecognizer")] - class Callback : Token + public override void TouchesBegan(NSSet touches, UIEvent evt) { - Action action; + State = UIGestureRecognizerState.Began; + base.TouchesBegan(touches, evt); + } - internal Callback(Action action) - { - this.action = action; - } + public override void TouchesEnded(NSSet touches, UIEvent evt) + { + State = UIGestureRecognizerState.Ended; + base.TouchesEnded(touches, evt); + } - [Export("target:")] - [Preserve(Conditional = true)] - public void Activated(UIHoverGestureRecognizer sender) - { - if (OperatingSystem.IsIOSVersionAtLeast(13)) - action(sender); - } + public override void TouchesMoved(NSSet touches, UIEvent evt) + { + State = UIGestureRecognizerState.Changed; + base.TouchesMoved(touches, evt); } } diff --git a/src/Controls/src/Core/Platform/iOS/CustomPressGestureRecognizer.cs b/src/Controls/src/Core/Platform/iOS/CustomPressGestureRecognizer.cs new file mode 100644 index 000000000000..1e91870ed8d5 --- /dev/null +++ b/src/Controls/src/Core/Platform/iOS/CustomPressGestureRecognizer.cs @@ -0,0 +1,86 @@ +#nullable disable +using System; +using System.Runtime.InteropServices; +using System.Runtime.Versioning; +using Foundation; +using ObjCRuntime; +using UIKit; +using PreserveAttribute = Microsoft.Maui.Controls.Internals.PreserveAttribute; + +namespace Microsoft.Maui.Controls.Platform.iOS; + +internal class CustomPressGestureRecognizer : UIGestureRecognizer +{ + NSObject _target; + + public CustomPressGestureRecognizer(NSObject target, Selector action) : base(target, action) + { + _target = target; + } + + public CustomPressGestureRecognizer(Action action) + : this(new Callback(action), Selector.FromHandle(Selector.GetHandle("target:"))!) { } + + [Register("__UIGestureRecognizer")] + class Callback : Token + { + Action action; + + internal Callback(Action action) + { + this.action = action; + } + + [Export("target:")] + [Preserve(Conditional = true)] + public void Activated(UIGestureRecognizer sender) + { + if (OperatingSystem.IsIOSVersionAtLeast(13)) + action(sender); + } + } + + //public CustomPressGestureRecognizer(Action action) : base(action) + //{ + // ShouldRecognizeSimultaneously = (_, __) => + // { + // return true; + // }; + //} + + + //public CustomPressGestureRecognizer(Action action) : base(action) + //{ + // _action = action; + // _action.Invoke(); + + // ShouldRecognizeSimultaneously = (_, __) => + // { + // return true; + // }; + //} + + public override void TouchesBegan(NSSet touches, UIEvent evt) + { + System.Diagnostics.Debug.WriteLine("TouchesBegan"); + State = UIGestureRecognizerState.Began; + base.TouchesBegan(touches, evt); + + } + + public override void TouchesEnded(NSSet touches, UIEvent evt) + { + System.Diagnostics.Debug.WriteLine("TouchesEnded"); + State = UIGestureRecognizerState.Ended; + base.TouchesEnded(touches, evt); + + } + + public override void TouchesMoved(NSSet touches, UIEvent evt) + { + System.Diagnostics.Debug.WriteLine("TouchesMoved"); + State = UIGestureRecognizerState.Changed; + base.TouchesMoved(touches, evt); + + } +} From 3a86ec74a5319c7daafbfb980cdac09a6e0b5c13 Mon Sep 17 00:00:00 2001 From: Rachel Kang Date: Fri, 4 Aug 2023 14:56:36 -0400 Subject: [PATCH 03/12] Make it work --- .../GesturePlatformManager.iOS.cs | 69 +++++++++---------- .../iOS/CustomHoverGestureRecognizer.cs | 40 ----------- .../iOS/CustomPressGestureRecognizer.cs | 29 +------- 3 files changed, 36 insertions(+), 102 deletions(-) delete mode 100644 src/Controls/src/Core/Platform/iOS/CustomHoverGestureRecognizer.cs diff --git a/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs b/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs index fc0951ad338a..f196e092106a 100644 --- a/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs +++ b/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs @@ -450,14 +450,14 @@ UISwipeGestureRecognizer CreateSwipeRecognizer(SwipeDirection direction, Action< [SupportedOSPlatform("ios13.0")] [SupportedOSPlatform("maccatalyst13.0")] - List? CreatePointerRecognizer(Action hoverAction, Action pressAction) + List CreatePointerRecognizer(Action hoverAction, Action pressAction) { - var results = new List() + var result = new List() { - new CustomHoverGestureRecognizer(hoverAction), - new CustomPressGestureRecognizer(pressAction) + new UIHoverGestureRecognizer(hoverAction) { ShouldRecognizeSimultaneously = (g, o) => true }, + new CustomPressGestureRecognizer(pressAction) { ShouldRecognizeSimultaneously = (g, o) => true } }; - return results; + return result; } UITapGestureRecognizer? CreateTapRecognizer( @@ -577,13 +577,6 @@ void LoadRecognizers() } } - var longPressGestureRecognizer = new CustomLongPressGestureRecognizer(() => - { - }); - longPressGestureRecognizer.ShouldRecognizeSimultaneously = (g, o) => true; - - PlatformView?.AddGestureRecognizer(longPressGestureRecognizer); - bool dragFound = false; bool dropFound = false; @@ -630,38 +623,42 @@ void LoadRecognizers() continue; } - var nativeRecognizer = GetPlatformRecognizer(recognizer); + var nativeRecognizers = GetPlatformRecognizer(recognizer); - if (nativeRecognizer != null && PlatformView != null) + if (nativeRecognizers is null) + continue; + + foreach (UIGestureRecognizer? nativeRecognizer in nativeRecognizers) { - nativeRecognizer.ShouldReceiveTouch = _shouldReceiveTouch; - PlatformView.AddGestureRecognizer(nativeRecognizer); + if (nativeRecognizer != null && PlatformView != null) + { + nativeRecognizer.ShouldReceiveTouch = _shouldReceiveTouch; + PlatformView.AddGestureRecognizer(nativeRecognizer); - _gestureRecognizers[recognizer] = nativeRecognizer; - } + _gestureRecognizers[recognizer] = nativeRecognizer; + } - if (OperatingSystem.IsIOSVersionAtLeast(11) && recognizer is DragGestureRecognizer) - { - dragFound = true; - _dragAndDropDelegate = _dragAndDropDelegate ?? new DragAndDropDelegate(_handler); - if (uIDragInteraction == null && PlatformView != null) + if (OperatingSystem.IsIOSVersionAtLeast(11) && recognizer is DragGestureRecognizer) { - var interaction = new UIDragInteraction(_dragAndDropDelegate); - interaction.Enabled = true; - _interactions.Add(interaction); - PlatformView.AddInteraction(interaction); + dragFound = true; + _dragAndDropDelegate = _dragAndDropDelegate ?? new DragAndDropDelegate(_handler); + if (uIDragInteraction == null && PlatformView != null) + { + var interaction = new UIDragInteraction(_dragAndDropDelegate); + interaction.Enabled = true; + PlatformView.AddInteraction(interaction); + } } - } - if (OperatingSystem.IsIOSVersionAtLeast(11) && recognizer is DropGestureRecognizer) - { - dropFound = true; - _dragAndDropDelegate = _dragAndDropDelegate ?? new DragAndDropDelegate(_handler); - if (uIDropInteraction == null && PlatformView != null) + if (OperatingSystem.IsIOSVersionAtLeast(11) && recognizer is DropGestureRecognizer) { - var interaction = new UIDropInteraction(_dragAndDropDelegate); - _interactions.Add(interaction); - PlatformView.AddInteraction(interaction); + dropFound = true; + _dragAndDropDelegate = _dragAndDropDelegate ?? new DragAndDropDelegate(_handler); + if (uIDropInteraction == null && PlatformView != null) + { + var interaction = new UIDropInteraction(_dragAndDropDelegate); + PlatformView.AddInteraction(interaction); + } } } } diff --git a/src/Controls/src/Core/Platform/iOS/CustomHoverGestureRecognizer.cs b/src/Controls/src/Core/Platform/iOS/CustomHoverGestureRecognizer.cs deleted file mode 100644 index 563616ba0616..000000000000 --- a/src/Controls/src/Core/Platform/iOS/CustomHoverGestureRecognizer.cs +++ /dev/null @@ -1,40 +0,0 @@ -#nullable disable -using System; -using System.Runtime.Versioning; -using Foundation; -using ObjCRuntime; -using UIKit; -using PreserveAttribute = Microsoft.Maui.Controls.Internals.PreserveAttribute; - -namespace Microsoft.Maui.Controls.Platform.iOS; - -[SupportedOSPlatform("ios13.0")] -[SupportedOSPlatform("maccatalyst13.0")] -internal class CustomHoverGestureRecognizer : UIHoverGestureRecognizer -{ - public CustomHoverGestureRecognizer(Action action) : base(action) - { - ShouldRecognizeSimultaneously = (_, __) => - { - return true; - }; - } - - public override void TouchesBegan(NSSet touches, UIEvent evt) - { - State = UIGestureRecognizerState.Began; - base.TouchesBegan(touches, evt); - } - - public override void TouchesEnded(NSSet touches, UIEvent evt) - { - State = UIGestureRecognizerState.Ended; - base.TouchesEnded(touches, evt); - } - - public override void TouchesMoved(NSSet touches, UIEvent evt) - { - State = UIGestureRecognizerState.Changed; - base.TouchesMoved(touches, evt); - } -} diff --git a/src/Controls/src/Core/Platform/iOS/CustomPressGestureRecognizer.cs b/src/Controls/src/Core/Platform/iOS/CustomPressGestureRecognizer.cs index 1e91870ed8d5..7c03f4c55897 100644 --- a/src/Controls/src/Core/Platform/iOS/CustomPressGestureRecognizer.cs +++ b/src/Controls/src/Core/Platform/iOS/CustomPressGestureRecognizer.cs @@ -40,47 +40,24 @@ public void Activated(UIGestureRecognizer sender) } } - //public CustomPressGestureRecognizer(Action action) : base(action) - //{ - // ShouldRecognizeSimultaneously = (_, __) => - // { - // return true; - // }; - //} - - - //public CustomPressGestureRecognizer(Action action) : base(action) - //{ - // _action = action; - // _action.Invoke(); - - // ShouldRecognizeSimultaneously = (_, __) => - // { - // return true; - // }; - //} - public override void TouchesBegan(NSSet touches, UIEvent evt) { - System.Diagnostics.Debug.WriteLine("TouchesBegan"); + //System.Diagnostics.Debug.WriteLine("TouchesBegan"); State = UIGestureRecognizerState.Began; base.TouchesBegan(touches, evt); - } public override void TouchesEnded(NSSet touches, UIEvent evt) { - System.Diagnostics.Debug.WriteLine("TouchesEnded"); + //System.Diagnostics.Debug.WriteLine("TouchesEnded"); State = UIGestureRecognizerState.Ended; base.TouchesEnded(touches, evt); - } public override void TouchesMoved(NSSet touches, UIEvent evt) { - System.Diagnostics.Debug.WriteLine("TouchesMoved"); + //System.Diagnostics.Debug.WriteLine("TouchesMoved"); State = UIGestureRecognizerState.Changed; base.TouchesMoved(touches, evt); - } } From eb2d7e114d20d80059a1902c240ff16c3009a5d6 Mon Sep 17 00:00:00 2001 From: Rachel Kang Date: Tue, 22 Aug 2023 12:23:36 -0400 Subject: [PATCH 04/12] Clean up --- src/Controls/samples/Controls.Sample/MauiProgram.cs | 2 +- .../GestureManager/GesturePlatformManager.Windows.cs | 2 +- .../src/Core/Platform/iOS/CustomPressGestureRecognizer.cs | 5 ----- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/Controls/samples/Controls.Sample/MauiProgram.cs b/src/Controls/samples/Controls.Sample/MauiProgram.cs index c12de1f3a0ef..e9f5f12c0f43 100644 --- a/src/Controls/samples/Controls.Sample/MauiProgram.cs +++ b/src/Controls/samples/Controls.Sample/MauiProgram.cs @@ -137,7 +137,7 @@ public static MauiApp CreateMauiApp() { PageType.Template => typeof(TemplatePage), PageType.Shell => typeof(AppShell), - PageType.Main => typeof(PointerGestureGalleryPage), + PageType.Main => typeof(CustomNavigationPage), PageType.FlyoutPage => typeof(CustomFlyoutPage), PageType.TabbedPage => typeof(Pages.TabbedPageGallery), PageType.Blazor => diff --git a/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.Windows.cs b/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.Windows.cs index b8da881ca119..f2f3013c0430 100644 --- a/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.Windows.cs +++ b/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.Windows.cs @@ -487,7 +487,7 @@ void OnPointerReleased(object sender, PointerRoutedEventArgs e) { uint id = e.Pointer.PointerId; if (_fingers.Contains(id)) - _fingers.Remove(id); + _fingers.Remove(id); SwipeComplete(true); PinchComplete(true); PanComplete(true); diff --git a/src/Controls/src/Core/Platform/iOS/CustomPressGestureRecognizer.cs b/src/Controls/src/Core/Platform/iOS/CustomPressGestureRecognizer.cs index 7c03f4c55897..0b5ec23f2a5d 100644 --- a/src/Controls/src/Core/Platform/iOS/CustomPressGestureRecognizer.cs +++ b/src/Controls/src/Core/Platform/iOS/CustomPressGestureRecognizer.cs @@ -1,7 +1,5 @@ #nullable disable using System; -using System.Runtime.InteropServices; -using System.Runtime.Versioning; using Foundation; using ObjCRuntime; using UIKit; @@ -42,21 +40,18 @@ public void Activated(UIGestureRecognizer sender) public override void TouchesBegan(NSSet touches, UIEvent evt) { - //System.Diagnostics.Debug.WriteLine("TouchesBegan"); State = UIGestureRecognizerState.Began; base.TouchesBegan(touches, evt); } public override void TouchesEnded(NSSet touches, UIEvent evt) { - //System.Diagnostics.Debug.WriteLine("TouchesEnded"); State = UIGestureRecognizerState.Ended; base.TouchesEnded(touches, evt); } public override void TouchesMoved(NSSet touches, UIEvent evt) { - //System.Diagnostics.Debug.WriteLine("TouchesMoved"); State = UIGestureRecognizerState.Changed; base.TouchesMoved(touches, evt); } From 4e9cbfec19448298048f0f77ddcaa8b155687f88 Mon Sep 17 00:00:00 2001 From: Rachel Kang Date: Wed, 6 Sep 2023 16:00:45 -0400 Subject: [PATCH 05/12] Resolve some conflicts --- .../src/Core/PointerGestureRecognizer.cs | 26 ------------------- 1 file changed, 26 deletions(-) diff --git a/src/Controls/src/Core/PointerGestureRecognizer.cs b/src/Controls/src/Core/PointerGestureRecognizer.cs index 63620e314621..c0003002b3dd 100644 --- a/src/Controls/src/Core/PointerGestureRecognizer.cs +++ b/src/Controls/src/Core/PointerGestureRecognizer.cs @@ -248,32 +248,6 @@ internal void SendPointerReleased(View sender, Func? getPosit handler?.Invoke(sender, new PointerEventArgs(getPosition, platformArgs)); } - /// - /// For internal use by the .NET MAUI platform. - /// - internal void SendPointerPressed(View sender, Func? getPosition) - { - ICommand cmd = PointerPressedCommand; - if (cmd?.CanExecute(PointerPressedCommandParameter) == true) - cmd.Execute(PointerPressedCommandParameter); - - EventHandler? handler = PointerPressed; - handler?.Invoke(sender, new PointerEventArgs(getPosition)); - } - - /// - /// For internal use by the .NET MAUI platform. - /// - internal void SendPointerReleased(View sender, Func? getPosition) - { - ICommand cmd = PointerReleasedCommand; - if (cmd?.CanExecute(PointerReleasedCommandParameter) == true) - cmd.Execute(PointerReleasedCommandParameter); - - EventHandler? handler = PointerReleased; - handler?.Invoke(sender, new PointerEventArgs(getPosition)); - } - internal static void SetupForPointerOverVSM( VisualElement element, Action updatePointerState, From dbd67dd9ab02407fca241c28e031b5e983d03771 Mon Sep 17 00:00:00 2001 From: Rachel Kang Date: Thu, 7 Sep 2023 16:24:28 -0400 Subject: [PATCH 06/12] Fix oversight during rebase --- .../Core/Platform/GestureManager/GesturePlatformManager.iOS.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs b/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs index f196e092106a..2a2de7b26fce 100644 --- a/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs +++ b/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs @@ -249,6 +249,7 @@ public void Dispose() eventTracker._handler?.MauiContext?.GetPlatformWindow() is UIWindow window) { var originPoint = hoverGesture.LocationInView(eventTracker?.PlatformView); + var platformPointerArgs = new PlatformPointerEventArgs(hoverGesture.View, hoverGesture); switch (hoverGesture.State) { @@ -274,6 +275,7 @@ public void Dispose() eventTracker._handler?.MauiContext?.GetPlatformWindow() is UIWindow window) { var originPoint = pressGesture.LocationInView(eventTracker?.PlatformView); + var platformPointerArgs = new PlatformPointerEventArgs(pressGesture.View, pressGesture); switch (pressGesture.State) { From ebb2015b71a3f76beee110a51dc74ba81c67a0b7 Mon Sep 17 00:00:00 2001 From: Rachel Kang Date: Wed, 20 Sep 2023 18:37:12 -0400 Subject: [PATCH 07/12] Add logic to change states if pointer is outside of view --- .../GesturePlatformManager.iOS.cs | 116 +++++++++--------- 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs b/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs index 2a2de7b26fce..23d759978d49 100644 --- a/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs +++ b/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs @@ -240,61 +240,7 @@ public void Dispose() if (pointerGestureRecognizer != null && OperatingSystem.IsIOSVersionAtLeast(13)) { - var uiRecognizers = CreatePointerRecognizer( - hoverGesture => - { - if (weakRecognizer.Target is PointerGestureRecognizer pointerGestureRecognizer && - weakEventTracker.Target is GesturePlatformManager eventTracker && - eventTracker._handler?.VirtualView is View view && - eventTracker._handler?.MauiContext?.GetPlatformWindow() is UIWindow window) - { - var originPoint = hoverGesture.LocationInView(eventTracker?.PlatformView); - var platformPointerArgs = new PlatformPointerEventArgs(hoverGesture.View, hoverGesture); - - switch (hoverGesture.State) - { - case UIGestureRecognizerState.Began: - pointerGestureRecognizer.SendPointerEntered(view, (relativeTo) => CalculatePosition(relativeTo, originPoint, weakRecognizer, weakEventTracker), platformPointerArgs); - break; - case UIGestureRecognizerState.Changed: - pointerGestureRecognizer.SendPointerMoved(view, (relativeTo) => CalculatePosition(relativeTo, originPoint, weakRecognizer, weakEventTracker), platformPointerArgs); - break; - case UIGestureRecognizerState.Cancelled: - case UIGestureRecognizerState.Failed: - case UIGestureRecognizerState.Ended: - pointerGestureRecognizer.SendPointerExited(view, (relativeTo) => CalculatePosition(relativeTo, originPoint, weakRecognizer, weakEventTracker), platformPointerArgs); - break; - } - } - }, - pressGesture => - { - if (weakRecognizer.Target is PointerGestureRecognizer pointerGestureRecognizer && - weakEventTracker.Target is GesturePlatformManager eventTracker && - eventTracker._handler?.VirtualView is View view && - eventTracker._handler?.MauiContext?.GetPlatformWindow() is UIWindow window) - { - var originPoint = pressGesture.LocationInView(eventTracker?.PlatformView); - var platformPointerArgs = new PlatformPointerEventArgs(pressGesture.View, pressGesture); - - switch (pressGesture.State) - { - case UIGestureRecognizerState.Began: - pointerGestureRecognizer.SendPointerPressed(view, (relativeTo) => CalculatePosition(relativeTo, originPoint, weakRecognizer, weakEventTracker), platformPointerArgs); - break; - case UIGestureRecognizerState.Changed: - pointerGestureRecognizer.SendPointerMoved(view, (relativeTo) => CalculatePosition(relativeTo, originPoint, weakRecognizer, weakEventTracker), platformPointerArgs); - break; - case UIGestureRecognizerState.Cancelled: - case UIGestureRecognizerState.Failed: - case UIGestureRecognizerState.Ended: - pointerGestureRecognizer.SendPointerReleased(view, (relativeTo) => CalculatePosition(relativeTo, originPoint, weakRecognizer, weakEventTracker), platformPointerArgs); - pointerGestureRecognizer.SendPointerEntered(view, (relativeTo) => CalculatePosition(relativeTo, originPoint, weakRecognizer, weakEventTracker), platformPointerArgs); - break; - } - } - } - ); + var uiRecognizers = CreatePointerRecognizer(weakRecognizer, weakEventTracker); return uiRecognizers; } @@ -452,12 +398,66 @@ UISwipeGestureRecognizer CreateSwipeRecognizer(SwipeDirection direction, Action< [SupportedOSPlatform("ios13.0")] [SupportedOSPlatform("maccatalyst13.0")] - List CreatePointerRecognizer(Action hoverAction, Action pressAction) + List CreatePointerRecognizer(WeakReference weakRecognizer, WeakReference weakEventTracker) { + bool exited = false; + + Action action = (pointerGesture) => + { + if (weakRecognizer.Target is PointerGestureRecognizer pointerGestureRecognizer && + weakEventTracker.Target is GesturePlatformManager eventTracker && + eventTracker._handler?.VirtualView is View view && + eventTracker._handler?.MauiContext?.GetPlatformWindow() is UIWindow window) + { + var originPoint = pointerGesture.LocationInView(eventTracker?.PlatformView); + var platformPointerArgs = new PlatformPointerEventArgs(pointerGesture.View, pointerGesture); + + switch (pointerGesture.State) + { + case UIGestureRecognizerState.Began: + if (pointerGesture is UIHoverGestureRecognizer) + pointerGestureRecognizer.SendPointerEntered(view, (relativeTo) => CalculatePosition(relativeTo, originPoint, weakRecognizer, weakEventTracker), platformPointerArgs); + else + pointerGestureRecognizer.SendPointerPressed(view, (relativeTo) => CalculatePosition(relativeTo, originPoint, weakRecognizer, weakEventTracker), platformPointerArgs); + break; + case UIGestureRecognizerState.Changed: + if (pointerGesture is UIHoverGestureRecognizer) + pointerGestureRecognizer.SendPointerMoved(view, (relativeTo) => CalculatePosition(relativeTo, originPoint, weakRecognizer, weakEventTracker), platformPointerArgs); + else + { + if (view.ToPlatform().Bounds.Contains(originPoint)) + pointerGestureRecognizer.SendPointerMoved(view, (relativeTo) => CalculatePosition(relativeTo, originPoint, weakRecognizer, weakEventTracker), platformPointerArgs); + else + { + pointerGestureRecognizer.SendPointerExited(view, (relativeTo) => CalculatePosition(relativeTo, originPoint, weakRecognizer, weakEventTracker), platformPointerArgs); + exited = true; + pointerGesture.State = UIGestureRecognizerState.Ended; + } + } + break; + case UIGestureRecognizerState.Cancelled: + case UIGestureRecognizerState.Failed: + case UIGestureRecognizerState.Ended: + if (pointerGesture is UIHoverGestureRecognizer && !exited) + pointerGestureRecognizer.SendPointerExited(view, (relativeTo) => CalculatePosition(relativeTo, originPoint, weakRecognizer, weakEventTracker), platformPointerArgs); + else if (pointerGesture is CustomPressGestureRecognizer && exited) + { + pointerGestureRecognizer.SendPointerReleased(view, (relativeTo) => CalculatePosition(relativeTo, originPoint, weakRecognizer, weakEventTracker), platformPointerArgs); + // PointerMoved still gets fired after this, one time. + // if (exited) break; on UIGestureRecognizerState.Changed does prevent this + // however, that prevents any gesture detection on re-entry. + // so I still need to figure out that part. but progress! + } + break; + } + } + }; + var result = new List() { - new UIHoverGestureRecognizer(hoverAction) { ShouldRecognizeSimultaneously = (g, o) => true }, - new CustomPressGestureRecognizer(pressAction) { ShouldRecognizeSimultaneously = (g, o) => true } + new UIHoverGestureRecognizer((gesture) => action.Invoke(gesture)) { ShouldRecognizeSimultaneously = (g, o) => true }, + new CustomPressGestureRecognizer((gesture) => action.Invoke(gesture)) { ShouldRecognizeSimultaneously = (g, o) => true } + }; return result; } From e0aa3baf89ff27919a797db184d42a14c08b245a Mon Sep 17 00:00:00 2001 From: Rachel Kang Date: Wed, 27 Sep 2023 13:34:26 -0400 Subject: [PATCH 08/12] Trigger exit only when exiting while pressed --- .../GesturePlatformManager.iOS.cs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs b/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs index 23d759978d49..e5514cbac8d4 100644 --- a/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs +++ b/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs @@ -415,12 +415,16 @@ UISwipeGestureRecognizer CreateSwipeRecognizer(SwipeDirection direction, Action< switch (pointerGesture.State) { case UIGestureRecognizerState.Began: + exited = false; if (pointerGesture is UIHoverGestureRecognizer) pointerGestureRecognizer.SendPointerEntered(view, (relativeTo) => CalculatePosition(relativeTo, originPoint, weakRecognizer, weakEventTracker), platformPointerArgs); else pointerGestureRecognizer.SendPointerPressed(view, (relativeTo) => CalculatePosition(relativeTo, originPoint, weakRecognizer, weakEventTracker), platformPointerArgs); break; case UIGestureRecognizerState.Changed: + if (exited) + break; + if (pointerGesture is UIHoverGestureRecognizer) pointerGestureRecognizer.SendPointerMoved(view, (relativeTo) => CalculatePosition(relativeTo, originPoint, weakRecognizer, weakEventTracker), platformPointerArgs); else @@ -432,22 +436,20 @@ UISwipeGestureRecognizer CreateSwipeRecognizer(SwipeDirection direction, Action< pointerGestureRecognizer.SendPointerExited(view, (relativeTo) => CalculatePosition(relativeTo, originPoint, weakRecognizer, weakEventTracker), platformPointerArgs); exited = true; pointerGesture.State = UIGestureRecognizerState.Ended; + break; } } break; case UIGestureRecognizerState.Cancelled: case UIGestureRecognizerState.Failed: case UIGestureRecognizerState.Ended: - if (pointerGesture is UIHoverGestureRecognizer && !exited) + if (exited) + break; + + if (pointerGesture is UIHoverGestureRecognizer) pointerGestureRecognizer.SendPointerExited(view, (relativeTo) => CalculatePosition(relativeTo, originPoint, weakRecognizer, weakEventTracker), platformPointerArgs); - else if (pointerGesture is CustomPressGestureRecognizer && exited) - { + else pointerGestureRecognizer.SendPointerReleased(view, (relativeTo) => CalculatePosition(relativeTo, originPoint, weakRecognizer, weakEventTracker), platformPointerArgs); - // PointerMoved still gets fired after this, one time. - // if (exited) break; on UIGestureRecognizerState.Changed does prevent this - // however, that prevents any gesture detection on re-entry. - // so I still need to figure out that part. but progress! - } break; } } From 5c4e9b8079a0b61777ef3e8e7f83b2092b8d7cdf Mon Sep 17 00:00:00 2001 From: Rachel Kang Date: Mon, 9 Oct 2023 15:20:52 -0400 Subject: [PATCH 09/12] Remove Windows changes - fix bad merge --- .../GestureManager/GesturePlatformManager.Windows.cs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.Windows.cs b/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.Windows.cs index f2f3013c0430..55a5a2b1642d 100644 --- a/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.Windows.cs +++ b/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.Windows.cs @@ -518,14 +518,6 @@ void OnPgrPointerReleased(object sender, PointerRoutedEventArgs e) => recognizer.SendPointerReleased(view, (relativeTo) => GetPosition(relativeTo, e), _control is null ? null : new PlatformPointerEventArgs(_control, e))); - void OnPgrPointerPressed(object sender, PointerRoutedEventArgs e) - => HandlePgrPointerEvent(e, (view, recognizer) - => recognizer.SendPointerPressed(view, (relativeTo) => GetPosition(relativeTo, e))); - - void OnPgrPointerReleased(object sender, PointerRoutedEventArgs e) - => HandlePgrPointerEvent(e, (view, recognizer) - => recognizer.SendPointerReleased(view, (relativeTo) => GetPosition(relativeTo, e))); - private void HandlePgrPointerEvent(PointerRoutedEventArgs e, Action SendPointerEvent) { var view = Element as View; From df37ce8fb13070fb4f5afe689955f754f33c80e8 Mon Sep 17 00:00:00 2001 From: Rachel Kang Date: Mon, 23 Oct 2023 12:08:10 -0400 Subject: [PATCH 10/12] Ensure drag/drop logic still gets hit --- .../GesturePlatformManager.iOS.cs | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs b/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs index e5514cbac8d4..b6bf80cc64b6 100644 --- a/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs +++ b/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs @@ -629,6 +629,29 @@ void LoadRecognizers() var nativeRecognizers = GetPlatformRecognizer(recognizer); + if (OperatingSystem.IsIOSVersionAtLeast(11) && recognizer is DragGestureRecognizer) + { + dragFound = true; + _dragAndDropDelegate = _dragAndDropDelegate ?? new DragAndDropDelegate(_handler); + if (uIDragInteraction == null && PlatformView != null) + { + var interaction = new UIDragInteraction(_dragAndDropDelegate); + interaction.Enabled = true; + PlatformView.AddInteraction(interaction); + } + } + + if (OperatingSystem.IsIOSVersionAtLeast(11) && recognizer is DropGestureRecognizer) + { + dropFound = true; + _dragAndDropDelegate = _dragAndDropDelegate ?? new DragAndDropDelegate(_handler); + if (uIDropInteraction == null && PlatformView != null) + { + var interaction = new UIDropInteraction(_dragAndDropDelegate); + PlatformView.AddInteraction(interaction); + } + } + if (nativeRecognizers is null) continue; @@ -641,29 +664,6 @@ void LoadRecognizers() _gestureRecognizers[recognizer] = nativeRecognizer; } - - if (OperatingSystem.IsIOSVersionAtLeast(11) && recognizer is DragGestureRecognizer) - { - dragFound = true; - _dragAndDropDelegate = _dragAndDropDelegate ?? new DragAndDropDelegate(_handler); - if (uIDragInteraction == null && PlatformView != null) - { - var interaction = new UIDragInteraction(_dragAndDropDelegate); - interaction.Enabled = true; - PlatformView.AddInteraction(interaction); - } - } - - if (OperatingSystem.IsIOSVersionAtLeast(11) && recognizer is DropGestureRecognizer) - { - dropFound = true; - _dragAndDropDelegate = _dragAndDropDelegate ?? new DragAndDropDelegate(_handler); - if (uIDropInteraction == null && PlatformView != null) - { - var interaction = new UIDropInteraction(_dragAndDropDelegate); - PlatformView.AddInteraction(interaction); - } - } } } From f1f2879580255cd3373999e03f334b1bd44060d7 Mon Sep 17 00:00:00 2001 From: Rachel Kang Date: Tue, 24 Oct 2023 09:45:12 -0400 Subject: [PATCH 11/12] Add back some logic that somehow got removed --- .../Platform/GestureManager/GesturePlatformManager.iOS.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs b/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs index b6bf80cc64b6..6c28897118aa 100644 --- a/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs +++ b/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs @@ -627,8 +627,6 @@ void LoadRecognizers() continue; } - var nativeRecognizers = GetPlatformRecognizer(recognizer); - if (OperatingSystem.IsIOSVersionAtLeast(11) && recognizer is DragGestureRecognizer) { dragFound = true; @@ -637,6 +635,7 @@ void LoadRecognizers() { var interaction = new UIDragInteraction(_dragAndDropDelegate); interaction.Enabled = true; + _interactions.Add(interaction); PlatformView.AddInteraction(interaction); } } @@ -648,10 +647,13 @@ void LoadRecognizers() if (uIDropInteraction == null && PlatformView != null) { var interaction = new UIDropInteraction(_dragAndDropDelegate); + _interactions.Add(interaction); PlatformView.AddInteraction(interaction); } } + var nativeRecognizers = GetPlatformRecognizer(recognizer); + if (nativeRecognizers is null) continue; From 73387d1a4fc57cb5c824fa475e6125ea9d22d679 Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Thu, 26 Oct 2023 15:54:25 -0500 Subject: [PATCH 12/12] - fix cleanup code --- .../GesturePlatformManager.iOS.cs | 47 ++++++++++++------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs b/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs index 6c28897118aa..180cce567809 100644 --- a/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs +++ b/src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs @@ -20,7 +20,7 @@ class GesturePlatformManager : IDisposable { readonly NotifyCollectionChangedEventHandler _collectionChangedHandler; - readonly Dictionary _gestureRecognizers = new Dictionary(); + readonly Dictionary> _gestureRecognizers = new Dictionary>(); readonly List _interactions = new List(); readonly IPlatformViewHandler _handler; @@ -88,10 +88,16 @@ public void Dispose() tapGestureRecognizer.PropertyChanged -= OnTapGestureRecognizerPropertyChanged; } - if (PlatformView != null) - PlatformView.RemoveGestureRecognizer(kvp.Value); - kvp.Value.ShouldReceiveTouch = null; - kvp.Value.Dispose(); + foreach(var uiGestureRecognizer in kvp.Value) + { + if (uiGestureRecognizer is null) + continue; + + if (PlatformView != null) + PlatformView.RemoveGestureRecognizer(uiGestureRecognizer); + uiGestureRecognizer.ShouldReceiveTouch = null; + uiGestureRecognizer.Dispose(); + } } if (PlatformView != null && OperatingSystem.IsIOSVersionAtLeast(11)) @@ -429,7 +435,8 @@ UISwipeGestureRecognizer CreateSwipeRecognizer(SwipeDirection direction, Action< pointerGestureRecognizer.SendPointerMoved(view, (relativeTo) => CalculatePosition(relativeTo, originPoint, weakRecognizer, weakEventTracker), platformPointerArgs); else { - if (view.ToPlatform().Bounds.Contains(originPoint)) + var bounds = eventTracker?.PlatformView?.Bounds; + if (bounds is not null && bounds.Value.Contains(originPoint)) pointerGestureRecognizer.SendPointerMoved(view, (relativeTo) => CalculatePosition(relativeTo, originPoint, weakRecognizer, weakEventTracker), platformPointerArgs); else { @@ -657,6 +664,7 @@ void LoadRecognizers() if (nativeRecognizers is null) continue; + _gestureRecognizers[recognizer] = nativeRecognizers; foreach (UIGestureRecognizer? nativeRecognizer in nativeRecognizers) { if (nativeRecognizer != null && PlatformView != null) @@ -664,7 +672,6 @@ void LoadRecognizers() nativeRecognizer.ShouldReceiveTouch = _shouldReceiveTouch; PlatformView.AddGestureRecognizer(nativeRecognizer); - _gestureRecognizers[recognizer] = nativeRecognizer; } } } @@ -689,19 +696,27 @@ void LoadRecognizers() for (int i = 0; i < toRemove.Count; i++) { IGestureRecognizer gestureRecognizer = toRemove[i]; - var uiRecognizer = _gestureRecognizers[gestureRecognizer]; + var uiRecognizers = _gestureRecognizers[gestureRecognizer]; _gestureRecognizers.Remove(gestureRecognizer); - if (PlatformView != null) - PlatformView.RemoveGestureRecognizer(uiRecognizer); - - if (TryGetTapGestureRecognizer(gestureRecognizer, out TapGestureRecognizer? tapGestureRecognizer) && - tapGestureRecognizer != null) + foreach (var uiRecognizer in uiRecognizers) { - gestureRecognizer.PropertyChanged -= OnTapGestureRecognizerPropertyChanged; - } + if (uiRecognizer is null) + continue; - uiRecognizer.Dispose(); + if (PlatformView != null) + { + PlatformView.RemoveGestureRecognizer(uiRecognizer); + } + + if (TryGetTapGestureRecognizer(gestureRecognizer, out TapGestureRecognizer? tapGestureRecognizer) && + tapGestureRecognizer != null) + { + gestureRecognizer.PropertyChanged -= OnTapGestureRecognizerPropertyChanged; + } + + uiRecognizer.Dispose(); + } } if (PlatformView != null && OperatingSystem.IsIOSVersionAtLeast(11))