Skip to content

Nested Flex Layouts#25036

Closed
kubaflo wants to merge 3 commits intodotnet:inflight/currentfrom
kubaflo:fix-20461
Closed

Nested Flex Layouts#25036
kubaflo wants to merge 3 commits intodotnet:inflight/currentfrom
kubaflo:fix-20461

Conversation

@kubaflo
Copy link
Copy Markdown
Contributor

@kubaflo kubaflo commented Oct 1, 2024

Description of Change

I'm considering whether this change might have any unforeseen implications. At present, it seems safe because flex layouts nested inside other flex layouts aren't functioning as expected at all and this change only affects this situation

Issues Fixed

Fixes: #24653
Fixes: #20461
Fixes #26013

Before After

@kubaflo kubaflo requested a review from a team as a code owner October 1, 2024 18:36
@dotnet-policy-service dotnet-policy-service bot added the community ✨ Community Contribution label Oct 1, 2024
@dotnet-policy-service
Copy link
Copy Markdown
Contributor

Hey there @kubaflo! Thank you so much for your PR! Someone from the team will get assigned to your PR shortly and we'll get it reviewed.

@jfversluis
Copy link
Copy Markdown
Member

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 3 pipeline(s).

@MartyIX
Copy link
Copy Markdown
Contributor

MartyIX commented Oct 5, 2024

btw: Windows image looks very different than others. Just to be clear, is that a bug or not?

@kubaflo
Copy link
Copy Markdown
Contributor Author

kubaflo commented Oct 5, 2024

btw: Windows image looks very different than others. Just to be clear, is that a bug or not?

Hmm I’m not sure. Could you maybe have a look at this please?

@MartyIX
Copy link
Copy Markdown
Contributor

MartyIX commented Oct 5, 2024

I can see:

image

and without your first commit (2a43d95) it looks like this:

image

@kubaflo
Copy link
Copy Markdown
Contributor Author

kubaflo commented Oct 5, 2024

I can see:

image

and without your first commit (2a43d95) it looks like this:

image

I think without my commit it looks very wrong. On iOS and Android, everything looks as expected, I think Windows might need some adjustment, but I don't have a Windows machine to work on it. Thanks for sending screenshots!

I think only this part doesn't work on Windows, but maybe it is how it is supposed to be.
Screenshot 2024-10-05 at 17 05 43

@jsuarezruiz
Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 3 pipeline(s).

@jsuarezruiz
Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 3 pipeline(s).

@jfversluis jfversluis added the area-layout StackLayout, GridLayout, ContentView, AbsoluteLayout, FlexLayout, ContentPresenter label Dec 9, 2024
@kubaflo kubaflo self-assigned this Mar 16, 2025
Copilot AI review requested due to automatic review settings March 8, 2026 10:48
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 8, 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 -- 25036

Or

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

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

This PR fixes nested FlexLayout rendering, which was completely broken — nested flex layouts had zero size and their children (including images, image buttons, and background colors) were not rendered. The root cause was that AddFlexItem() tried to reuse a child FlexLayout's internal _root Flex.Item as the item in the parent flex tree, which caused the child's Layout() method to short-circuit (because _root.Parent != null indicated it was a non-root node and skipped layout entirely). The fix always creates a fresh Flex.Item for each child—including nested FlexLayout children—and assigns a SelfSizing callback to measure through the standard child.Measure() path for all children.

Changes:

  • Core fix in FlexLayout.cs: Remove the special-case path that reused a child FlexLayout's _root as the flex item; instead always create a new Flex.Item with a SelfSizing callback for all children
  • New UI test host page (Issue20461.xaml / .xaml.cs): Reproduces the nested flex layout scenario with images, image buttons, and multiple nesting levels
  • New NUnit test and snapshot baselines for Android and Windows (iOS snapshot also present)

Reviewed changes

Copilot reviewed 4 out of 7 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/Controls/src/Core/Layout/FlexLayout.cs Core fix: removes reuse of child FlexLayout's _root, always creates a new Flex.Item for all children
src/Controls/tests/TestCases.HostApp/Issues/Issue20461.xaml UI test page reproducing nested FlexLayouts with images and image buttons
src/Controls/tests/TestCases.HostApp/Issues/Issue20461.xaml.cs Code-behind for the test page
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue20461.cs NUnit test that waits for nested elements and verifies the screenshot
src/Controls/tests/TestCases.Android.Tests/snapshots/android/NestedFlexLayoutShouldRenderCorrectly.png Android baseline snapshot
src/Controls/tests/TestCases.WinUI.Tests/snapshots/windows/NestedFlexLayoutShouldRenderCorrectly.png Windows baseline snapshot

PureWeen pushed a commit that referenced this pull request Mar 11, 2026
The Copilot reviewer agent on PR #25036 (Nested Flex Layouts) ran 5
try-fix attempts across models and hit the 180-minute timeout during
Round 2 cross-pollination. Doubling to 360 minutes to accommodate
complex PRs that need multiple fix attempts.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented Mar 22, 2026

🤖 AI Summary

📊 Expand Full Review00cb2d4 · Removed checking if child is FlexLayout
🔍 Pre-Flight — Context & Validation

Issue: #20461 - Nested FlexLayouts don't show BackgroundColor
PR: #25036 - Nested Flex Layouts
Platforms Affected: Android primarily; linked reports also cover iOS and Windows concerns
Files Changed: 1 implementation, 6 test/support

Key Findings

  • PR links three related issues: Nested FlexLayouts don't show BackgroundColor #20461 (nested FlexLayout background colors), Image Button in a nested flex layout not rendering #24653 (nested FlexLayout image button not rendering), and Nested FlexLayout not working #26013 (nested FlexLayout content not displaying on Android).
  • The implementation change is isolated to src/Controls/src/Core/Layout/FlexLayout.cs; the PR replaces reuse of a nested FlexLayout's internal root item with a fresh Flex.Item per child and keeps self-sizing behavior on the created item.
  • Test coverage was added through HostApp/UI test assets for Issue20461, including Android/iOS/Windows snapshots and a shared UI test NestedFlexLayoutShouldRenderCorrectly.
  • PR discussion highlights an unresolved edge case on Windows: maintainers noted Windows visuals differ from Android/iOS, and the author acknowledged they could not validate Windows locally.
  • No prior agent review comment with phase status markers was found in PR comments.

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #25036 Stop reusing a nested FlexLayout's internal _root; create a dedicated Flex.Item for each child and attach self-sizing to that item so nested layouts measure/render independently. ⏳ PENDING (Gate) src/Controls/src/Core/Layout/FlexLayout.cs Original PR; linked UI test uses Issue20461

🚦 Gate — Test Verification

Gate Result: ✅ PASSED

Platform: android
Mode: Full Verification

  • Tests FAIL without fix: ✅
  • Tests PASS with fix: ✅

🔧 Fix — Analysis & Comparison

Fix Candidates

# Source Approach Test Result Files Changed Notes
1 try-fix Lazily rebuild nested FlexLayout roots during layout and install a sizing proxy on the captured parent item. ❌ FAIL 1 file Rendered content but screenshot still differed by 6.90% on first-pass geometry.
2 try-fix Repair nested FlexLayout parent-child item associations in PopulateLayout / OnParentSet so nested layouts get a proxy parent item with SelfSizing, without changing AddFlexItem. ✅ PASS 1 file Passed Android Issue20461; substantially larger change (+226/-73).
3 try-fix Keep nested root reuse but always attach SelfSizing to the inserted item. ❌ FAIL 1 file Smaller idea, but insufficient; Android Issue20461 still failed.
4 try-fix Child-managed FlexItemProxy for nested FlexLayout instances. ⚠️ BLOCKED 1 file Partial artifacts only; temp-clone/app-launch contamination prevented trustworthy validation.
5 try-fix Parent-local child→Flex.Item ownership map so each parent tracks its inserted wrapper item explicitly. ✅ PASS 1 file Passed Android Issue20461; near-PR size (+34/-30) but adds ownership-map complexity.
PR PR #25036 Create a dedicated Flex.Item for each child in AddFlexItem and attach self-sizing there. ✅ PASSED (Gate) 1 file Original PR; Android gate passed; smallest passing implementation (+26/-29).

Cross-Pollination

Model Round New Ideas? Details
claude-opus-4.6 1 Yes Lazy root rebuild/proxy sizing attempt executed.
claude-sonnet-4.6 1 Yes PopulateLayout/OnParentSet repair path passed.
gpt-5.3-codex 1 Yes SelfSizing-on-reused-root attempt executed and failed.
gemini-3-pro-preview 1 Yes Child-managed proxy concept proposed, but execution was blocked by temp clone contamination.
claude-opus-4.6 2 No NO NEW IDEAS
claude-sonnet-4.6 2 No NO NEW IDEAS
gpt-5.3-codex 2 Yes NEW IDEA: parent-local child→item ownership map
gemini-3-pro-preview 2 No NO NEW IDEAS
claude-opus-4.6 3 No NO NEW IDEAS
claude-sonnet-4.6 3 No NO NEW IDEAS
gpt-5.3-codex 3 No NO NEW IDEAS
gemini-3-pro-preview 3 No NO NEW IDEAS

Passing Candidate Comparison

Candidate Result Approx. Size Strengths Tradeoffs
PR ✅ PASS +26/-29 Smallest passing change; fixes root cause at item creation point; easy to reason about None observed on Android; Windows concern remains only in PR discussion, not this test run
#2 ✅ PASS +226/-73 Explicitly handles multiple initialization paths Much larger and more complex than needed
#5 ✅ PASS +34/-30 Also small; explicit parent ownership model Adds state-tracking complexity beyond the PR need

Exhausted: Yes
Selected Fix: PR #25036 — All passing solutions converge on the same invariant: nested FlexLayout must participate as a measured leaf in the parent tree via a separate parent-owned item. The PR implements that invariant with the smallest, clearest passing change.


📋 Report — Final Recommendation

✅ Final Recommendation: APPROVE

Phase Status

Phase Status Notes
Pre-Flight ✅ COMPLETE Linked issues and PR discussion reviewed; Windows concern noted from comments.
Gate ✅ PASSED Android full verification: tests fail without fix and pass with fix.
Try-Fix ✅ COMPLETE 5 attempts total, 2 alternative passes, design space exhausted.
Report ✅ COMPLETE

Summary

PR #25036 fixes the nested FlexLayout rendering bug on Android with valid UI coverage. The gate verified the added Issue20461 test actually fails on the broken baseline and passes with the PR fix. I then ran the mandatory try-fix exploration across four model families plus follow-up rounds; while two independent alternatives also passed, the PR’s implementation was the smallest and clearest passing solution.

Root Cause

The bug comes from nested FlexLayout ownership of Flex.Item state. Reusing a child FlexLayout's internal _root as the parent-owned flex item lets the parent and child trees interfere with each other. Passing fixes all separate those responsibilities so the nested layout is measured as a leaf in the parent tree while keeping its own _root internal.

Fix Quality

The PR addresses the root cause directly in AddFlexItem by ensuring the parent uses a dedicated wrapper Flex.Item with SelfSizing. Compared with the passing alternatives, it achieves the same correct invariant with less code and less state-management complexity. Based on Android verification, this is the best fix among the candidates explored.


@MauiBot MauiBot added 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-reviewed PR was reviewed by AI agent workflow (full 4-phase review) labels Mar 22, 2026
@kubaflo
Copy link
Copy Markdown
Contributor Author

kubaflo commented Mar 22, 2026

/azp run maui-pr-uitests

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@kubaflo
Copy link
Copy Markdown
Contributor Author

kubaflo commented Mar 22, 2026

/azp run maui-pr-devicetests

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@kubaflo kubaflo changed the base branch from main to inflight/current March 24, 2026 16:36
@kubaflo kubaflo closed this Mar 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-layout StackLayout, GridLayout, ContentView, AbsoluteLayout, FlexLayout, ContentPresenter community ✨ Community Contribution layout-flex FlexLayout issues 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-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.

Nested FlexLayout not working Image Button in a nested flex layout not rendering Nested FlexLayouts don't show BackgroundColor

6 participants