diff --git a/src/Controls/tests/TestCases.Android.Tests/snapshots/android/ViewShouldNotShiftOnShadowChanged.png b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/ViewShouldNotShiftOnShadowChanged.png new file mode 100644 index 000000000000..08c2ac7f816b Binary files /dev/null and b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/ViewShouldNotShiftOnShadowChanged.png differ diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue27732.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue27732.cs new file mode 100644 index 000000000000..a7793918a570 --- /dev/null +++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue27732.cs @@ -0,0 +1,105 @@ +using Microsoft.Maui.Controls.Shapes; + +namespace Maui.Controls.Sample.Issues; + +[Issue(IssueTracker.Github, 27732, "[Windows] View Position Shifts When Shadows Are Dynamically Removed or Resized", PlatformAffected.UWP)] +public class Issue27732 : TestContentPage +{ + Border borderShadow; + Image imageShadow; + Label labelShadow; + Button shadowButton; + bool _shadow = false; + + protected override void Init() + { + Title = "Issue27732"; + borderShadow = new Border + { + AutomationId = "BorderShadow", + StrokeShape = new RoundRectangle { CornerRadius = 24 }, + Background = Colors.Red, + WidthRequest = 80 + }; + + imageShadow = new Image + { + AutomationId = "ImageShadow", + Aspect = Aspect.AspectFit, + Source = "oasis.jpg", + WidthRequest = 80 + }; + + labelShadow = new Label + { + AutomationId = "LabelShadow", + Text = "Label", + FontSize = 18, + WidthRequest = 80 + }; + + shadowButton = new Button + { + AutomationId = "ToggleShadowButton", + Text = "Add Shadow", + HorizontalOptions = LayoutOptions.Start + }; + shadowButton.Clicked += OnShadowClicked; + + Content = new StackLayout + { + Margin = new Thickness(0, 40), + HorizontalOptions = LayoutOptions.Center, + Spacing = 20, + Children = + { + new HorizontalStackLayout + { + HorizontalOptions = LayoutOptions.Center, + Spacing = 10, + Children = { borderShadow, imageShadow, labelShadow } + }, + new HorizontalStackLayout + { + Spacing = 10, + Children = + { + new Label + { + Text = "Toggle Shadow Button:", + FontSize = 15, + VerticalOptions = LayoutOptions.Center, + HorizontalOptions = LayoutOptions.Start + }, + shadowButton + } + } + } + }; + } + + void OnShadowClicked(object sender, EventArgs e) + { + if (_shadow) + { + shadowButton.Text = "Add Shadow"; + borderShadow.Shadow = imageShadow.Shadow = labelShadow.Shadow = null; + _shadow = false; + } + else + { + shadowButton.Text = "Remove Shadow"; + + var newShadow = new Shadow + { + Brush = Brush.Black, + Offset = new Point(4, 4), + Radius = 10, + Opacity = 0.5f + }; + + borderShadow.Shadow = imageShadow.Shadow = labelShadow.Shadow = newShadow; + _shadow = true; + } + } +} \ No newline at end of file diff --git a/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/ViewShouldNotShiftOnShadowChanged.png b/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/ViewShouldNotShiftOnShadowChanged.png new file mode 100644 index 000000000000..91bcc6d9e31a Binary files /dev/null and b/src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/ViewShouldNotShiftOnShadowChanged.png differ diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue27732.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue27732.cs new file mode 100644 index 000000000000..7f8e6a59d9a6 --- /dev/null +++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue27732.cs @@ -0,0 +1,28 @@ +using NUnit.Framework; +using UITest.Appium; +using UITest.Core; + +namespace Microsoft.Maui.TestCases.Tests.Issues; + +public class Issue27732 : _IssuesUITest +{ + public Issue27732(TestDevice testDevice) : base(testDevice) + { + } + + public override string Issue => "[Windows] View Position Shifts When Shadows Are Dynamically Removed or Resized"; + + const string ToggleShadowButton = "ToggleShadowButton"; + + [Test] + [Category(UITestCategories.Visual)] + public void ViewShouldNotShiftOnShadowChanged() + { + App.WaitForElement(ToggleShadowButton); + for (int i = 0; i < 5; i++) + { + App.Tap(ToggleShadowButton); + } + VerifyScreenshot(); + } +} \ No newline at end of file diff --git a/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/Issue24414Test_5.png b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/Issue24414Test_5.png index bfb6730747f7..dd3e12c0ba7c 100644 Binary files a/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/Issue24414Test_5.png and b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/Issue24414Test_5.png differ diff --git a/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/ViewShouldNotShiftOnShadowChanged.png b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/ViewShouldNotShiftOnShadowChanged.png new file mode 100644 index 000000000000..81b03c6dd22a Binary files /dev/null and b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/ViewShouldNotShiftOnShadowChanged.png differ diff --git a/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/ViewShouldNotShiftOnShadowChanged.png b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/ViewShouldNotShiftOnShadowChanged.png new file mode 100644 index 000000000000..3fd0319e8ea1 Binary files /dev/null and b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/ViewShouldNotShiftOnShadowChanged.png differ diff --git a/src/Core/src/Handlers/View/ViewHandlerOfT.Windows.cs b/src/Core/src/Handlers/View/ViewHandlerOfT.Windows.cs index ab3758e657b8..853ed06ce963 100644 --- a/src/Core/src/Handlers/View/ViewHandlerOfT.Windows.cs +++ b/src/Core/src/Handlers/View/ViewHandlerOfT.Windows.cs @@ -57,9 +57,9 @@ protected override void RemoveContainer() } #pragma warning disable RS0030 // Do not use banned APIs; Panel.Children is banned for performance reasons. MauiPanel might not be used everywhere though. - var oldParentChildren = PlatformView.Parent is MauiPanel mauiPanel + var oldParentChildren = ContainerView.Parent is MauiPanel mauiPanel ? mauiPanel.CachedChildren - : (PlatformView.Parent as Panel)?.Children; + : (ContainerView.Parent as Panel)?.Children; #pragma warning restore RS0030 // Do not use banned APIs var oldIndex = oldParentChildren?.IndexOf(ContainerView);