From 4f9838df9623e7632cd7a3db0c8dd7aa93a58500 Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Tue, 27 Aug 2024 15:26:11 -0500 Subject: [PATCH 1/2] Remove code from iOS that short circuits propagation --- .../Handlers/iOS/FrameRenderer.cs | 2 +- .../TestCases.HostApp/Issues/Issue24434.cs | 39 +++++++++++++++++++ .../Tests/Issues/Issue24434.cs | 24 ++++++++++++ src/Core/src/Platform/iOS/LayoutView.cs | 4 +- src/Core/src/Platform/iOS/MauiView.cs | 2 +- src/Core/src/Platform/iOS/ViewExtensions.cs | 10 +---- src/Core/src/Platform/iOS/WrapperView.cs | 2 +- 7 files changed, 69 insertions(+), 14 deletions(-) create mode 100644 src/Controls/tests/TestCases.HostApp/Issues/Issue24434.cs create mode 100644 src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue24434.cs diff --git a/src/Controls/src/Core/Compatibility/Handlers/iOS/FrameRenderer.cs b/src/Controls/src/Core/Compatibility/Handlers/iOS/FrameRenderer.cs index 21ccbac8c69c..4cbe69a47ac1 100644 --- a/src/Controls/src/Core/Compatibility/Handlers/iOS/FrameRenderer.cs +++ b/src/Controls/src/Core/Compatibility/Handlers/iOS/FrameRenderer.cs @@ -207,7 +207,7 @@ protected override void Dispose(bool disposing) public override void SetNeedsLayout() { base.SetNeedsLayout(); - this.GetSuperViewIfWindowSet()?.SetNeedsLayout(); + this.Superview?.SetNeedsLayout(); } [Microsoft.Maui.Controls.Internals.Preserve(Conditional = true)] diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue24434.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue24434.cs new file mode 100644 index 000000000000..f27554aafd86 --- /dev/null +++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue24434.cs @@ -0,0 +1,39 @@ +using Microsoft.Maui.Controls.Internals; + +namespace Maui.Controls.Sample.Issues +{ + [Issue(IssueTracker.Github, 24434, "Modifying a layout while view isn't part of the Window fails to update the layout visually", + PlatformAffected.iOS)] + public class Issue24434 : ContentPage + { + public Issue24434() + { + VerticalStackLayout vsl = new VerticalStackLayout(); + + vsl.Add(new Button() + { + Text = "Click me and you should see a label appear beneath me", + LineBreakMode = LineBreakMode.WordWrap, + AutomationId = "ClickMe", + Command = new Command(async () => + { + TaskCompletionSource taskCompletionSource = new TaskCompletionSource(); + vsl.Unloaded += (_,_) => + { + vsl.Add(new Label { Text = "Hello, World!", AutomationId = "Success" }); + taskCompletionSource.TrySetResult(); + }; + + await Navigation.PushAsync(new ContentPage(){ Content = new Label() { Text = "I should just disappear"}}); + await Navigation.PushModalAsync(new ContentPage(){ Content = new Label() { Text = "I should just disappear"}}); + + await taskCompletionSource.Task.WaitAsync(TimeSpan.FromSeconds(5)); + await Navigation.PopAsync(); + await Navigation.PopModalAsync(); + }) + }); + + Content = vsl; + } + } +} diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue24434.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue24434.cs new file mode 100644 index 000000000000..a4421e4dcefa --- /dev/null +++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue24434.cs @@ -0,0 +1,24 @@ +using NUnit.Framework; +using UITest.Appium; +using UITest.Core; + +namespace Microsoft.Maui.TestCases.Tests.Issues +{ + public class Issue24434 : _IssuesUITest + { + public Issue24434(TestDevice testDevice) : base(testDevice) + { + } + + public override string Issue => "Modifying a layout while view isn't part of the Window fails to update the layout visually"; + + [Test] + [Category(UITestCategories.Layout)] + public void TapThenDoubleTap() + { + App.WaitForElement("ClickMe"); + App.Tap("ClickMe"); + App.WaitForElement("Success"); + } + } +} \ No newline at end of file diff --git a/src/Core/src/Platform/iOS/LayoutView.cs b/src/Core/src/Platform/iOS/LayoutView.cs index b4c972198454..98672006b113 100644 --- a/src/Core/src/Platform/iOS/LayoutView.cs +++ b/src/Core/src/Platform/iOS/LayoutView.cs @@ -11,14 +11,14 @@ public override void SubviewAdded(UIView uiview) { InvalidateConstraintsCache(); base.SubviewAdded(uiview); - this.GetSuperViewIfWindowSet()?.SetNeedsLayout(); + this.Superview?.SetNeedsLayout(); } public override void WillRemoveSubview(UIView uiview) { InvalidateConstraintsCache(); base.WillRemoveSubview(uiview); - this.GetSuperViewIfWindowSet()?.SetNeedsLayout(); + this.Superview?.SetNeedsLayout(); } public override UIView? HitTest(CGPoint point, UIEvent? uievent) diff --git a/src/Core/src/Platform/iOS/MauiView.cs b/src/Core/src/Platform/iOS/MauiView.cs index 0f6ea22eb460..c3e0db4349fa 100644 --- a/src/Core/src/Platform/iOS/MauiView.cs +++ b/src/Core/src/Platform/iOS/MauiView.cs @@ -140,7 +140,7 @@ public override void SetNeedsLayout() { InvalidateConstraintsCache(); base.SetNeedsLayout(); - this.GetSuperViewIfWindowSet()?.SetNeedsLayout(); + this.Superview?.SetNeedsLayout(); } IVisualTreeElement? IVisualTreeElementProvidable.GetElement() diff --git a/src/Core/src/Platform/iOS/ViewExtensions.cs b/src/Core/src/Platform/iOS/ViewExtensions.cs index 00a19ce029d9..79d6c5f64ad7 100644 --- a/src/Core/src/Platform/iOS/ViewExtensions.cs +++ b/src/Core/src/Platform/iOS/ViewExtensions.cs @@ -264,18 +264,10 @@ public static void UpdateBackgroundLayerFrame(this UIView view) } } - internal static UIView? GetSuperViewIfWindowSet(this UIView? view) - { - if (view?.Window is null) - return null; - - return view.Superview; - } - public static void InvalidateMeasure(this UIView platformView, IView view) { platformView.SetNeedsLayout(); - platformView.GetSuperViewIfWindowSet()?.SetNeedsLayout(); + platformView.Superview?.SetNeedsLayout(); } public static void UpdateWidth(this UIView platformView, IView view) diff --git a/src/Core/src/Platform/iOS/WrapperView.cs b/src/Core/src/Platform/iOS/WrapperView.cs index 7cf656e6d286..95728ffa4264 100644 --- a/src/Core/src/Platform/iOS/WrapperView.cs +++ b/src/Core/src/Platform/iOS/WrapperView.cs @@ -240,7 +240,7 @@ public override void SetNeedsLayout() { base.SetNeedsLayout(); - this.GetSuperViewIfWindowSet()?.SetNeedsLayout(); + this.Superview?.SetNeedsLayout(); } partial void ClipChanged() From 1693c5986ed51ffaf992b6a217b1eea149a68bd6 Mon Sep 17 00:00:00 2001 From: Shane Neuville Date: Wed, 28 Aug 2024 12:07:22 -0500 Subject: [PATCH 2/2] - fix --- .../TestCases.HostApp/Issues/Issue24434.cs | 52 +++++++++++-------- .../Tests/Issues/Issue24434.cs | 2 +- 2 files changed, 31 insertions(+), 23 deletions(-) diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue24434.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue24434.cs index f27554aafd86..c589c6ff1594 100644 --- a/src/Controls/tests/TestCases.HostApp/Issues/Issue24434.cs +++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue24434.cs @@ -4,36 +4,44 @@ namespace Maui.Controls.Sample.Issues { [Issue(IssueTracker.Github, 24434, "Modifying a layout while view isn't part of the Window fails to update the layout visually", PlatformAffected.iOS)] - public class Issue24434 : ContentPage + public class Issue24434 : NavigationPage { - public Issue24434() + public Issue24434() : base(new TestPage()) { - VerticalStackLayout vsl = new VerticalStackLayout(); - vsl.Add(new Button() + } + + public class TestPage : ContentPage + { + public TestPage() { - Text = "Click me and you should see a label appear beneath me", - LineBreakMode = LineBreakMode.WordWrap, - AutomationId = "ClickMe", - Command = new Command(async () => + VerticalStackLayout vsl = new VerticalStackLayout(); + + vsl.Add(new Button() { - TaskCompletionSource taskCompletionSource = new TaskCompletionSource(); - vsl.Unloaded += (_,_) => + Text = "Click me and you should see a label appear beneath me", + LineBreakMode = LineBreakMode.WordWrap, + AutomationId = "ClickMe", + Command = new Command(async () => { - vsl.Add(new Label { Text = "Hello, World!", AutomationId = "Success" }); - taskCompletionSource.TrySetResult(); - }; + TaskCompletionSource taskCompletionSource = new TaskCompletionSource(); + vsl.Unloaded += (_, _) => + { + vsl.Add(new Label { Text = "Hello, World!", AutomationId = "Success" }); + taskCompletionSource.TrySetResult(); + }; + + await Navigation.PushAsync(new ContentPage() { Content = new Label() { Text = "I should just disappear" } }); + await Navigation.PushModalAsync(new ContentPage() { Content = new Label() { Text = "I should just disappear" } }); - await Navigation.PushAsync(new ContentPage(){ Content = new Label() { Text = "I should just disappear"}}); - await Navigation.PushModalAsync(new ContentPage(){ Content = new Label() { Text = "I should just disappear"}}); - - await taskCompletionSource.Task.WaitAsync(TimeSpan.FromSeconds(5)); - await Navigation.PopAsync(); - await Navigation.PopModalAsync(); - }) - }); + await taskCompletionSource.Task.WaitAsync(TimeSpan.FromSeconds(5)); + await Navigation.PopModalAsync(); + await Navigation.PopAsync(); + }) + }); - Content = vsl; + Content = vsl; + } } } } diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue24434.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue24434.cs index a4421e4dcefa..8f7b078f06a2 100644 --- a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue24434.cs +++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue24434.cs @@ -14,7 +14,7 @@ public Issue24434(TestDevice testDevice) : base(testDevice) [Test] [Category(UITestCategories.Layout)] - public void TapThenDoubleTap() + public void ModifyingANonVisibleLayoutWorks() { App.WaitForElement("ClickMe"); App.Tap("ClickMe");