From 6087a5f0a36e225686f9d221f76529114c73ea0e Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Thu, 29 Dec 2022 16:47:51 -0600 Subject: [PATCH 01/10] Fix initial page and back button Navigation events --- .../NavigationPage/iOS/NavigationRenderer.cs | 26 ++++++++++++++++++- .../NavigationPage/NavigationPage.Legacy.cs | 25 +++++++++++------- src/Controls/src/Core/NavigationPage.cs | 7 ----- .../Core.UnitTests/PageLifeCycleTests.cs | 16 +++++++----- .../TestClasses/TestNavigationPage.cs | 16 +++++++++--- .../NavigationPage/NavigationPageTests.cs | 14 ++++++++++ 6 files changed, 78 insertions(+), 26 deletions(-) diff --git a/src/Controls/src/Core/Compatibility/Handlers/NavigationPage/iOS/NavigationRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/NavigationPage/iOS/NavigationRenderer.cs index 73a51d9e34bf..46360b50261a 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/NavigationPage/iOS/NavigationRenderer.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/NavigationPage/iOS/NavigationRenderer.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Threading.Tasks; using CoreGraphics; +using Foundation; using Microsoft.Maui.Controls.Internals; using Microsoft.Maui.Controls.Platform; using Microsoft.Maui.Controls.PlatformConfiguration.iOSSpecific; @@ -43,7 +44,7 @@ public class NavigationRenderer : UINavigationController, IPlatformViewHandler bool _navigating = false; VisualElement _element; - [Preserve(Conditional = true)] + [Internals.Preserve(Conditional = true)] public NavigationRenderer() : base(typeof(MauiControlsNavigationBar), null) { _viewHandlerWrapper = new ViewHandlerDelegator(Mapper, CommandMapper, this); @@ -780,6 +781,7 @@ void UpdateToolBarVisible() TopViewController?.NavigationItem?.TitleView?.LayoutSubviews(); } + bool _uiRequestedPop; internal async Task UpdateFormsInnerNavigation(Page pageBeingRemoved) { if (NavPage == null) @@ -789,9 +791,24 @@ internal async Task UpdateFormsInnerNavigation(Page pageBeingRemoved) _ignorePopCall = true; if (Element.Navigation.NavigationStack.Contains(pageBeingRemoved)) + { await (NavPage as INavigationPageController)?.RemoveAsyncInner(pageBeingRemoved, false, true); + if (_uiRequestedPop) + { + NavPage?.SendNavigatedFromHandler(pageBeingRemoved); + } + } + _ignorePopCall = false; + _uiRequestedPop = false; + } + [Export("navigationBar:shouldPopItem:")] + [Internals.Preserve(Conditional = true)] + internal bool ShouldPopItem(UINavigationBar _, UINavigationItem __) + { + _uiRequestedPop = true; + return true; } internal static void SetFlyoutLeftBarButton(UIViewController containerController, FlyoutPage FlyoutPage) @@ -959,6 +976,7 @@ void SetupLines() class MauiNavigationDelegate : UINavigationControllerDelegate { + bool _finishedWithInitialNavigation; readonly WeakReference _navigation; public MauiNavigationDelegate(NavigationRenderer navigationRenderer) { @@ -974,6 +992,12 @@ public override void DidShowViewController(UINavigationController navigationCont { pvc.UpdateFrames(); } + + if (r.Element is NavigationPage np && !_finishedWithInitialNavigation) + { + _finishedWithInitialNavigation = true; + np.SendNavigatedFromHandler(null); + } } } diff --git a/src/Controls/src/Core/HandlerImpl/NavigationPage/NavigationPage.Legacy.cs b/src/Controls/src/Core/HandlerImpl/NavigationPage/NavigationPage.Legacy.cs index 94a9c59642e4..32f972718726 100644 --- a/src/Controls/src/Core/HandlerImpl/NavigationPage/NavigationPage.Legacy.cs +++ b/src/Controls/src/Core/HandlerImpl/NavigationPage/NavigationPage.Legacy.cs @@ -16,8 +16,7 @@ public partial class NavigationPage : INavigationPageController { internal async Task PopAsyncInner( bool animated, - bool fast, - bool requestedFromHandler) + bool fast) { if (NavigationPageController.StackDepth == 1) { @@ -27,7 +26,7 @@ internal async Task PopAsyncInner( var page = (Page)InternalChildren.Last(); var previousPage = CurrentPage; SendNavigating(); - var removedPage = await RemoveAsyncInner(page, animated, fast, requestedFromHandler); + var removedPage = await RemoveAsyncInner(page, animated, fast); SendNavigated(previousPage); return removedPage; } @@ -35,8 +34,7 @@ internal async Task PopAsyncInner( internal async Task RemoveAsyncInner( Page page, bool animated, - bool fast, - bool requestedFromHandler) + bool fast) { if (NavigationPageController.StackDepth == 1) { @@ -53,7 +51,7 @@ internal async Task RemoveAsyncInner( var removed = true; EventHandler requestPop = _popRequested; - if (requestPop != null && !requestedFromHandler) + if (requestPop != null) { requestPop(this, args); @@ -74,15 +72,14 @@ internal async Task RemoveAsyncInner( return page; } - Task INavigationPageController.PopAsyncInner(bool animated, bool fast) { - return PopAsyncInner(animated, fast, false); + return PopAsyncInner(animated, fast); } Task INavigationPageController.RemoveAsyncInner(Page page, bool animated, bool fast) { - return RemoveAsyncInner(page, animated, fast, false); + return RemoveAsyncInner(page, animated, fast); } EventHandler _popRequested; @@ -207,6 +204,16 @@ async Task PushAsyncInner(Page page, bool animated) Pushed?.Invoke(this, args); } +#if IOS + internal void SendNavigatedFromHandler(Page previousPage) + { + if (CurrentPage.HasNavigatedTo) + return; + + SendNavigated(previousPage); + } +#endif + void PushPage(Page page) { InternalChildren.Add(page); diff --git a/src/Controls/src/Core/NavigationPage.cs b/src/Controls/src/Core/NavigationPage.cs index 6cdc4eef9f5b..0330819a69c8 100644 --- a/src/Controls/src/Core/NavigationPage.cs +++ b/src/Controls/src/Core/NavigationPage.cs @@ -377,13 +377,6 @@ protected override bool OnBackButtonPressed() return base.OnBackButtonPressed(); } - internal void InitialNativeNavigationStackLoaded() - { - SendNavigated(null); - } - - - void SendNavigated(Page previousPage) { previousPage?.SendNavigatedFrom(new NavigatedFromEventArgs(CurrentPage)); diff --git a/src/Controls/tests/Core.UnitTests/PageLifeCycleTests.cs b/src/Controls/tests/Core.UnitTests/PageLifeCycleTests.cs index 2890c229dfe1..6e645bf42c94 100644 --- a/src/Controls/tests/Core.UnitTests/PageLifeCycleTests.cs +++ b/src/Controls/tests/Core.UnitTests/PageLifeCycleTests.cs @@ -6,14 +6,18 @@ namespace Microsoft.Maui.Controls.Core.UnitTests public class PageLifeCycleTests : BaseTestFixture { - [Theory] - [InlineData(false)] - [InlineData(true)] - public void NavigationPageInitialPage(bool useMaui) + [Fact] + // This test isn't valid for non handler based + // navigation because the initial navigated event + // fires from the legacy code instead of the + // new handler code + // We have device tests to also verify this works on + // each platform + public async Task NavigationPageInitialPage() { var lcPage = new LCPage(); - NavigationPage navigationPage = new TestNavigationPage(useMaui, lcPage); - navigationPage.InitialNativeNavigationStackLoaded(); + var navigationPage = new TestNavigationPage(true, lcPage); + await navigationPage.NavigatingTask; Assert.Null(lcPage.NavigatingFromArgs); Assert.Null(lcPage.NavigatedFromArgs); Assert.NotNull(lcPage.NavigatedToArgs); diff --git a/src/Controls/tests/Core.UnitTests/TestClasses/TestNavigationPage.cs b/src/Controls/tests/Core.UnitTests/TestClasses/TestNavigationPage.cs index e3816bbc9f15..ef7e626772ef 100644 --- a/src/Controls/tests/Core.UnitTests/TestClasses/TestNavigationPage.cs +++ b/src/Controls/tests/Core.UnitTests/TestClasses/TestNavigationPage.cs @@ -39,7 +39,7 @@ public async Task SendBackButtonPressedAsync() return result; } - + public Task NavigatingTask => Handler?.NavigatingTask ?? Task.CompletedTask; } public class TestNavigationHandler : ViewHandler @@ -54,8 +54,11 @@ public static PropertyMapper Naviga public NavigationRequest CurrentNavigationRequest { get; private set; } + TaskCompletionSource _navigationSource; + + public Task NavigatingTask => (_navigationSource?.Task ?? Task.CompletedTask); - public void CompleteCurrentNavigation() + public async void CompleteCurrentNavigation() { if (CurrentNavigationRequest == null) throw new InvalidOperationException("No Active Navigation in the works"); @@ -65,13 +68,20 @@ public void CompleteCurrentNavigation() if ((this as IElementHandler).VirtualView is IStackNavigation sn) sn.NavigationFinished(newStack); + + await Task.Delay(10); + var source = _navigationSource; + _navigationSource = null; + source.SetResult(); } async void RequestNavigation(NavigationRequest navigationRequest) { - if (CurrentNavigationRequest != null) + if (CurrentNavigationRequest != null || _navigationSource != null) throw new InvalidOperationException("Already Processing Navigation"); + + _navigationSource = new TaskCompletionSource(); CurrentNavigationRequest = navigationRequest; await Task.Delay(10); diff --git a/src/Controls/tests/DeviceTests/Elements/NavigationPage/NavigationPageTests.cs b/src/Controls/tests/DeviceTests/Elements/NavigationPage/NavigationPageTests.cs index dc75a54263ab..4b39d1d1266e 100644 --- a/src/Controls/tests/DeviceTests/Elements/NavigationPage/NavigationPageTests.cs +++ b/src/Controls/tests/DeviceTests/Elements/NavigationPage/NavigationPageTests.cs @@ -50,6 +50,20 @@ await CreateHandlerAndAddToWindow(new Window(navPage), async }); } + [Fact] + public async Task InitialPageFiresNavigatedEvent() + { + SetupBuilder(); + var page = new ContentPage(); + var navPage = new NavigationPage(page) { Title = "App Page" }; + + await CreateHandlerAndAddToWindow(new Window(navPage), async (handler) => + { + await OnNavigatedToAsync(page); + Assert.True(page.HasNavigatedTo); + }); + } + #if !IOS && !MACCATALYST [Fact(DisplayName = "Back Button Visibility Changes with push/pop")] public async Task BackButtonVisibilityChangesWithPushPop() From babda89b1c598718eed472de2e195c8398314922 Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Thu, 29 Dec 2022 17:48:47 -0600 Subject: [PATCH 02/10] - add tests for backbutton --- .../NavigationPage/NavigationPageTests.iOS.cs | 49 ++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/src/Controls/tests/DeviceTests/Elements/NavigationPage/NavigationPageTests.iOS.cs b/src/Controls/tests/DeviceTests/Elements/NavigationPage/NavigationPageTests.iOS.cs index 8166ba33f264..abd247e555c8 100644 --- a/src/Controls/tests/DeviceTests/Elements/NavigationPage/NavigationPageTests.iOS.cs +++ b/src/Controls/tests/DeviceTests/Elements/NavigationPage/NavigationPageTests.iOS.cs @@ -1,8 +1,55 @@ -using Xunit; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Maui.Controls; +using Microsoft.Maui.Platform; +using Microsoft.Maui.Controls.Platform; +using Microsoft.Maui.Controls.Handlers.Compatibility; +using Microsoft.Maui.DeviceTests.Stubs; +using Microsoft.Maui.Handlers; +using Microsoft.Maui.Hosting; +using UIKit; +using Xunit; namespace Microsoft.Maui.DeviceTests { public partial class NavigationPageTests : ControlsHandlerTestBase { + [Fact] + public async Task NavigatingBackViaBackButtonFiresNavigatedEvent() + { + SetupBuilder(); + var page = new ContentPage(); + + var navPage = new NavigationPage(page) { Title = "App Page" }; + + await navPage.PushAsync(new ContentPage()); + await CreateHandlerAndAddToWindow(new Window(navPage), async (handler) => + { + await OnNavigatedToAsync(navPage.CurrentPage); + var navController = navPage.Handler as UINavigationController; + + Assert.False(page.HasNavigatedTo); + TapBackButton(navController.NavigationBar); + await OnNavigatedToAsync(page); + Assert.True(page.HasNavigatedTo); + }); + } + + void TapBackButton(UINavigationBar uINavigationBar) + { + var item = uINavigationBar.FindDescendantView(result => + { + return result.Class.Name?.Contains("UIButtonBarButton", StringComparison.OrdinalIgnoreCase) == true; + }); + + _ = item ?? throw new Exception("Unable to locate back button view"); + + var recognizer = item.GestureRecognizers.OfType().First(); + recognizer.State = UIGestureRecognizerState.Ended; + } + } } From a06c1cf022310ab4ab0ebe3b9f0e2e57b510610b Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Fri, 30 Dec 2022 10:01:04 -0600 Subject: [PATCH 03/10] - add comments and consolidate --- .../NavigationPage/iOS/NavigationRenderer.cs | 5 +++-- .../NavigationPage/NavigationPage.Legacy.cs | 8 ++++++-- .../NavigationPage/NavigationPageTests.iOS.cs | 16 +--------------- 3 files changed, 10 insertions(+), 19 deletions(-) diff --git a/src/Controls/src/Core/Compatibility/Handlers/NavigationPage/iOS/NavigationRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/NavigationPage/iOS/NavigationRenderer.cs index 46360b50261a..970f7c1cbe40 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/NavigationPage/iOS/NavigationRenderer.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/NavigationPage/iOS/NavigationRenderer.cs @@ -43,6 +43,7 @@ public class NavigationRenderer : UINavigationController, IPlatformViewHandler ViewHandlerDelegator _viewHandlerWrapper; bool _navigating = false; VisualElement _element; + bool _uiRequestedPop; // User tapped the back button or swiped to navigate back [Internals.Preserve(Conditional = true)] public NavigationRenderer() : base(typeof(MauiControlsNavigationBar), null) @@ -781,8 +782,7 @@ void UpdateToolBarVisible() TopViewController?.NavigationItem?.TitleView?.LayoutSubviews(); } - bool _uiRequestedPop; - internal async Task UpdateFormsInnerNavigation(Page pageBeingRemoved) + async Task UpdateFormsInnerNavigation(Page pageBeingRemoved) { if (NavPage == null) return; @@ -978,6 +978,7 @@ class MauiNavigationDelegate : UINavigationControllerDelegate { bool _finishedWithInitialNavigation; readonly WeakReference _navigation; + public MauiNavigationDelegate(NavigationRenderer navigationRenderer) { _navigation = new WeakReference(navigationRenderer); diff --git a/src/Controls/src/Core/HandlerImpl/NavigationPage/NavigationPage.Legacy.cs b/src/Controls/src/Core/HandlerImpl/NavigationPage/NavigationPage.Legacy.cs index 32f972718726..8bdfe2f2dfdb 100644 --- a/src/Controls/src/Core/HandlerImpl/NavigationPage/NavigationPage.Legacy.cs +++ b/src/Controls/src/Core/HandlerImpl/NavigationPage/NavigationPage.Legacy.cs @@ -14,7 +14,7 @@ namespace Microsoft.Maui.Controls /// public partial class NavigationPage : INavigationPageController { - internal async Task PopAsyncInner( + async Task PopAsyncInner( bool animated, bool fast) { @@ -31,7 +31,7 @@ internal async Task PopAsyncInner( return removedPage; } - internal async Task RemoveAsyncInner( + async Task RemoveAsyncInner( Page page, bool animated, bool fast) @@ -205,6 +205,10 @@ async Task PushAsyncInner(Page page, bool animated) } #if IOS + // Because iOS currently doesn't use our `IStackNavigationView` structures + // there are scenarios where the legacy handler needs to alert the xplat + // code of when a navigation has occurred. + // For example, initial load and when the user taps the back button internal void SendNavigatedFromHandler(Page previousPage) { if (CurrentPage.HasNavigatedTo) diff --git a/src/Controls/tests/DeviceTests/Elements/NavigationPage/NavigationPageTests.iOS.cs b/src/Controls/tests/DeviceTests/Elements/NavigationPage/NavigationPageTests.iOS.cs index abd247e555c8..50323c68fdde 100644 --- a/src/Controls/tests/DeviceTests/Elements/NavigationPage/NavigationPageTests.iOS.cs +++ b/src/Controls/tests/DeviceTests/Elements/NavigationPage/NavigationPageTests.iOS.cs @@ -32,24 +32,10 @@ await CreateHandlerAndAddToWindow(new Window(navPage), async var navController = navPage.Handler as UINavigationController; Assert.False(page.HasNavigatedTo); - TapBackButton(navController.NavigationBar); + navController.NavigationBar.TapBackButton(); await OnNavigatedToAsync(page); Assert.True(page.HasNavigatedTo); }); } - - void TapBackButton(UINavigationBar uINavigationBar) - { - var item = uINavigationBar.FindDescendantView(result => - { - return result.Class.Name?.Contains("UIButtonBarButton", StringComparison.OrdinalIgnoreCase) == true; - }); - - _ = item ?? throw new Exception("Unable to locate back button view"); - - var recognizer = item.GestureRecognizers.OfType().First(); - recognizer.State = UIGestureRecognizerState.Ended; - } - } } From 87ca40da10a5cc21d8b1912df910ba0f04248efa Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Fri, 30 Dec 2022 10:02:06 -0600 Subject: [PATCH 04/10] Update VisualElement.cs --- src/Controls/src/Core/VisualElement.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Controls/src/Core/VisualElement.cs b/src/Controls/src/Core/VisualElement.cs index 2f74c861cdda..dd1a83dfee66 100644 --- a/src/Controls/src/Core/VisualElement.cs +++ b/src/Controls/src/Core/VisualElement.cs @@ -249,9 +249,6 @@ static void OnTransformChanged(BindableObject bindable, object oldValue, object void NotifyBackgroundChanges() { - if (Background is ImmutableBrush) - return; - if (Background != null) { Background.Parent = this; @@ -264,9 +261,6 @@ void NotifyBackgroundChanges() void StopNotifyingBackgroundChanges() { - if (Background is ImmutableBrush) - return; - if (Background != null) { Background.Parent = null; From 171c7189722a4f858e16d93e1d627e6ed32b9948 Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Fri, 30 Dec 2022 10:28:30 -0600 Subject: [PATCH 05/10] - validate pushed page fires navigated --- .../NavigationPage/NavigationPageTests.cs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/Controls/tests/DeviceTests/Elements/NavigationPage/NavigationPageTests.cs b/src/Controls/tests/DeviceTests/Elements/NavigationPage/NavigationPageTests.cs index 4b39d1d1266e..961889bb524d 100644 --- a/src/Controls/tests/DeviceTests/Elements/NavigationPage/NavigationPageTests.cs +++ b/src/Controls/tests/DeviceTests/Elements/NavigationPage/NavigationPageTests.cs @@ -64,6 +64,29 @@ await CreateHandlerAndAddToWindow(new Window(navPage), async }); } + [Fact] + public async Task PushedPageFiresNavigatedEventOnInitialLoad() + { + SetupBuilder(); + + bool pageFiredNavigated = false; + var page = new ContentPage(); + page.NavigatedTo += (_, _) => pageFiredNavigated = true; + + var page2 = new ContentPage(); + + var navPage = new NavigationPage(page) { Title = "App Page" }; + await navPage.PushAsync(page2); + + await CreateHandlerAndAddToWindow(new Window(navPage), async (handler) => + { + await OnNavigatedToAsync(page2); + Assert.True(page2.HasNavigatedTo); + }); + + Assert.False(pageFiredNavigated); + } + #if !IOS && !MACCATALYST [Fact(DisplayName = "Back Button Visibility Changes with push/pop")] public async Task BackButtonVisibilityChangesWithPushPop() From 02b4ed87900b3f95fc56529556d8ace05b7f1c76 Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Tue, 3 Jan 2023 16:32:47 -0600 Subject: [PATCH 06/10] - fix tests --- .../tests/Core.UnitTests/TestClasses/TestNavigationPage.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Controls/tests/Core.UnitTests/TestClasses/TestNavigationPage.cs b/src/Controls/tests/Core.UnitTests/TestClasses/TestNavigationPage.cs index ef7e626772ef..2071afd087e1 100644 --- a/src/Controls/tests/Core.UnitTests/TestClasses/TestNavigationPage.cs +++ b/src/Controls/tests/Core.UnitTests/TestClasses/TestNavigationPage.cs @@ -69,9 +69,10 @@ public async void CompleteCurrentNavigation() if ((this as IElementHandler).VirtualView is IStackNavigation sn) sn.NavigationFinished(newStack); - await Task.Delay(10); var source = _navigationSource; _navigationSource = null; + + await Task.Delay(1); source.SetResult(); } From cd47f5c43ab8a4b11256f2bb6fb3c50b96f0e29b Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Tue, 3 Jan 2023 16:36:03 -0600 Subject: [PATCH 07/10] - fix tests for reals --- .../tests/Core.UnitTests/TestClasses/TestNavigationPage.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Controls/tests/Core.UnitTests/TestClasses/TestNavigationPage.cs b/src/Controls/tests/Core.UnitTests/TestClasses/TestNavigationPage.cs index 2071afd087e1..bec58167e33c 100644 --- a/src/Controls/tests/Core.UnitTests/TestClasses/TestNavigationPage.cs +++ b/src/Controls/tests/Core.UnitTests/TestClasses/TestNavigationPage.cs @@ -66,11 +66,12 @@ public async void CompleteCurrentNavigation() var newStack = CurrentNavigationRequest.NavigationStack.ToList(); CurrentNavigationRequest = null; + var source = _navigationSource; + _navigationSource = null; + if ((this as IElementHandler).VirtualView is IStackNavigation sn) sn.NavigationFinished(newStack); - var source = _navigationSource; - _navigationSource = null; await Task.Delay(1); source.SetResult(); From a9330a9085c5ce197d6405b146c823a121fd3c2f Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Wed, 18 Jan 2023 21:38:52 -0600 Subject: [PATCH 08/10] - fix exception messages --- .../DeviceTests/AssertionExtensions.iOS.cs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/TestUtils/src/DeviceTests/AssertionExtensions.iOS.cs b/src/TestUtils/src/DeviceTests/AssertionExtensions.iOS.cs index 1d9a3e005702..ea92d50d8e9a 100644 --- a/src/TestUtils/src/DeviceTests/AssertionExtensions.iOS.cs +++ b/src/TestUtils/src/DeviceTests/AssertionExtensions.iOS.cs @@ -548,14 +548,20 @@ public static UIView GetAccessiblePlatformView(this UIView platformView) return platformView; } - public static void TapBackButton(this UINavigationBar uINavigationBar) + + static UIView GetBackButton(this UINavigationBar uINavigationBar) { var item = uINavigationBar.FindDescendantView(result => { return result.Class.Name?.Contains("UIButtonBarButton", StringComparison.OrdinalIgnoreCase) == true; }); - _ = item ?? throw new Exception("Unable to locate back button view"); + return item ?? throw new Exception("Unable to locate back button view"); + } + + public static void TapBackButton(this UINavigationBar uINavigationBar) + { + var item = uINavigationBar.GetBackButton(); var recognizer = item!.GestureRecognizers!.OfType().FirstOrDefault(); _ = recognizer ?? throw new Exception("Unable to Back Button TapGestureRecognizer"); @@ -580,16 +586,11 @@ public static void TapBackButton(this UINavigationBar uINavigationBar) public static string? GetBackButtonText(this UINavigationBar uINavigationBar) { - var item = uINavigationBar.FindDescendantView(result => - { - return result.Class.Name?.Contains("UIButtonBarButton", StringComparison.OrdinalIgnoreCase) == true; - }); - - _ = item ?? throw new Exception("Unable to locate TitleBar Control"); + var item = uINavigationBar.GetBackButton(); var titleLabel = item.FindDescendantView(); - _ = item ?? throw new Exception("Unable to locate UILabel Inside UINavigationBar"); + _ = item ?? throw new Exception("Unable to locate BackButton UILabel Inside UINavigationBar"); return titleLabel?.Text; } } From b9e1f811acdeff2606eb8b6423e25e21c791f815 Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Wed, 18 Jan 2023 23:46:24 -0600 Subject: [PATCH 09/10] Revert "Update VisualElement.cs" This reverts commit 87ca40da10a5cc21d8b1912df910ba0f04248efa. --- src/Controls/src/Core/VisualElement.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Controls/src/Core/VisualElement.cs b/src/Controls/src/Core/VisualElement.cs index dd1a83dfee66..2f74c861cdda 100644 --- a/src/Controls/src/Core/VisualElement.cs +++ b/src/Controls/src/Core/VisualElement.cs @@ -249,6 +249,9 @@ static void OnTransformChanged(BindableObject bindable, object oldValue, object void NotifyBackgroundChanges() { + if (Background is ImmutableBrush) + return; + if (Background != null) { Background.Parent = this; @@ -261,6 +264,9 @@ void NotifyBackgroundChanges() void StopNotifyingBackgroundChanges() { + if (Background is ImmutableBrush) + return; + if (Background != null) { Background.Parent = null; From cdcdab13959cefd6f01b984271ea2abdbc682067 Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Tue, 24 Jan 2023 11:14:28 -0600 Subject: [PATCH 10/10] - add fix for iOS14 --- src/TestUtils/src/DeviceTests/AssertionExtensions.iOS.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/TestUtils/src/DeviceTests/AssertionExtensions.iOS.cs b/src/TestUtils/src/DeviceTests/AssertionExtensions.iOS.cs index ea92d50d8e9a..d0454c953ac0 100644 --- a/src/TestUtils/src/DeviceTests/AssertionExtensions.iOS.cs +++ b/src/TestUtils/src/DeviceTests/AssertionExtensions.iOS.cs @@ -576,6 +576,12 @@ public static void TapBackButton(this UINavigationBar uINavigationBar) return result.Class.Name?.Contains("UINavigationBarTitleControl", StringComparison.OrdinalIgnoreCase) == true; }); + //Pre iOS 15 + item = item ?? uINavigationBar.FindDescendantView(result => + { + return result.Class.Name?.Contains("UINavigationBarContentView", StringComparison.OrdinalIgnoreCase) == true; + }); + _ = item ?? throw new Exception("Unable to locate TitleBar Control"); var titleLabel = item.FindDescendantView();