Skip to content

Fixed Stacklayout is not rendered when clip is applied and StackLayout placed child to the Border control in iOS/ Mac platform#33330

Merged
kubaflo merged 14 commits into
dotnet:inflight/currentfrom
KarthikRajaKalaimani:fix-33241
Apr 10, 2026
Merged

Fixed Stacklayout is not rendered when clip is applied and StackLayout placed child to the Border control in iOS/ Mac platform#33330
kubaflo merged 14 commits into
dotnet:inflight/currentfrom
KarthikRajaKalaimani:fix-33241

Conversation

@KarthikRajaKalaimani
Copy link
Copy Markdown
Contributor

@KarthikRajaKalaimani KarthikRajaKalaimani commented Dec 30, 2025

Note

Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!

Issue Details:

Stacklayout is not rendered when clip is applied and StackLayout placed child to the Border control in iOS/ Mac platform.

Root Cause:

When the clip is applied to the StackLayout, its ContainerView (WrapperView) is being inserted at index 0 to its parent control Border, which places it below Border's background layer in the z-order. As a result, the stacklayout is not visible in the view in iOS and Mac platform.

Description of Change:

The wrapper view is brought to the front of its parent’s subview stack so it renders above the Border background in the Z order.

Tested the behavior in the following platforms.

  • Android
  • Windows
  • iOS
  • Mac

Reference:

N/A

Issues Fixed:

Fixes #33241

Screenshots

Before After
image image

@dotnet-policy-service dotnet-policy-service Bot added community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration labels Dec 30, 2025
@kubaflo kubaflo added platform/android platform/ios area-layout StackLayout, GridLayout, ContentView, AbsoluteLayout, FlexLayout, ContentPresenter labels Dec 30, 2025
@rmarinho
Copy link
Copy Markdown
Member

rmarinho commented Feb 18, 2026

🤖 AI Summary

📊 Expand Full Review
🔍 Pre-Flight — Context & Validation
📝 Review SessionSnapshot included for mac and android platform · fd8048b

Issue: #33241 - [Mac/iOS] StackLayout fails to render content while applying Clip, and the layout is placed inside a Border with Background
Platforms Affected: iOS, macOS (fix in src/Core/src/Platform/iOS/WrapperView.cs)
Files Changed: 1 implementation file, 2 test files, 3 snapshot images

Issue Summary

When a RoundRectangleGeometry clip is applied to a custom StackLayout that's placed inside a Border with a Background set, the StackLayout fails to render on iOS and Mac. The issue only occurs when the parent Border has a Background property set.

Root Cause (per PR): When clip is applied to StackLayout, its ContainerView (WrapperView) is inserted at index 0 in its parent Border's subview stack, which places it below Border's background layer in the z-order. As a result, the StackLayout is invisible.

Files Changed

  • Fix files (1):
    • src/Core/src/Platform/iOS/WrapperView.cs (+6/-1) - iOS/MacCatalyst platform code
  • Test files (2):
    • src/Controls/tests/TestCases.HostApp/Issues/Issue33241.cs (+33) - HostApp test page
    • src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue33241.cs (+22) - NUnit test
  • Snapshot files (3):
    • Android, iOS, Mac snapshots

Platform Analysis

Important: The fix is in src/Core/src/Platform/iOS/WrapperView.cs (iOS/MacCatalyst only). The HostApp test class has PlatformAffected.iOS | PlatformAffected.macOS. The Android snapshot exists but the fix does NOT affect Android behavior. Testing on Android would yield false positive (test passes with or without fix).

Gate should run on iOS (macOS host has iOS available).

PR Discussion

  • Only automated policy bot comment; no reviewer feedback yet.
  • Community contribution from Syncfusion partner.

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #33330 In WrapperView.LayoutSubviews(), add else branch when _borderView is null: call this.Superview?.BringSubviewToFront(this) to bring WrapperView to front of parent's subview PENDING (Gate) WrapperView.cs (+6/-1) Original PR stack

🚦 Gate — Test Verification
📝 Review SessionSnapshot included for mac and android platform · fd8048b

** INCONCLUSIVE (Environment Blocker - snapshot resolution mismatch)Result:**
Platform: iOS (iPhone 16 Pro)
Mode: Full Verification attempted

Attempts Made

DEVICE_UDID not substituted (literal $(DEVICE_UDID))
Appium mac2 driver not installed
INCONCLUSIVE - snapshot resolution mismatch

Test Execution (iPhone 16 Pro)

PASSES (both with and without fix)
FAILS both with and without fix

Error: Snapshot different than baseline: Issue33241Test.png (size differs - baseline is 1124x2286 pixels, actual is 1206x2472 pixels)

Analysis

The test structure is sound:

  • WaitForElement("CustomView") would detect if the element is inaccessible
  • VerifyScreenshot() would catch visual differences (element hidden vs visible)

However, the baseline snapshot included in the PR was captured on a **different resolution iPhone Xs) than our test environment (120611242286px2472px = iPhone 16 Pro). This causes VerifyScreenshot() to fail with a size mismatch error before it can compare pixel content.

The fix itself (WrapperView.cs: call Superview?.BringSubviewToFront(this) when no _borderView) is architecturally but cannot be empirically verified in this environment due to device/snapshot mismatch.correct

Gate Disposition

Gate is BLOCKED due to environment limitation (device resolution mismatch). Per autonomous execution rules, proceeding to Fix phase with partial results.

  • Tests FAIL without fix (passes WaitForElement, but same VerifyScreenshot error):
  • Tests PASS with (same VerifyScreenshot error - can't distinguish)fix:

🔧 Fix — Analysis & Comparison
📝 Review SessionSnapshot included for mac and android platform · fd8048b

Fix Candidates

# Source Approach Test Result Files Changed Notes
1 try-fix (claude-sonnet-4.5) Override MovedToSuperview() to call Superview.BringSubviewToFront(this) once when added to superview FAIL (env) WrapperView.cs Snapshot resolution mismatch (1124Hierarchy2286 vs 1206 2472). Also conceptually flawed: timing too early, z-order can be reset by subsequent layout operations
PR PR #33330 In , add branch: when no PASS (Gate conceptual) WrapperView.cs (+6/-1) Original PR; correct approach - runs on every layout pass, ensures z-order maintained

Exhausted: No (stopped early - environment blocker confirmed after 1 attempt)

Environment Blocker: The test Issue33241Test uses VerifyScreenshot(). The baseline snapshot was captured at 11242286 pixels (likely iPhone Xs), but our test environment uses iPhone 16 Pro (12062472 pixels). Every try-fix attempt - regardless of fix approach - fails with VisualTestFailedException: Snapshot different than baseline (size differs). This environment blocker was confirmed on all tested platforms (iOS, MacCatalyst).

Selected Fix: PR's The LayoutSubviews() approach is architecturally correct because:fix

  1. Runs after all layers are created (timing is right)
  2. Re-applies z-order correction on every layout pass (robust against z-order resets)
  3. Minimal change, targeted to the exact problem location
  4. The MovedToSuperview() alternative was explored and found flawed (timing issue)

Root Cause Analysis

When Clip is set on a StackLayout in .NET MAUI on iOS/Mac, the handler calls SetClip() which creates a WrapperView container. This WrapperView is inserted into its parent's subview list at index 0. On iOS, the parent Border's background is rendered through a CALayer that may be positioned above index-0 subviews. The WrapperView (containing the StackLayout) ends up hidden beneath the Border's background layer.

The fix calls BringSubviewToFront(this) on the WrapperView's superview in the else branch of LayoutSubviews() (when _borderView is null), ensuring the WrapperView sits above the Border background layer.


📋 Report — Final Recommendation
📝 Review SessionSnapshot included for mac and android platform · fd8048b

Final Recommendation: APPROVE (with suggestions)

Summary

PR #33330 fixes a z-order issue on iOS/Mac where a StackLayout with a Clip becomes invisible when placed inside a Border with a Background. The fix is minimal, targeted, and architecturally sound. Gate was inconclusive due to a snapshot resolution mismatch in the test environment (baseline was captured at 11242286px on iPhone Xs; test ran on iPhone 16 Pro at 12062472px). One try-fix alternative was explored and found conceptually inferior to the PR's approach.


Root Cause

When .Clip is set on a layout, .NET MAUI wraps the platform view in a WrapperView. This WrapperView is inserted into its parent's subview stack. On iOS/Mac, the parent Border's background rendering (CALayer) can end up above the WrapperView in z-order, making the layout invisible. The WrapperView.LayoutSubviews() already called BringSubviewToFront(_borderView) for the border decoration case, but had no z-order correction for the clip-only case (_borderView is null).

Fix Quality

The fix adds an else branch in WrapperView.LayoutSubviews(): when _borderView is null (clip-only scenario), call Superview?.BringSubviewToFront(this) to ensure the WrapperView sits above the parent's background layers. This is correct because:

  • Runs on every layout pass, correcting z-order even if it's reset elsewhere
  • Mirrors the existing BringSubviewToFront(_borderView) pattern already in place
  • Null-safe (Superview?.)
  • Minimal change in the right location

Alternative Considered

Try-fix explored using MovedToSuperview() override to correct z-order at hierarchy insertion time. This is inferior because the timing is too early (background layers may not exist yet) and z-order can be reset by subsequent layout operations. The PR's LayoutSubviews() approach is correctly timed.


PR Finalize Analysis

Title Assessment

Current: Fixed Stacklayout is not rendered when clip is applied and StackLayout placed child to the Border control in iOS/ Mac platform

Issues:

  • Fixed prefix is noise/non-standard
  • Doesn't follow [Platform] Component: Description convention
  • Describes the bug, not the fix

Recommended: [iOS/Mac] WrapperView: Bring to front when Clip applied inside Border with Background


Description Assessment: Good - Minor Additions Needed

Quality Well-structured, accurate, includes screenshots, root cause, and description of change. NOTE block is present.:

Missing elements:

  • What NOT to Do section (documenting the MovedToSuperview() approach as inferior)
  • More explicit note that _borderView null = clip-only case

Code Review Findings

Redundant this. qualifier (minor style)

  • File: src/Core/src/Platform/iOS/WrapperView.cs:107
  • Code: this.Superview?.BringSubviewToFront(this);
  • Suggestion: Use Superview?.BringSubviewToFront( the this. prefix is idiomatic in some codebases but unnecessary here. Minor style point.this);

Missing newline at end of file

  • File: src/Controls/tests/TestCases.HostApp/Issues/Issue33241.cs
  • Code: } without trailing newline
  • Suggestion: Add newline at end of file (common style convention in this repo)

Snapshot baseline device mismatch (needs CI fix)

  • Files: TestCases.iOS.Tests/snapshots/ios/Issue33241Test.png
  • Problem: The baseline snapshot is 11242286px (captured on iPhone Xs) but CI or other devices may use different resolutions. If CI uses the same device type this is fine, but the test environment should match what CI uses.
  • Suggestion: Verify the snapshot was captured using iPhone Xs (the standard device used per test infrastructure docs). If not, recapture on iPhone Xs.

Test attribute is correct

  • PlatformAffected.iOS | PlatformAffected.macOS correctly scopes the test to affected platforms; the bug is iOS/Mac only.

Looks Good

  • Fix location (WrapperView.LayoutSubviews()) is runs every layout pass, ensuring z-order is maintainedcorrect
  • Null-safe superview access (Superview?.)
  • Mirrors the existing BringSubviewToFront(_borderView) pattern in the same method
  • Test structure (WaitForElement + VerifyScreenshot) is appropriate for this visual bug
  • Screenshots in PR description clearly show before/after

None.


Gate Status

** Snapshot resolution mismatch prevented empirical validation (baseline: 1124Inconclusive2286, actual: 1206** 2472). The fix is reviewed and approved on code merits. Team should verify the iOS snapshot was captured on iPhone Xs as the standard CI device.


📋 Expand PR Finalization Review
Title: ✅ Good

Current: Fixed Stacklayout is not rendered when clip is applied and StackLayout placed child to the Border control in iOS/ Mac platform

Description: ✅ Good
  • Uses "Fixed" prefix — commit message titles should describe the change, not the action
  • Too verbose and awkward phrasing ("placed child to the Border control")
  • "Stacklayout" vs "StackLayout" — capitalization inconsistency
  • Platform is repeated awkwardly ("iOS/ Mac platform" with stray space)
  • Doesn't name the key type involved (WrapperView)
    Missing Elements:

**

  • The description title says "iOS/ Mac platform" but the fix is in WrapperView.cs, which is the shared iOS/MacCatalyst file. Worth noting MacCatalyst explicitly.

Overall verdict: The description is well-written and accurate. A recommended description is provided with minor improvements (title tweak, clarifications for future agents).


Phase 2: Code Review

See code-review.md for detailed findings.

Summary:

  • 🟡 1 medium concern: BringSubviewToFront(this) called on every LayoutSubviews() pass — broad behavioral change
  • 🟡 2 minor code quality issues in test files (indentation, missing newline)
  • ✅ Fix logic is correct and targeted

Recommended Changes

  1. Update PR title to: [iOS/Mac] WrapperView: Bring to front when clip is applied inside a Border
  2. Add missing newline at end of src/Controls/tests/TestCases.HostApp/Issues/Issue33241.cs
  3. Fix double-indentation in src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue33241.cs
  4. Consider whether BringSubviewToFront should be guarded to only run when a clip/geometry is applied (see code-review.md)

✨ Suggested PR Description

[!NOTE]
Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!

Root Cause

When a clip geometry (e.g., RoundRectangleGeometry) is applied to a MAUI view (e.g., StackLayout) that is a child of a Border with a Background, the platform wraps the clipped view in a WrapperView. On iOS/MacCatalyst, WrapperView is inserted into the Border's native subview hierarchy at index 0 (bottom of the z-order), placing it behind the Border's background layer. This makes the WrapperView's content invisible.

Description of Change

In WrapperView.LayoutSubviews(), an else branch was added: when no _borderView is present (i.e., the WrapperView itself is a content child, not a border host), the WrapperView calls this.Superview?.BringSubviewToFront(this) to move itself to the top of its parent's subview stack. This ensures the clipped content renders above the Border's background layer.

File changed: src/Core/src/Platform/iOS/WrapperView.cs

The existing _borderView path is unchanged — when WrapperView hosts a BorderView, it still calls BringSubviewToFront(_borderView) as before.

Issues Fixed

Fixes #33241

Platforms Tested

  • Android
  • Windows
  • iOS
  • Mac (MacCatalyst)
Code Review: ✅ Passed

Code Review — PR #33330

🟡 Medium Concern

BringSubviewToFront(this) called on every LayoutSubviews() pass

File: src/Core/src/Platform/iOS/WrapperView.cs
Lines: ~105–108 (the new else branch)

else
{
    this.Superview?.BringSubviewToFront(this);
}

Problem:
LayoutSubviews() is called on every layout pass (e.g., size change, rotation, parent relayout). The new else branch runs BringSubviewToFront(this) unconditionally every time — for all WrapperViews that don't have a _borderView, not just those with a clip applied.

This is a broader behavioral change than the fix requires. Specifically:

  • A WrapperView wraps views that need a clip, shadow, or border. Not all of these need to be at the front of their superview's z-order.
  • If any other code relies on a WrapperView being behind other sibling views, this change will silently break it.
  • Calling BringSubviewToFront is cheap but semantically significant — it permanently reorders subviews on every layout pass.

Recommendation:
Consider guarding the BringSubviewToFront(this) call to only apply when a clip (MaskLayer) is present:

else if (MaskLayer is not null)
{
    this.Superview?.BringSubviewToFront(this);
}

This scopes the fix to only the cases where a clip geometry is being applied, which is the described root cause, rather than all WrapperViews without a border.


🟡 Minor Issues

Double-indentation in test file

File: src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue33241.cs

The constructor and members use two levels of indentation inside the class body, which appears to be an extra tab level:

public class Issue33241 : _IssuesUITest
{
		public Issue33241(TestDevice testDevice) : base(testDevice)  // ← extra indent
		{
		}

Should be single-level indentation consistent with other test files.


Missing newline at end of file

File: src/Controls/tests/TestCases.HostApp/Issues/Issue33241.cs

The diff shows \ No newline at end of file. C# source files should end with a newline.


Mixed indentation in HostApp file

File: src/Controls/tests/TestCases.HostApp/Issues/Issue33241.cs

The Issue33241() constructor body uses a mix of tabs and spaces for indentation (visible in the diff). The new Border { ... } initializer uses spaces while the rest of the file uses tabs.


✅ Looks Good

  • Fix logic is correct: The root cause (WrapperView inserted below Background layer) is correctly addressed by calling BringSubviewToFront.
  • Test coverage: UI tests added for iOS, Mac, and Android with screenshots.
  • No API surface changes: The fix is entirely internal to WrapperView.LayoutSubviews().
  • Existing _borderView path unchanged: The BringSubviewToFront(_borderView) call for the border case is unaffected.
  • The [Issue] attribute on the HostApp class correctly specifies PlatformAffected.iOS | PlatformAffected.macOS.

@rmarinho rmarinho added s/agent-approved AI agent recommends approval - PR fix is correct and optimal s/agent-fix-lose Author adopted the agent's fix and it turned out to be bad s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) labels Feb 18, 2026
@kubaflo kubaflo added s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates and removed s/agent-fix-lose Author adopted the agent's fix and it turned out to be bad labels Feb 20, 2026
@sheiksyedm sheiksyedm marked this pull request as ready for review March 13, 2026 10:26
Copilot AI review requested due to automatic review settings March 13, 2026 10:27
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes an iOS/Mac rendering issue where a clipped StackLayout inside a Border with a background becomes invisible due to incorrect z-ordering, and adds a new UI test with snapshot baselines to prevent regressions.

Changes:

  • Adjusts iOS WrapperView layout behavior to alter z-ordering when a wrapped view is clipped.
  • Adds a new Issue UI test (Issue33241) that verifies rendering via screenshot comparison.
  • Adds new snapshot baselines for Android/iOS/Mac test runners.

Reviewed changes

Copilot reviewed 3 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/Core/src/Platform/iOS/WrapperView.cs Updates LayoutSubviews to change z-ordering of wrapper/border views during layout.
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue33241.cs Adds a new Appium/NUnit issue test that waits for the clipped view and verifies via screenshot.
src/Controls/tests/TestCases.HostApp/Issues/Issue33241.cs Adds the HostApp reproduction page for Issue 33241 (Border + clipped StackLayout).
src/Controls/tests/TestCases.Android.Tests/snapshots/android/Issue33241Test.png Adds Android screenshot baseline for the new test.
src/Controls/tests/TestCases.iOS.Tests/snapshots/ios/Issue33241Test.png Adds iOS screenshot baseline for the new test.
src/Controls/tests/TestCases.Mac.Tests/snapshots/mac/Issue33241Test.png Adds Mac screenshot baseline for the new test.

Comment thread src/Core/src/Platform/iOS/WrapperView.cs Outdated
Comment on lines +19 to +20
App.WaitForElement("CustomView");
VerifyScreenshot();
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 16, 2026

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 33330

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 33330"

@KarthikRajaKalaimani
Copy link
Copy Markdown
Contributor Author

🤖 AI Summary

📊 Expand Full Review
🔍 Pre-Flight — Context & Validation
📝 Review SessionSnapshot included for mac and android platform · fd8048b
Issue: #33241 - [Mac/iOS] StackLayout fails to render content while applying Clip, and the layout is placed inside a Border with Background Platforms Affected: iOS, macOS (fix in src/Core/src/Platform/iOS/WrapperView.cs) Files Changed: 1 implementation file, 2 test files, 3 snapshot images

Issue Summary

When a RoundRectangleGeometry clip is applied to a custom StackLayout that's placed inside a Border with a Background set, the StackLayout fails to render on iOS and Mac. The issue only occurs when the parent Border has a Background property set.

Root Cause (per PR): When clip is applied to StackLayout, its ContainerView (WrapperView) is inserted at index 0 in its parent Border's subview stack, which places it below Border's background layer in the z-order. As a result, the StackLayout is invisible.

Files Changed

  • Fix files (1):

    • src/Core/src/Platform/iOS/WrapperView.cs (+6/-1) - iOS/MacCatalyst platform code
  • Test files (2):

    • src/Controls/tests/TestCases.HostApp/Issues/Issue33241.cs (+33) - HostApp test page
    • src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue33241.cs (+22) - NUnit test
  • Snapshot files (3):

    • Android, iOS, Mac snapshots

Platform Analysis

Important: The fix is in src/Core/src/Platform/iOS/WrapperView.cs (iOS/MacCatalyst only). The HostApp test class has PlatformAffected.iOS | PlatformAffected.macOS. The Android snapshot exists but the fix does NOT affect Android behavior. Testing on Android would yield false positive (test passes with or without fix).

Gate should run on iOS (macOS host has iOS available).

PR Discussion

  • Only automated policy bot comment; no reviewer feedback yet.
  • Community contribution from Syncfusion partner.

Fix Candidates

Source Approach Test Result Files Changed Notes

PR PR #33330 In WrapperView.LayoutSubviews(), add else branch when _borderView is null: call this.Superview?.BringSubviewToFront(this) to bring WrapperView to front of parent's subview PENDING (Gate) WrapperView.cs (+6/-1) Original PR stack
🚦 Gate — Test Verification
📝 Review SessionSnapshot included for mac and android platform · fd8048b
** INCONCLUSIVE (Environment Blocker - snapshot resolution mismatch)Result:** Platform: iOS (iPhone 16 Pro) Mode: Full Verification attempted

Attempts Made

DEVICE_UDID not substituted (literal $(DEVICE_UDID)) Appium mac2 driver not installed INCONCLUSIVE - snapshot resolution mismatch

Test Execution (iPhone 16 Pro)

PASSES (both with and without fix) FAILS both with and without fix

Error: Snapshot different than baseline: Issue33241Test.png (size differs - baseline is 1124x2286 pixels, actual is 1206x2472 pixels)

Analysis

The test structure is sound:

  • WaitForElement("CustomView") would detect if the element is inaccessible
  • VerifyScreenshot() would catch visual differences (element hidden vs visible)

However, the baseline snapshot included in the PR was captured on a **different resolution iPhone Xs) than our test environment (120611242286px2472px = iPhone 16 Pro). This causes VerifyScreenshot() to fail with a size mismatch error before it can compare pixel content.

The fix itself (WrapperView.cs: call Superview?.BringSubviewToFront(this) when no _borderView) is architecturally but cannot be empirically verified in this environment due to device/snapshot mismatch.correct

Gate Disposition

Gate is BLOCKED due to environment limitation (device resolution mismatch). Per autonomous execution rules, proceeding to Fix phase with partial results.

  • Tests FAIL without fix (passes WaitForElement, but same VerifyScreenshot error):
  • Tests PASS with (same VerifyScreenshot error - can't distinguish)fix:

🔧 Fix — Analysis & Comparison
📝 Review SessionSnapshot included for mac and android platform · fd8048b

Fix Candidates

Source Approach Test Result Files Changed Notes

1 try-fix (claude-sonnet-4.5) Override MovedToSuperview() to call Superview.BringSubviewToFront(this) once when added to superview FAIL (env) WrapperView.cs Snapshot resolution mismatch (1124Hierarchy2286 vs 1206 2472). Also conceptually flawed: timing too early, z-order can be reset by subsequent layout operations
PR PR #33330 In , add branch: when no PASS (Gate conceptual) WrapperView.cs (+6/-1) Original PR; correct approach - runs on every layout pass, ensures z-order maintained
Exhausted: No (stopped early - environment blocker confirmed after 1 attempt)

Environment Blocker: The test Issue33241Test uses VerifyScreenshot(). The baseline snapshot was captured at 11242286 pixels (likely iPhone Xs), but our test environment uses iPhone 16 Pro (12062472 pixels). Every try-fix attempt - regardless of fix approach - fails with VisualTestFailedException: Snapshot different than baseline (size differs). This environment blocker was confirmed on all tested platforms (iOS, MacCatalyst).

Selected Fix: PR's The LayoutSubviews() approach is architecturally correct because:fix

  1. Runs after all layers are created (timing is right)
  2. Re-applies z-order correction on every layout pass (robust against z-order resets)
  3. Minimal change, targeted to the exact problem location
  4. The MovedToSuperview() alternative was explored and found flawed (timing issue)

Root Cause Analysis

When Clip is set on a StackLayout in .NET MAUI on iOS/Mac, the handler calls SetClip() which creates a WrapperView container. This WrapperView is inserted into its parent's subview list at index 0. On iOS, the parent Border's background is rendered through a CALayer that may be positioned above index-0 subviews. The WrapperView (containing the StackLayout) ends up hidden beneath the Border's background layer.

The fix calls BringSubviewToFront(this) on the WrapperView's superview in the else branch of LayoutSubviews() (when _borderView is null), ensuring the WrapperView sits above the Border background layer.

📋 Report — Final Recommendation
📝 Review SessionSnapshot included for mac and android platform · fd8048b

Final Recommendation: APPROVE (with suggestions)

Summary

PR #33330 fixes a z-order issue on iOS/Mac where a StackLayout with a Clip becomes invisible when placed inside a Border with a Background. The fix is minimal, targeted, and architecturally sound. Gate was inconclusive due to a snapshot resolution mismatch in the test environment (baseline was captured at 11242286px on iPhone Xs; test ran on iPhone 16 Pro at 12062472px). One try-fix alternative was explored and found conceptually inferior to the PR's approach.

Root Cause

When .Clip is set on a layout, .NET MAUI wraps the platform view in a WrapperView. This WrapperView is inserted into its parent's subview stack. On iOS/Mac, the parent Border's background rendering (CALayer) can end up above the WrapperView in z-order, making the layout invisible. The WrapperView.LayoutSubviews() already called BringSubviewToFront(_borderView) for the border decoration case, but had no z-order correction for the clip-only case (_borderView is null).

Fix Quality

The fix adds an else branch in WrapperView.LayoutSubviews(): when _borderView is null (clip-only scenario), call Superview?.BringSubviewToFront(this) to ensure the WrapperView sits above the parent's background layers. This is correct because:

  • Runs on every layout pass, correcting z-order even if it's reset elsewhere
  • Mirrors the existing BringSubviewToFront(_borderView) pattern already in place
  • Null-safe (Superview?.)
  • Minimal change in the right location

Alternative Considered

Try-fix explored using MovedToSuperview() override to correct z-order at hierarchy insertion time. This is inferior because the timing is too early (background layers may not exist yet) and z-order can be reset by subsequent layout operations. The PR's LayoutSubviews() approach is correctly timed.

PR Finalize Analysis

Title Assessment

Current: Fixed Stacklayout is not rendered when clip is applied and StackLayout placed child to the Border control in iOS/ Mac platform

Issues:

  • Fixed prefix is noise/non-standard
  • Doesn't follow [Platform] Component: Description convention
  • Describes the bug, not the fix

Recommended: [iOS/Mac] WrapperView: Bring to front when Clip applied inside Border with Background

Description Assessment: Good - Minor Additions Needed

Quality Well-structured, accurate, includes screenshots, root cause, and description of change. NOTE block is present.:

Missing elements:

  • What NOT to Do section (documenting the MovedToSuperview() approach as inferior)
  • More explicit note that _borderView null = clip-only case

Code Review Findings

Redundant this. qualifier (minor style)

  • File: src/Core/src/Platform/iOS/WrapperView.cs:107
  • Code: this.Superview?.BringSubviewToFront(this);
  • Suggestion: Use Superview?.BringSubviewToFront( the this. prefix is idiomatic in some codebases but unnecessary here. Minor style point.this);

Missing newline at end of file

  • File: src/Controls/tests/TestCases.HostApp/Issues/Issue33241.cs
  • Code: } without trailing newline
  • Suggestion: Add newline at end of file (common style convention in this repo)

Snapshot baseline device mismatch (needs CI fix)

  • Files: TestCases.iOS.Tests/snapshots/ios/Issue33241Test.png
  • Problem: The baseline snapshot is 11242286px (captured on iPhone Xs) but CI or other devices may use different resolutions. If CI uses the same device type this is fine, but the test environment should match what CI uses.
  • Suggestion: Verify the snapshot was captured using iPhone Xs (the standard device used per test infrastructure docs). If not, recapture on iPhone Xs.

Test attribute is correct

  • PlatformAffected.iOS | PlatformAffected.macOS correctly scopes the test to affected platforms; the bug is iOS/Mac only.

Looks Good

  • Fix location (WrapperView.LayoutSubviews()) is runs every layout pass, ensuring z-order is maintainedcorrect
  • Null-safe superview access (Superview?.)
  • Mirrors the existing BringSubviewToFront(_borderView) pattern in the same method
  • Test structure (WaitForElement + VerifyScreenshot) is appropriate for this visual bug
  • Screenshots in PR description clearly show before/after

None.

Gate Status

** Snapshot resolution mismatch prevented empirical validation (baseline: 1124Inconclusive2286, actual: 1206** 2472). The fix is reviewed and approved on code merits. Team should verify the iOS snapshot was captured on iPhone Xs as the standard CI device.

📋 Expand PR Finalization Review
Title: ✅ Good

Current: Fixed Stacklayout is not rendered when clip is applied and StackLayout placed child to the Border control in iOS/ Mac platform

Description: ✅ Good

  • Uses "Fixed" prefix — commit message titles should describe the change, not the action
  • Too verbose and awkward phrasing ("placed child to the Border control")
  • "Stacklayout" vs "StackLayout" — capitalization inconsistency
  • Platform is repeated awkwardly ("iOS/ Mac platform" with stray space)
  • Doesn't name the key type involved (WrapperView)
    Missing Elements:

**

  • The description title says "iOS/ Mac platform" but the fix is in WrapperView.cs, which is the shared iOS/MacCatalyst file. Worth noting MacCatalyst explicitly.

Overall verdict: The description is well-written and accurate. A recommended description is provided with minor improvements (title tweak, clarifications for future agents).

Phase 2: Code Review

See code-review.md for detailed findings.

Summary:

  • 🟡 1 medium concern: BringSubviewToFront(this) called on every LayoutSubviews() pass — broad behavioral change
  • 🟡 2 minor code quality issues in test files (indentation, missing newline)
  • ✅ Fix logic is correct and targeted

Recommended Changes

  1. Update PR title to: [iOS/Mac] WrapperView: Bring to front when clip is applied inside a Border
  2. Add missing newline at end of src/Controls/tests/TestCases.HostApp/Issues/Issue33241.cs
  3. Fix double-indentation in src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue33241.cs
  4. Consider whether BringSubviewToFront should be guarded to only run when a clip/geometry is applied (see code-review.md)

✨ Suggested PR Description

[!NOTE]
Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!

Root Cause

When a clip geometry (e.g., RoundRectangleGeometry) is applied to a MAUI view (e.g., StackLayout) that is a child of a Border with a Background, the platform wraps the clipped view in a WrapperView. On iOS/MacCatalyst, WrapperView is inserted into the Border's native subview hierarchy at index 0 (bottom of the z-order), placing it behind the Border's background layer. This makes the WrapperView's content invisible.

Description of Change

In WrapperView.LayoutSubviews(), an else branch was added: when no _borderView is present (i.e., the WrapperView itself is a content child, not a border host), the WrapperView calls this.Superview?.BringSubviewToFront(this) to move itself to the top of its parent's subview stack. This ensures the clipped content renders above the Border's background layer.

File changed: src/Core/src/Platform/iOS/WrapperView.cs

The existing _borderView path is unchanged — when WrapperView hosts a BorderView, it still calls BringSubviewToFront(_borderView) as before.

Issues Fixed

Fixes #33241

Platforms Tested

  • Android
  • Windows
  • iOS
  • Mac (MacCatalyst)

Code Review: ✅ Passed

Code Review — PR #33330

🟡 Medium Concern

BringSubviewToFront(this) called on every LayoutSubviews() pass

File: src/Core/src/Platform/iOS/WrapperView.cs Lines: ~105–108 (the new else branch)

else
{
    this.Superview?.BringSubviewToFront(this);
}

Problem: LayoutSubviews() is called on every layout pass (e.g., size change, rotation, parent relayout). The new else branch runs BringSubviewToFront(this) unconditionally every time — for all WrapperViews that don't have a _borderView, not just those with a clip applied.

This is a broader behavioral change than the fix requires. Specifically:

  • A WrapperView wraps views that need a clip, shadow, or border. Not all of these need to be at the front of their superview's z-order.
  • If any other code relies on a WrapperView being behind other sibling views, this change will silently break it.
  • Calling BringSubviewToFront is cheap but semantically significant — it permanently reorders subviews on every layout pass.

Recommendation: Consider guarding the BringSubviewToFront(this) call to only apply when a clip (MaskLayer) is present:

else if (MaskLayer is not null)
{
    this.Superview?.BringSubviewToFront(this);
}

This scopes the fix to only the cases where a clip geometry is being applied, which is the described root cause, rather than all WrapperViews without a border.

🟡 Minor Issues

Double-indentation in test file

File: src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue33241.cs

The constructor and members use two levels of indentation inside the class body, which appears to be an extra tab level:

public class Issue33241 : _IssuesUITest
{
		public Issue33241(TestDevice testDevice) : base(testDevice)  // ← extra indent
		{
		}

Should be single-level indentation consistent with other test files.

Missing newline at end of file

File: src/Controls/tests/TestCases.HostApp/Issues/Issue33241.cs

The diff shows \ No newline at end of file. C# source files should end with a newline.

Mixed indentation in HostApp file

File: src/Controls/tests/TestCases.HostApp/Issues/Issue33241.cs

The Issue33241() constructor body uses a mix of tabs and spaces for indentation (visible in the diff). The new Border { ... } initializer uses spaces while the rest of the file uses tabs.

✅ Looks Good

  • Fix logic is correct: The root cause (WrapperView inserted below Background layer) is correctly addressed by calling BringSubviewToFront.
  • Test coverage: UI tests added for iOS, Mac, and Android with screenshots.
  • No API surface changes: The fix is entirely internal to WrapperView.LayoutSubviews().
  • Existing _borderView path unchanged: The BringSubviewToFront(_borderView) call for the border case is unaffected.
  • The [Issue] attribute on the HostApp class correctly specifies PlatformAffected.iOS | PlatformAffected.macOS.

Modified the fix based on the Copilot suggestion.

@sheiksyedm
Copy link
Copy Markdown
Contributor

/azp run maui-pr-uitests

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented Mar 28, 2026

🚦 Gate - Test Before and After Fix

📊 Expand Full Gate9497d6a · added comments

Gate Result: ✅ PASSED

Platform: IOS · Base: main · Merge base: b43bdad1

Test Without Fix (expect FAIL) With Fix (expect PASS)
🖥️ Issue33241 Issue33241 ✅ FAIL — 212s ✅ PASS — 82s
🔴 Without fix — 🖥️ Issue33241: FAIL ✅ · 212s
  Determining projects to restore...
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/BindingSourceGen/Controls.BindingSourceGen.csproj (in 510 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Graphics/src/Graphics/Graphics.csproj (in 612 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Essentials/src/Essentials.csproj (in 14.05 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/Core/Controls.Core.csproj (in 14.29 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/Foldable/src/Controls.Foldable.csproj (in 14.28 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/Xaml/Controls.Xaml.csproj (in 14.31 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Core/src/Core.csproj (in 14.3 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj (in 14.34 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/Maps/src/Controls.Maps.csproj (in 14.34 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Core/maps/src/Maps.csproj (in 14.35 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/BlazorWebView/src/Maui/Microsoft.AspNetCore.Components.WebView.Maui.csproj (in 14.33 sec).
/Users/cloudtest/vss/_work/1/s/.dotnet/packs/Microsoft.iOS.Sdk.net10.0_26.0/26.0.11017/targets/Xamarin.Shared.Sdk.targets(309,3): warning : RuntimeIdentifier was set on the command line, and will override the value for RuntimeIdentifiers set in the project file. [/Users/cloudtest/vss/_work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-ios]
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13788322
  Graphics -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Graphics/Debug/net10.0-ios26.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13788322
  Essentials -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Essentials/Debug/net10.0-ios26.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13788322
  Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Core/Debug/net10.0-ios26.0/Microsoft.Maui.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13788322
  Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Maps/Debug/net10.0-ios26.0/Microsoft.Maui.Maps.dll
  Controls.BindingSourceGen -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13788322
  Controls.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13788322
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13788322
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13788322
  Microsoft.AspNetCore.Components.WebView.Maui -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Microsoft.AspNetCore.Components.WebView.Maui/Debug/net10.0-ios26.0/Microsoft.AspNetCore.Components.WebView.Maui.dll
  Controls.Xaml -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.Xaml.dll
  Controls.Foldable -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Foldable/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.Foldable.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13788322
  Controls.Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Maps/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.Maps.dll
  Detected signing identity:
    Code Signing Key: "" (-)
    Provisioning Profile: "" () - no entitlements
    Bundle Id: com.microsoft.maui.uitests
    App Id: com.microsoft.maui.uitests
  Controls.TestCases.HostApp -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-ios/iossimulator-arm64/Controls.TestCases.HostApp.dll
  Optimizing assemblies for size may change the behavior of the app. Be sure to test after publishing. See: https://aka.ms/dotnet-illink
  Optimizing assemblies for size. This process might take a while.

Build succeeded.

/Users/cloudtest/vss/_work/1/s/.dotnet/packs/Microsoft.iOS.Sdk.net10.0_26.0/26.0.11017/targets/Xamarin.Shared.Sdk.targets(309,3): warning : RuntimeIdentifier was set on the command line, and will override the value for RuntimeIdentifiers set in the project file. [/Users/cloudtest/vss/_work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-ios]
    1 Warning(s)
    0 Error(s)

Time Elapsed 00:01:37.78
  Determining projects to restore...
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/BindingSourceGen/Controls.BindingSourceGen.csproj (in 856 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Graphics/src/Graphics/Graphics.csproj (in 856 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/VisualTestUtils/VisualTestUtils.csproj (in 856 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/tests/CustomAttributes/Controls.CustomAttributes.csproj (in 856 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Essentials/src/Essentials.csproj (in 871 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/UITest.Core/UITest.Core.csproj (in 0.6 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Core/src/Core.csproj (in 934 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/Core/Controls.Core.csproj (in 949 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/UITest.NUnit/UITest.NUnit.csproj (in 1.93 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/UITest.Appium/UITest.Appium.csproj (in 2.06 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/UITest.Analyzers/UITest.Analyzers.csproj (in 2.49 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/TestUtils/src/VisualTestUtils.MagickNet/VisualTestUtils.MagickNet.csproj (in 7.4 sec).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/tests/TestCases.iOS.Tests/Controls.TestCases.iOS.Tests.csproj (in 8.32 sec).
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13788322
  Graphics -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
  Controls.CustomAttributes -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.CustomAttributes/Debug/net10.0/Controls.CustomAttributes.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13788322
  Essentials -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13788322
  Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Core/Debug/net10.0/Microsoft.Maui.dll
  Controls.BindingSourceGen -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13788322
  Controls.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
  UITest.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Core/Debug/net10.0/UITest.Core.dll
  UITest.NUnit -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.NUnit/Debug/net10.0/UITest.NUnit.dll
  VisualTestUtils -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/VisualTestUtils/Debug/netstandard2.0/VisualTestUtils.dll
  UITest.Appium -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Appium/Debug/net10.0/UITest.Appium.dll
  VisualTestUtils.MagickNet -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/VisualTestUtils.MagickNet/Debug/netstandard2.0/VisualTestUtils.MagickNet.dll
  UITest.Analyzers -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Analyzers/Debug/netstandard2.0/UITest.Analyzers.dll
  Controls.TestCases.iOS.Tests -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll
Test run for /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (arm64)

Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
/Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll
[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 10.0.0)
[xUnit.net 00:00:00.04]   Discovering: Controls.TestCases.iOS.Tests
[xUnit.net 00:00:00.13]   Discovered:  Controls.TestCases.iOS.Tests
NUnit Adapter 4.5.0.0: Test execution started
Running selected tests in /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll
   NUnit3TestExecutor discovered 1 of 1 NUnit test cases using Current Discovery mode, Non-Explicit run
>>>>> 4/9/2026 7:52:17 AM FixtureSetup for Issue33241(iOS)
>>>>> 4/9/2026 7:52:22 AM ClippedStackLayoutInsideBorderWithBackgroundRendersCorrectly Start
>>>>> 4/9/2026 7:52:24 AM ClippedStackLayoutInsideBorderWithBackgroundRendersCorrectly Stop
>>>>> 4/9/2026 7:52:24 AM Log types: syslog, crashlog, performance, safariConsole, safariNetwork, server
  Failed ClippedStackLayoutInsideBorderWithBackgroundRendersCorrectly [2 s]
  Error Message:
   VisualTestUtils.VisualTestFailedException : 
Snapshot different than baseline: ClippedStackLayoutInsideBorderWithBackgroundRendersCorrectly.png (20.89% difference)
If the correct baseline has changed (this isn't a a bug), then update the baseline image.
See test attachment or download the build artifacts to get the new snapshot file.

More info: https://aka.ms/visual-test-workflow

  Stack Trace:
     at VisualTestUtils.VisualRegressionTester.Fail(String message) in /_/src/TestUtils/src/VisualTestUtils/VisualRegressionTester.cs:line 162
   at VisualTestUtils.VisualRegressionTester.VerifyMatchesSnapshot(String name, ImageSnapshot actualImage, String environmentName, ITestContext testContext) in /_/src/TestUtils/src/VisualTestUtils/VisualRegressionTester.cs:line 123
   at Microsoft.Maui.TestCases.Tests.UITest.<VerifyScreenshot>g__Verify|13_0(String name, <>c__DisplayClass13_0&) in /_/src/Controls/tests/TestCases.Shared.Tests/UITest.cs:line 477
   at Microsoft.Maui.TestCases.Tests.UITest.VerifyScreenshot(String name, Nullable`1 retryDelay, Nullable`1 retryTimeout, Int32 cropLeft, Int32 cropRight, Int32 cropTop, Int32 cropBottom, Double tolerance) in /_/src/Controls/tests/TestCases.Shared.Tests/UITest.cs:line 309
   at Microsoft.Maui.TestCases.Tests.Issues.Issue33241.ClippedStackLayoutInsideBorderWithBackgroundRendersCorrectly() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue33241.cs:line 20
   at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
   at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)

NUnit Adapter 4.5.0.0: Test execution complete

Total tests: 1
     Failed: 1
Test Run Failed.
 Total time: 59.5844 Seconds

🟢 With fix — 🖥️ Issue33241: PASS ✅ · 82s
  Determining projects to restore...
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/BindingSourceGen/Controls.BindingSourceGen.csproj (in 360 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Graphics/src/Graphics/Graphics.csproj (in 375 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Essentials/src/Essentials.csproj (in 383 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/Core/Controls.Core.csproj (in 429 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Core/src/Core.csproj (in 442 ms).
  6 of 11 projects are up-to-date for restore.
/Users/cloudtest/vss/_work/1/s/.dotnet/packs/Microsoft.iOS.Sdk.net10.0_26.0/26.0.11017/targets/Xamarin.Shared.Sdk.targets(309,3): warning : RuntimeIdentifier was set on the command line, and will override the value for RuntimeIdentifiers set in the project file. [/Users/cloudtest/vss/_work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-ios]
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13788322
  Graphics -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Graphics/Debug/net10.0-ios26.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13788322
  Essentials -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Essentials/Debug/net10.0-ios26.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13788322
  Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Core/Debug/net10.0-ios26.0/Microsoft.Maui.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13788322
  Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Maps/Debug/net10.0-ios26.0/Microsoft.Maui.Maps.dll
  Controls.BindingSourceGen -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13788322
  Controls.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13788322
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13788322
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13788322
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13788322
  Microsoft.AspNetCore.Components.WebView.Maui -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Microsoft.AspNetCore.Components.WebView.Maui/Debug/net10.0-ios26.0/Microsoft.AspNetCore.Components.WebView.Maui.dll
  Controls.Maps -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Maps/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.Maps.dll
  Controls.Foldable -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Foldable/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.Foldable.dll
  Controls.Xaml -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0-ios26.0/Microsoft.Maui.Controls.Xaml.dll
  Detected signing identity:
    Code Signing Key: "" (-)
    Provisioning Profile: "" () - no entitlements
    Bundle Id: com.microsoft.maui.uitests
    App Id: com.microsoft.maui.uitests
  Controls.TestCases.HostApp -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-ios/iossimulator-arm64/Controls.TestCases.HostApp.dll
  Optimizing assemblies for size may change the behavior of the app. Be sure to test after publishing. See: https://aka.ms/dotnet-illink
  Optimizing assemblies for size. This process might take a while.

Build succeeded.

/Users/cloudtest/vss/_work/1/s/.dotnet/packs/Microsoft.iOS.Sdk.net10.0_26.0/26.0.11017/targets/Xamarin.Shared.Sdk.targets(309,3): warning : RuntimeIdentifier was set on the command line, and will override the value for RuntimeIdentifiers set in the project file. [/Users/cloudtest/vss/_work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-ios]
    1 Warning(s)
    0 Error(s)

Time Elapsed 00:00:42.02
  Determining projects to restore...
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/BindingSourceGen/Controls.BindingSourceGen.csproj (in 378 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Graphics/src/Graphics/Graphics.csproj (in 378 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Essentials/src/Essentials.csproj (in 387 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Controls/src/Core/Controls.Core.csproj (in 369 ms).
  Restored /Users/cloudtest/vss/_work/1/s/src/Core/src/Core.csproj (in 425 ms).
  8 of 13 projects are up-to-date for restore.
  Controls.CustomAttributes -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.CustomAttributes/Debug/net10.0/Controls.CustomAttributes.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13788322
  Graphics -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13788322
  Essentials -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13788322
  Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Core/Debug/net10.0/Microsoft.Maui.dll
  Controls.BindingSourceGen -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13788322
  Controls.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
  UITest.Core -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Core/Debug/net10.0/UITest.Core.dll
  VisualTestUtils -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/VisualTestUtils/Debug/netstandard2.0/VisualTestUtils.dll
  UITest.Appium -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Appium/Debug/net10.0/UITest.Appium.dll
  VisualTestUtils.MagickNet -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/VisualTestUtils.MagickNet/Debug/netstandard2.0/VisualTestUtils.MagickNet.dll
  UITest.NUnit -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.NUnit/Debug/net10.0/UITest.NUnit.dll
  UITest.Analyzers -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/UITest.Analyzers/Debug/netstandard2.0/UITest.Analyzers.dll
  Controls.TestCases.iOS.Tests -> /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll
Test run for /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (arm64)

Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
/Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll
[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 10.0.0)
[xUnit.net 00:00:00.04]   Discovering: Controls.TestCases.iOS.Tests
[xUnit.net 00:00:00.13]   Discovered:  Controls.TestCases.iOS.Tests
NUnit Adapter 4.5.0.0: Test execution started
Running selected tests in /Users/cloudtest/vss/_work/1/s/artifacts/bin/Controls.TestCases.iOS.Tests/Debug/net10.0/Controls.TestCases.iOS.Tests.dll
   NUnit3TestExecutor discovered 1 of 1 NUnit test cases using Current Discovery mode, Non-Explicit run
>>>>> 4/9/2026 7:53:42 AM FixtureSetup for Issue33241(iOS)
>>>>> 4/9/2026 7:53:47 AM ClippedStackLayoutInsideBorderWithBackgroundRendersCorrectly Start
>>>>> 4/9/2026 7:53:47 AM ClippedStackLayoutInsideBorderWithBackgroundRendersCorrectly Stop
  Passed ClippedStackLayoutInsideBorderWithBackgroundRendersCorrectly [517 ms]
NUnit Adapter 4.5.0.0: Test execution complete

Test Run Successful.
Total tests: 1
     Passed: 1
 Total time: 16.9604 Seconds

📁 Fix files reverted (3 files)
  • eng/pipelines/ci-copilot.yml
  • src/Core/src/Platform/iOS/LayerExtensions.cs
  • src/Core/src/Platform/iOS/WrapperView.cs

@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented Mar 28, 2026

🤖 AI Summary

📊 Expand Full Review9497d6a · added comments
🔍 Pre-Flight — Context & Validation

Issue: #33241 - [Mac/iOS] StackLayout fails to render content while applying Clip, and the layout is placed inside a Border with Background
PR: #33330 - Fixed StackLayout is not rendered when clip is applied and StackLayout placed child to the Border control in iOS/Mac platform
Platforms Affected: iOS, macOS (fix in iOS-only platform code via LayerExtensions.cs / WrapperView.cs)
Files Changed: 2 implementation, 6 test (4 snapshot images + 2 C# test files)

Key Findings

  • Root Cause: When a Clip is applied to a StackLayout inside a Border, the StackLayout's WrapperView is inserted at z-index 0 into the Border's subview stack, placing it below the Border's background CALayer, making the child invisible.
  • Fix approach: LayerExtensions.InsertBackgroundLayer() now sets backgroundLayer.ZPosition = -1 before insertion, ensuring the background CALayer always renders behind subview layers regardless of UIKit reorganization during layout passes.
  • WrapperView.cs change is purely cosmetic: Adds braces around BringSubviewToFront(_borderView) and removes a blank line — no behavioral change.
  • Prior review feedback addressed: Original PR used Superview?.BringSubviewToFront(this) on the WrapperView (flagged as breaking sibling z-order). Updated to use ZPosition = -1 on the background layer instead.
  • Test method name: Properly renamed to ClippedStackLayoutInsideBorderWithBackgroundRendersCorrectly (was previously Issue33241Test).
  • WinUI snapshot added: PR includes ClippedStackLayoutInsideBorderWithBackgroundRendersCorrectly.png for WinUI, addressing prior reviewer concern.
  • One open unresolved review thread: The old WinUI snapshot thread (referencing Issue33241Test.png) is marked is_resolved: false but the underlying concern is addressed (snapshot added with correct name).
  • Test type: UI Test (screenshot baseline comparison)
  • Gate: ✅ PASSED — tests FAIL without fix, PASS with fix on iOS

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #33330 Set backgroundLayer.ZPosition = -1 in InsertBackgroundLayer() ✅ PASSED (Gate) LayerExtensions.cs, WrapperView.cs (cosmetic) Original PR

🔧 Fix — Analysis & Comparison

Fix Candidates

# Source Approach Test Result Files Changed Notes
1 try-fix (claude-opus-4.6) Reorder parent background CALayer in PASS WrapperView.cs (+31 lines) Reactive fix each layout pass; more complex than PR fix
2 try-fix (claude-sonnet-4.6) Set in PASS ViewHandlerOfT.iOS.cs (+10 lines) Raises WrapperView above background; affects all containers globally
3 try-fix (gpt-5.3-codex) Add extension called from PASS LayerExtensions.cs, MauiView.cs (+~15 lines) Layout-time reorder from parent side; runs every layout pass
4 try-fix (gpt-5.4) Reinsert WrapperView layer above parent background layer from without ZPosition PASS LayerExtensions.cs, WrapperView.cs, ViewHandlerOfT.iOS.cs (+~15 lines) 3 files changed; more invasive
PR PR #33330 Set in PASSED (Gate) LayerExtensions.cs (+6 lines), WrapperView.cs (cosmetic) Single targeted change at root cause

Cross-Pollination

Model Round New Ideas? Details
claude-opus-4.6 2 No NO NEW solution space exhausted
claude-sonnet-4.6 2 Yes Use layer.backgroundColor directly for solid colors (no competing architectural change, out of scope for this fix
gpt-5.3-codex 2 Yes Split Border into background host + content host sibling large architectural refactor, out of scope
gpt-5.4 2 Yes Use WrapperView's root layer for rendering instead of background architectural refactor, out of scope

Exhausted: Yes (all 4 models queried; cross-poll ideas are architectural refactors out of scope)
Selected Fix: PR's Set backgroundLayer.ZPosition = -1 in InsertBackgroundLayer()fix

Reason: All 5 approaches pass the test, but the PR's fix is the best choice:

  1. Minimal 1 meaningful line in 1 focused filechange
  2. Root cause Fixes where the background layer is inserted/configuredlocation
  3. No runtime Done once at layer creation, not every layout pass (unlike attempts 1, 3)overhead
  4. Standard iOS ZPosition = -1 is the canonical way to keep a layer behind all content layersidiom
  5. No global side Does not change z-order of other views/layers (unlike attempt 2)effects

📋 Report — Final Recommendation

✅ Final Recommendation: APPROVE

Phase Status

Phase Status Notes
Pre-Flight ✅ COMPLETE Issue #33241 — iOS/macOS StackLayout clipped + inside Border with Background
Gate ✅ PASSED iOS — tests FAIL without fix, PASS with fix
Try-Fix ✅ COMPLETE 4 attempts, all 4 passing; PR's fix selected as best
Report ✅ COMPLETE

Selected Fix: PR's fix (see try-fix for comparison table)


Summary

PR #33330 fixes a rendering bug where a StackLayout with a Clip becomes invisible when placed inside a Border with a Background on iOS/macOS. The fix is correct, minimal, and verified by the gate. All four try-fix attempts found alternative solutions, confirming the fix addresses the root cause, but the PR's approach is the cleanest.

Prior review concerns have been addressed: the original Superview?.BringSubviewToFront(this) approach (which incorrectly reordered sibling subviews) was replaced with a ZPosition-based fix, the test method was renamed descriptively, and snapshots for all platforms (iOS, iOS-26, Android, WinUI) were added.


Root Cause

When Clip is set on a StackLayout inside a Border, MAUI wraps the StackLayout in a WrapperView container and inserts it as a subview into the Border. The Border already has a background CALayer inserted at sublayer index 0 via InsertBackgroundLayer(). When UIKit adds the WrapperView as a subview, it places the WrapperView's backing CALayer at sublayer index 0, pushing the existing background CALayer to sublayer index 1. Since both layers have the same default ZPosition = 0, Core Animation renders them in sublayer array order — the background layer at index 1 ends up rendered on top of the WrapperView's content, making the StackLayout invisible.


Fix Quality

The fix: Sets backgroundLayer.ZPosition = -1 in LayerExtensions.InsertBackgroundLayer() before adding the layer to the hierarchy.

Assessment: ✅ Excellent

Criterion Assessment
Minimal change ✅ 1 meaningful line in 1 file
Root cause location ✅ Fixes at layer creation/insertion site
Runtime overhead ✅ None — applied once at setup, not per layout pass
iOS idiom ✅ Standard — ZPosition = -1 is the canonical background-behind-content pattern
Side effects ✅ None — background layers are always supposed to be behind content
Cross-platform safety ✅ iOS/macOS only (file uses UIKit APIs)

WrapperView.cs change is cosmetic only (adds braces, removes blank line) — no behavioral change.


Minor Issues (Non-blocking)

  1. Missing newline at end of fileTestCases.HostApp/Issues/Issue33241.cs is missing a trailing newline (No newline at end of file)
  2. Inconsistent indentationIssue33241.cs mixes tabs and spaces in the Border/Content initializer block (lines 13–24 use inconsistent mixed indentation)
  3. Test class double-indentationIssue33241 test class members are indented with 2 extra tabs (appears to be a formatting oversight)
  4. One unresolved review thread — The WinUI snapshot thread from a prior review was marked "not resolved" but the concern is addressed (snapshot ClippedStackLayoutInsideBorderWithBackgroundRendersCorrectly.png IS present for WinUI)

These are minor formatting issues that can be fixed in a follow-up or as part of formatting tooling. They do not affect correctness.


@MauiBot MauiBot added s/agent-review-incomplete and removed s/agent-approved AI agent recommends approval - PR fix is correct and optimal labels Mar 28, 2026
@MauiBot MauiBot added s/agent-changes-requested AI agent recommends changes - found a better alternative or issues and removed s/agent-review-incomplete labels Apr 3, 2026
Copy link
Copy Markdown
Contributor

@kubaflo kubaflo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please review the AI's summary?

@KarthikRajaKalaimani
Copy link
Copy Markdown
Contributor Author

Could you please review the AI's summary?

Addressed AI Summary concerns

@MauiBot MauiBot added s/agent-approved AI agent recommends approval - PR fix is correct and optimal and removed s/agent-changes-requested AI agent recommends changes - found a better alternative or issues labels Apr 9, 2026
@kubaflo kubaflo changed the base branch from main to inflight/current April 10, 2026 09:47
@kubaflo kubaflo merged commit 2cea25c into dotnet:inflight/current Apr 10, 2026
36 checks passed
PureWeen pushed a commit that referenced this pull request Apr 14, 2026
…t placed child to the Border control in iOS/ Mac platform (#33330)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Issue Details:

Stacklayout is not rendered when clip is applied and StackLayout placed
child to the Border control in iOS/ Mac platform.
       
### Root Cause:

When the clip is applied to the StackLayout, its ContainerView
(WrapperView) is being inserted at index 0 to its parent control Border,
which places it below Border's background layer in the z-order. As a
result, the stacklayout is not visible in the view in iOS and Mac
platform.

### Description of Change:

The wrapper view is brought to the front of its parent’s subview stack
so it renders above the Border background in the Z order.

**Tested the behavior in the following platforms.**

- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Reference:

N/A

### Issues Fixed:

Fixes  #33241    

### Screenshots
| Before  | After  |
|---------|--------|
| <img width="369" height="606" alt="image"
src="https://github.com/user-attachments/assets/0be8bc27-5de4-41ad-a41f-92581513ac55"
/> | <img width="369" height="606" alt="image"
src="https://github.com/user-attachments/assets/6a3590f6-2763-473a-aa91-ee1113e48ec3"
/> |
devanathan-vaithiyanathan pushed a commit to Tamilarasan-Paranthaman/maui that referenced this pull request Apr 21, 2026
…t placed child to the Border control in iOS/ Mac platform (dotnet#33330)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Issue Details:

Stacklayout is not rendered when clip is applied and StackLayout placed
child to the Border control in iOS/ Mac platform.
       
### Root Cause:

When the clip is applied to the StackLayout, its ContainerView
(WrapperView) is being inserted at index 0 to its parent control Border,
which places it below Border's background layer in the z-order. As a
result, the stacklayout is not visible in the view in iOS and Mac
platform.

### Description of Change:

The wrapper view is brought to the front of its parent’s subview stack
so it renders above the Border background in the Z order.

**Tested the behavior in the following platforms.**

- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Reference:

N/A

### Issues Fixed:

Fixes  dotnet#33241    

### Screenshots
| Before  | After  |
|---------|--------|
| <img width="369" height="606" alt="image"
src="https://github.com/user-attachments/assets/0be8bc27-5de4-41ad-a41f-92581513ac55"
/> | <img width="369" height="606" alt="image"
src="https://github.com/user-attachments/assets/6a3590f6-2763-473a-aa91-ee1113e48ec3"
/> |
PureWeen pushed a commit that referenced this pull request Apr 22, 2026
…t placed child to the Border control in iOS/ Mac platform (#33330)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Issue Details:

Stacklayout is not rendered when clip is applied and StackLayout placed
child to the Border control in iOS/ Mac platform.
       
### Root Cause:

When the clip is applied to the StackLayout, its ContainerView
(WrapperView) is being inserted at index 0 to its parent control Border,
which places it below Border's background layer in the z-order. As a
result, the stacklayout is not visible in the view in iOS and Mac
platform.

### Description of Change:

The wrapper view is brought to the front of its parent’s subview stack
so it renders above the Border background in the Z order.

**Tested the behavior in the following platforms.**

- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Reference:

N/A

### Issues Fixed:

Fixes  #33241    

### Screenshots
| Before  | After  |
|---------|--------|
| <img width="369" height="606" alt="image"
src="https://github.com/user-attachments/assets/0be8bc27-5de4-41ad-a41f-92581513ac55"
/> | <img width="369" height="606" alt="image"
src="https://github.com/user-attachments/assets/6a3590f6-2763-473a-aa91-ee1113e48ec3"
/> |
PureWeen pushed a commit that referenced this pull request Apr 28, 2026
…t placed child to the Border control in iOS/ Mac platform (#33330)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Issue Details:

Stacklayout is not rendered when clip is applied and StackLayout placed
child to the Border control in iOS/ Mac platform.
       
### Root Cause:

When the clip is applied to the StackLayout, its ContainerView
(WrapperView) is being inserted at index 0 to its parent control Border,
which places it below Border's background layer in the z-order. As a
result, the stacklayout is not visible in the view in iOS and Mac
platform.

### Description of Change:

The wrapper view is brought to the front of its parent’s subview stack
so it renders above the Border background in the Z order.

**Tested the behavior in the following platforms.**

- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Reference:

N/A

### Issues Fixed:

Fixes  #33241    

### Screenshots
| Before  | After  |
|---------|--------|
| <img width="369" height="606" alt="image"
src="https://github.com/user-attachments/assets/0be8bc27-5de4-41ad-a41f-92581513ac55"
/> | <img width="369" height="606" alt="image"
src="https://github.com/user-attachments/assets/6a3590f6-2763-473a-aa91-ee1113e48ec3"
/> |
PureWeen pushed a commit that referenced this pull request Apr 29, 2026
…t placed child to the Border control in iOS/ Mac platform (#33330)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Issue Details:

Stacklayout is not rendered when clip is applied and StackLayout placed
child to the Border control in iOS/ Mac platform.
       
### Root Cause:

When the clip is applied to the StackLayout, its ContainerView
(WrapperView) is being inserted at index 0 to its parent control Border,
which places it below Border's background layer in the z-order. As a
result, the stacklayout is not visible in the view in iOS and Mac
platform.

### Description of Change:

The wrapper view is brought to the front of its parent’s subview stack
so it renders above the Border background in the Z order.

**Tested the behavior in the following platforms.**

- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Reference:

N/A

### Issues Fixed:

Fixes  #33241    

### Screenshots
| Before  | After  |
|---------|--------|
| <img width="369" height="606" alt="image"
src="https://github.com/user-attachments/assets/0be8bc27-5de4-41ad-a41f-92581513ac55"
/> | <img width="369" height="606" alt="image"
src="https://github.com/user-attachments/assets/6a3590f6-2763-473a-aa91-ee1113e48ec3"
/> |
github-actions Bot pushed a commit that referenced this pull request May 6, 2026
…t placed child to the Border control in iOS/ Mac platform (#33330)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Issue Details:

Stacklayout is not rendered when clip is applied and StackLayout placed
child to the Border control in iOS/ Mac platform.
       
### Root Cause:

When the clip is applied to the StackLayout, its ContainerView
(WrapperView) is being inserted at index 0 to its parent control Border,
which places it below Border's background layer in the z-order. As a
result, the stacklayout is not visible in the view in iOS and Mac
platform.

### Description of Change:

The wrapper view is brought to the front of its parent’s subview stack
so it renders above the Border background in the Z order.

**Tested the behavior in the following platforms.**

- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Reference:

N/A

### Issues Fixed:

Fixes  #33241    

### Screenshots
| Before  | After  |
|---------|--------|
| <img width="369" height="606" alt="image"
src="https://github.com/user-attachments/assets/0be8bc27-5de4-41ad-a41f-92581513ac55"
/> | <img width="369" height="606" alt="image"
src="https://github.com/user-attachments/assets/6a3590f6-2763-473a-aa91-ee1113e48ec3"
/> |
@github-actions github-actions Bot locked and limited conversation to collaborators May 11, 2026
@kubaflo kubaflo added the s/agent-gate-passed AI verified tests catch the bug (fail without fix, pass with fix) label May 20, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-layout StackLayout, GridLayout, ContentView, AbsoluteLayout, FlexLayout, ContentPresenter community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration platform/android platform/ios s/agent-approved AI agent recommends approval - PR fix is correct and optimal s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates s/agent-gate-passed AI verified tests catch the bug (fail without fix, pass with fix) s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Mac/iOS] StackLayout fails to render content while applying Clip, and the layout is placed inside a Border with Background in .NET MAUI

7 participants