diff --git a/src/Controls/tests/TestCases.Android.Tests/snapshots/android/ClippedStackLayoutInsideBorderWithBackgroundRendersCorrectly.png b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/ClippedStackLayoutInsideBorderWithBackgroundRendersCorrectly.png new file mode 100644 index 000000000000..514422386a6f Binary files /dev/null and b/src/Controls/tests/TestCases.Android.Tests/snapshots/android/ClippedStackLayoutInsideBorderWithBackgroundRendersCorrectly.png differ diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue33241.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue33241.cs new file mode 100644 index 000000000000..21bb9b260887 --- /dev/null +++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue33241.cs @@ -0,0 +1,38 @@ +using Microsoft.Maui.Controls.Shapes; +namespace Maui.Controls.Sample.Issues; + +[Issue(IssueTracker.Github, 33241, "StackLayout fails to render content while applying Clip, and the layout is placed inside a Border with Background", PlatformAffected.iOS | PlatformAffected.macOS)] +public class Issue33241 : ContentPage +{ + public Issue33241() + { + var layout = new VerticalStackLayout(); + var label = new Label(); + label.Text = "The blue box should have a red box inside of it."; + label.AutomationId = "Label"; + layout.Children.Add(label); + var border = new Border + { + HeightRequest = 500, + Background = Colors.SkyBlue, + Padding = 10, + Content = + new Issue33241_CustomView + { + Background = Colors.Red, + Padding = 10 + } + }; + layout.Children.Add(border); + Content = layout; + } +} + +public class Issue33241_CustomView : StackLayout +{ + protected override void OnSizeAllocated(double width, double height) + { + this.Clip = new RoundRectangleGeometry { Rect = new Rect(0, 0, width, height) }; + base.OnSizeAllocated(width, height); + } +} \ No newline at end of file diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue33241.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue33241.cs new file mode 100644 index 000000000000..3015e3a98d6c --- /dev/null +++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue33241.cs @@ -0,0 +1,22 @@ +using NUnit.Framework; +using UITest.Appium; +using UITest.Core; + +namespace Microsoft.Maui.TestCases.Tests.Issues; + +public class Issue33241 : _IssuesUITest +{ + public Issue33241(TestDevice testDevice) : base(testDevice) + { + } + + public override string Issue => "StackLayout fails to render content while applying Clip, and the layout is placed inside a Border with Background"; + + [Test] + [Category(UITestCategories.Border)] + public void ClippedStackLayoutInsideBorderWithBackgroundRendersCorrectly() + { + App.WaitForElement("Label"); + VerifyScreenshot(); + } +} diff --git a/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/ClippedStackLayoutInsideBorderWithBackgroundRendersCorrectly.png b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/ClippedStackLayoutInsideBorderWithBackgroundRendersCorrectly.png new file mode 100644 index 000000000000..6d0d0cc1b50e Binary files /dev/null and b/src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/ClippedStackLayoutInsideBorderWithBackgroundRendersCorrectly.png differ diff --git a/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios-26/ClippedStackLayoutInsideBorderWithBackgroundRendersCorrectly.png b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios-26/ClippedStackLayoutInsideBorderWithBackgroundRendersCorrectly.png new file mode 100644 index 000000000000..f4a3812f20ff Binary files /dev/null and b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios-26/ClippedStackLayoutInsideBorderWithBackgroundRendersCorrectly.png differ diff --git a/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/ClippedStackLayoutInsideBorderWithBackgroundRendersCorrectly.png b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/ClippedStackLayoutInsideBorderWithBackgroundRendersCorrectly.png new file mode 100644 index 000000000000..efab4306bb81 Binary files /dev/null and b/src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/ClippedStackLayoutInsideBorderWithBackgroundRendersCorrectly.png differ diff --git a/src/Core/src/Platform/iOS/LayerExtensions.cs b/src/Core/src/Platform/iOS/LayerExtensions.cs index 45808a9d9245..f5bdb6afc460 100644 --- a/src/Core/src/Platform/iOS/LayerExtensions.cs +++ b/src/Core/src/Platform/iOS/LayerExtensions.cs @@ -14,6 +14,12 @@ public static void InsertBackgroundLayer(this UIView control, CALayer background { var layer = control.Layer; + // Ensure the background layer always renders behind subview layers, + // even if UIKit reorganizes the sublayer array during layout passes. + // Setting ZPosition before insertion is safe — it's a property on the + // layer object and only takes effect once added to the sublayer hierarchy. + backgroundLayer.ZPosition = -1; + if (index > -1) layer.InsertSublayer(backgroundLayer, index); else diff --git a/src/Core/src/Platform/iOS/WrapperView.cs b/src/Core/src/Platform/iOS/WrapperView.cs index b75189a2f877..65ad129e0a65 100644 --- a/src/Core/src/Platform/iOS/WrapperView.cs +++ b/src/Core/src/Platform/iOS/WrapperView.cs @@ -99,10 +99,11 @@ public override void LayoutSubviews() return; if (_borderView is not null) + { BringSubviewToFront(_borderView); + } var child = subviews[0]; - child.Frame = Bounds; if (MaskLayer is not null)