diff --git a/src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellItemTransition.cs b/src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellItemTransition.cs index 090939cce980..44d650904b14 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellItemTransition.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellItemTransition.cs @@ -1,4 +1,5 @@ #nullable disable +using System; using System.Threading.Tasks; using ObjCRuntime; using UIKit; @@ -14,7 +15,15 @@ public Task Transition(IShellItemRenderer oldRenderer, IShellItemRenderer newRen var newView = newRenderer.ViewController.View; oldView.Layer.RemoveAllAnimations(); - newView.Alpha = 0; + + // On iOS 26+, setting newView.Alpha = 0 before the fade-in causes Liquid Glass + // tab bar icons to composite at zero opacity, resulting in missing tab icons. + // We skip the initial alpha=0 on iOS 26+, which means there is no fade-in + // animation on iOS 26+ — this is intentional to avoid the rendering issue. + if (!(OperatingSystem.IsIOSVersionAtLeast(26) || OperatingSystem.IsMacCatalystVersionAtLeast(26))) + { + newView.Alpha = 0; + } oldView.Superview.InsertSubviewAbove(newView, oldView); diff --git a/src/Controls/tests/TestCases.Android.Tests/snapshots/android/TabBarShouldBeVisibleAfterNavigatingFromModalViaGoToAsync.png b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/TabBarShouldBeVisibleAfterNavigatingFromModalViaGoToAsync.png new file mode 100644 index 000000000000..df1d3f454eab Binary files /dev/null and b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/TabBarShouldBeVisibleAfterNavigatingFromModalViaGoToAsync.png differ diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue34143.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue34143.cs new file mode 100644 index 000000000000..a7e05fa1c117 --- /dev/null +++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue34143.cs @@ -0,0 +1,152 @@ +namespace Maui.Controls.Sample.Issues; + +[Issue(IssueTracker.Github, 34143, "Tab bar ghosting issue after navigating from modal via GoToAsync", PlatformAffected.iOS)] +public class Issue34143 : TestShell +{ + protected override void Init() + { + var homeShellContent = new ShellContent + { + Title = "Home", + Route = "Issue34143Home", + ContentTemplate = new DataTemplate(() => new Issue34143MainPage()) + }; + + var tab1 = new Tab + { + Title = "Tab 1", + Route = "Issue34143Tab1", + AutomationId = "Issue34143Tab1", + Icon = "coffee.png", + Items = + { + new ShellContent + { + Route = "Issue34143Tab1Content", + ContentTemplate = new DataTemplate(() => new Issue34143TabPage("Tab 1 Content")) + } + } + }; + + var tab2 = new Tab + { + Title = "Tab 2", + Route = "Issue34143Tab2", + AutomationId = "Issue34143Tab2", + Icon = "coffee.png", + Items = + { + new ShellContent + { + Route = "Issue34143Tab2Content", + ContentTemplate = new DataTemplate(() => new Issue34143TabPage("Tab 2 Content")) + } + } + }; + + var tab3 = new Tab + { + Title = "Tab 3", + Route = "Issue34143Tab3", + AutomationId = "Issue34143Tab3", + Icon = "coffee.png", + Items = + { + new ShellContent + { + Route = "Issue34143Tab3Content", + ContentTemplate = new DataTemplate(() => new Issue34143TabPage("Tab 3 Content")) + } + } + }; + + var tabBar = new TabBar + { + Items = { tab1, tab2, tab3 } + }; + + Items.Add(homeShellContent); + Items.Add(tabBar); + } + + public class Issue34143MainPage : ContentPage + { + public Issue34143MainPage() + { + BackgroundColor = Colors.White; + Content = new VerticalStackLayout + { + VerticalOptions = LayoutOptions.Center, + HorizontalOptions = LayoutOptions.Center, + Children = + { + new Label + { + Text = "Home Page", + AutomationId = "Issue34143HomeLabel", + HorizontalOptions = LayoutOptions.Center + }, + new Button + { + Text = "Push Modal", + AutomationId = "Issue34143PushModal", + Command = new Command(async () => + await Shell.Current.Navigation.PushModalAsync(new Issue34143ModalPage())) + } + } + }; + } + } + + public class Issue34143ModalPage : ContentPage + { + public Issue34143ModalPage() + { + BackgroundColor = Colors.White; + Title = "Modal"; + Content = new VerticalStackLayout + { + VerticalOptions = LayoutOptions.Center, + HorizontalOptions = LayoutOptions.Center, + Children = + { + new Label + { + Text = "Modal Page", + AutomationId = "Issue34143ModalLabel", + HorizontalOptions = LayoutOptions.Center + }, + new Button + { + Text = "Go to Tab Bar", + AutomationId = "Issue34143GoToTabBar", + Command = new Command(async () => + await Shell.Current.GoToAsync("//Issue34143Tab1")) + } + } + }; + } + } + + public class Issue34143TabPage : ContentPage + { + public Issue34143TabPage(string contentText) + { + BackgroundColor = Colors.White; + Content = new VerticalStackLayout + { + VerticalOptions = LayoutOptions.Center, + HorizontalOptions = LayoutOptions.Center, + Children = + { + new Label + { + Text = contentText, + AutomationId = "Issue34143TabContent", + HorizontalOptions = LayoutOptions.Center + } + } + }; + } + } +} diff --git a/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/TabBarShouldBeVisibleAfterNavigatingFromModalViaGoToAsync.png b/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/TabBarShouldBeVisibleAfterNavigatingFromModalViaGoToAsync.png new file mode 100644 index 000000000000..4a38fa9890ef Binary files /dev/null and b/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/TabBarShouldBeVisibleAfterNavigatingFromModalViaGoToAsync.png differ diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34143.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34143.cs new file mode 100644 index 000000000000..3bb3749f41ed --- /dev/null +++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34143.cs @@ -0,0 +1,34 @@ +using NUnit.Framework; +using UITest.Appium; +using UITest.Core; + +namespace Microsoft.Maui.TestCases.Tests.Issues; + +public class Issue34143 : _IssuesUITest +{ + public override string Issue => "Tab bar ghosting issue after navigating from modal via GoToAsync"; + + public Issue34143(TestDevice device) : base(device) { } + + [Test] + [Category(UITestCategories.Shell)] + public void TabBarShouldBeVisibleAfterNavigatingFromModalViaGoToAsync() + { + // Start on Home page + App.WaitForElement("Issue34143PushModal"); + + // Push a modal page + App.Tap("Issue34143PushModal"); + + // Verify modal is shown + App.WaitForElement("Issue34143GoToTabBar"); + + // Navigate from modal to the tab bar using GoToAsync + App.Tap("Issue34143GoToTabBar"); + + // Verify we landed on Tab 1 and the tab bar tabs are interactable (not ghosted) + App.WaitForElement("Issue34143TabContent"); + + VerifyScreenshot(); + } +} diff --git a/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios-26/TabBarShouldBeVisibleAfterNavigatingFromModalViaGoToAsync.png b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios-26/TabBarShouldBeVisibleAfterNavigatingFromModalViaGoToAsync.png new file mode 100644 index 000000000000..9e14c0ba716c Binary files /dev/null and b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios-26/TabBarShouldBeVisibleAfterNavigatingFromModalViaGoToAsync.png differ diff --git a/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/TabBarShouldBeVisibleAfterNavigatingFromModalViaGoToAsync.png b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/TabBarShouldBeVisibleAfterNavigatingFromModalViaGoToAsync.png new file mode 100644 index 000000000000..c23bb1d35ddb Binary files /dev/null and b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/TabBarShouldBeVisibleAfterNavigatingFromModalViaGoToAsync.png differ