From d88bb77d36cb6e077800ffee171ab0834aee5a41 Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Thu, 9 May 2024 10:01:41 -0700 Subject: [PATCH] Fix PopoverPresentationController for action sheet (#22312) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix PopoverPresentationController for action sheet * - fix * Fixed build error --------- Co-authored-by: Javier Suárez --- .../Issues/Issues16321.xaml | 2 + .../Issues/Issues16321.xaml.cs | 46 ++++++++++++++++--- .../Platform/AlertManager/AlertManager.iOS.cs | 26 ++++++----- .../tests/UITests/Tests/Issues/Issue16321.cs | 25 ++++------ 4 files changed, 64 insertions(+), 35 deletions(-) diff --git a/src/Controls/samples/Controls.Sample.UITests/Issues/Issues16321.xaml b/src/Controls/samples/Controls.Sample.UITests/Issues/Issues16321.xaml index 0a1fc6ae9c3e..ef5aa49882a5 100644 --- a/src/Controls/samples/Controls.Sample.UITests/Issues/Issues16321.xaml +++ b/src/Controls/samples/Controls.Sample.UITests/Issues/Issues16321.xaml @@ -6,6 +6,8 @@ + + \ No newline at end of file diff --git a/src/Controls/samples/Controls.Sample.UITests/Issues/Issues16321.xaml.cs b/src/Controls/samples/Controls.Sample.UITests/Issues/Issues16321.xaml.cs index ea75962617fe..012702f7e6c0 100644 --- a/src/Controls/samples/Controls.Sample.UITests/Issues/Issues16321.xaml.cs +++ b/src/Controls/samples/Controls.Sample.UITests/Issues/Issues16321.xaml.cs @@ -4,6 +4,8 @@ using Microsoft.Maui; using System.Linq; using System; +using System.Threading.Tasks; + #if IOS using UIKit; @@ -38,8 +40,18 @@ async void OpenAlertWithModals(System.Object sender, System.EventArgs e) await Navigation.PopModalAsync(); } + async void OpenActionSheetWithModals(System.Object sender, System.EventArgs e) + { + await Navigation.PushModalAsync(new ContentPage()); + await Navigation.PushModalAsync(new ContentPage()); + await this.DisplayActionSheet("hello", "message", "Cancel", "Option 1", "Option 2"); + await Navigation.PopModalAsync(); + await Navigation.PopModalAsync(); + } + #if IOS - async void OpenAlertWithNewUIWindow(System.Object sender, System.EventArgs e) + + async void OpenPrompt(System.Object sender, System.EventArgs e, Func promptAction) { var uIWindow = new UIWindow(); var keyWindow = (this.Window.Handler.PlatformView as UIWindow); @@ -59,7 +71,7 @@ async void OpenAlertWithNewUIWindow(System.Object sender, System.EventArgs e) popupVC.ModalTransitionStyle = UIModalTransitionStyle.CoverVertical; await uIWindow.RootViewController.PresentViewControllerAsync(popupVC, false); - await page.DisplayAlert("hello", "message", "Cancel"); + await promptAction.Invoke(page); var rvc = uIWindow.RootViewController; @@ -74,11 +86,33 @@ async void OpenAlertWithNewUIWindow(System.Object sender, System.EventArgs e) keyWindow.WindowLevel = UIWindowLevel.Normal; this.RemoveLogicalChild(page); } -#else - async void OpenAlertWithNewUIWindow(System.Object sender, System.EventArgs e) + + void OpenAlertWithNewUIWindow(System.Object sender, System.EventArgs e) + { + OpenPrompt(sender, e, (page) => { - await this.DisplayAlert("hello", "message", "Cancel"); - } + return page.DisplayAlert("hello", "message", "Cancel"); + }); + } + + + void OpenActionSheetWithNewUIWindow(System.Object sender, System.EventArgs e) + { + OpenPrompt(sender, e, (page) => + { + return page.DisplayActionSheet("hello", "message", "Cancel", "Option 1", "Option 2"); + }); + } +#else + async void OpenActionSheetWithNewUIWindow(System.Object sender, System.EventArgs e) + { + await this.DisplayActionSheet("hello", "message", "Cancel", "Option 1", "Option 2"); + } + + async void OpenAlertWithNewUIWindow(System.Object sender, System.EventArgs e) + { + await this.DisplayAlert("hello", "message", "Cancel"); + } #endif } } \ No newline at end of file diff --git a/src/Controls/src/Core/Platform/AlertManager/AlertManager.iOS.cs b/src/Controls/src/Core/Platform/AlertManager/AlertManager.iOS.cs index 2729181c83c0..e4323b096bbf 100644 --- a/src/Controls/src/Core/Platform/AlertManager/AlertManager.iOS.cs +++ b/src/Controls/src/Core/Platform/AlertManager/AlertManager.iOS.cs @@ -177,11 +177,22 @@ void PresentActionSheet(Page sender, ActionSheetArguments arguments) static void PresentPopUp(Page sender, Window virtualView, UIWindow platformView, UIAlertController alert, ActionSheetArguments arguments = null) { + UIWindow presentingWindow = platformView; + + if (sender.Handler is IPlatformViewHandler pvh && + pvh.PlatformView?.Window is UIWindow senderPageWindow && + senderPageWindow != platformView && + senderPageWindow.RootViewController is not null) + { + presentingWindow = senderPageWindow; + } + if (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Pad && arguments != null) { + var topViewController = GetTopUIViewController(presentingWindow); UIDevice.CurrentDevice.BeginGeneratingDeviceOrientationNotifications(); var observer = NSNotificationCenter.DefaultCenter.AddObserver(UIDevice.OrientationDidChangeNotification, - n => { alert.PopoverPresentationController.SourceRect = platformView.RootViewController.View.Bounds; }); + n => { alert.PopoverPresentationController.SourceRect = topViewController.View.Bounds; }); arguments.Result.Task.ContinueWith(t => { @@ -189,20 +200,11 @@ static void PresentPopUp(Page sender, Window virtualView, UIWindow platformView, UIDevice.CurrentDevice.EndGeneratingDeviceOrientationNotifications(); }, TaskScheduler.FromCurrentSynchronizationContext()); - alert.PopoverPresentationController.SourceView = platformView.RootViewController.View; - alert.PopoverPresentationController.SourceRect = platformView.RootViewController.View.Bounds; + alert.PopoverPresentationController.SourceView = topViewController.View; + alert.PopoverPresentationController.SourceRect = topViewController.View.Bounds; alert.PopoverPresentationController.PermittedArrowDirections = 0; // No arrow } - UIWindow presentingWindow = platformView; - if (sender.Handler is IPlatformViewHandler pvh && - pvh.PlatformView?.Window is UIWindow senderPageWindow && - senderPageWindow != platformView && - senderPageWindow.RootViewController is not null) - { - presentingWindow = senderPageWindow; - } - presentingWindow.BeginInvokeOnMainThread(() => { GetTopUIViewController(presentingWindow) diff --git a/src/Controls/tests/UITests/Tests/Issues/Issue16321.cs b/src/Controls/tests/UITests/Tests/Issues/Issue16321.cs index 0c02e35076d4..2552915bd472 100644 --- a/src/Controls/tests/UITests/Tests/Issues/Issue16321.cs +++ b/src/Controls/tests/UITests/Tests/Issues/Issue16321.cs @@ -11,29 +11,20 @@ public class Issue16321 : _IssuesUITest public override string Issue => "Alerts Open on top of current presented view"; [Test] + [TestCase("OpenAlertWithModals")] + [TestCase("OpenAlertWithNewUIWindow")] + [TestCase("OpenActionSheetWithNewUIWindow")] + [TestCase("OpenActionSheetWithModals")] [Category(UITestCategories.DisplayAlert)] - public void OpenAlertWithModals() + public void OpenAlertWithModals(string testCase) { this.IgnoreIfPlatforms(new[] { TestDevice.Mac, TestDevice.Windows, TestDevice.Android }); - App.WaitForElement("OpenAlertWithModals").Click(); - App.WaitForElement("Cancel").Click(); - } - - [Test] - [Category(UITestCategories.DisplayAlert)] - public void OpenAlertWithNewUIWindow() - { - this.IgnoreIfPlatforms(new[] - { - TestDevice.Mac, TestDevice.Windows, TestDevice.Android - }); - - App.WaitForElement("OpenAlertWithNewUIWindow").Click(); - App.WaitForElement("Cancel").Click(); + App.WaitForElement(testCase).Tap(); + App.WaitForElement("Cancel").Tap(); } } -} +} \ No newline at end of file