Fix FlexLayout Grow causes measured child sizes to be ignored#34535
Fix FlexLayout Grow causes measured child sizes to be ignored#34535kubaflo merged 5 commits intodotnet:inflight/currentfrom
Conversation
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 34535Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 34535" |
|
/azp run maui-pr-uitests , maui-pr-devicetests |
|
Azure Pipelines successfully started running 2 pipeline(s). |
There was a problem hiding this comment.
Pull request overview
Fixes FlexLayout’s flex-grow sizing so that grow distribution uses only available free space and preserves measured child sizes, addressing incorrect item sizing reported in #34464.
Changes:
- Update flex-grow calculation to distribute only free space (container minus measured grow-item sizes).
- Preserve intrinsic/measured size for growing children rather than resetting to zero.
- Add a new UI test + host repro page for issue #34464.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| src/Core/src/Layouts/Flex.cs | Adjusts grow sizing math to use free space and keep measured sizes. |
| src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34464.cs | Adds UI test coverage for the reported layout issue. |
| src/Controls/tests/TestCases.HostApp/Issues/Issue34464.cs | Adds a host app repro page for issue #34464. |
🤖 AI Summary📊 Expand Full Review —
|
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #34535 | Compute free space as flex_dim - extra_flex_dim, distribute only that free space to growing items, and preserve each item's measured size during PENDING (Gate) |
src/Core/src/Layouts/Flex.cs, src/Controls/tests/Core.UnitTests/Layouts/FlexLayoutTests.cs, src/Controls/tests/TestCases.HostApp/Issues/Issue34464.cs, src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34464.cs |
Original PR; adds both unit and UI validation. | growth. |
Issue: #34464 - FlexLayout Grow causes measured child sizes to be ignored
PR: #34535 - Fix FlexLayout Grow causes measured child sizes to be ignored
Platforms Affected: Android, iOS, MacCatalyst/macOS, Windows
Files Changed: 1 implementation, 7 test/support
Key Findings
- The issue reports that
FlexLayout.Growcurrently replaces each growing item's measured main-axis size instead of adding only its share of remaining free space, which clips larger content and diverges from CSS flexbox behavior. - The issue body includes a concrete numeric repro and points to
src/Core/src/Layouts/Flex.csas the problematic logic; triage later validated the bug across Android, iOS, MacCatalyst, and Windows. - This PR changes one runtime file, adds a focused unit test in
src/Controls/tests/Core.UnitTests/Layouts/FlexLayoutTests.cs, adds a HostApp repro page plus a shared UI test for issue34464, and includes snapshot baselines for Android, iOS, Mac, and Windows. - Prior inline review feedback flagged two important concerns:
freeSpaceshould not go negative in the grow path, and the new UI test waits only forHeaderLabel, which may not guarantee the BindableLayout-generated children are realized before the screenshot is captured. - Prior agent review on this PR failed Gate on MacCatalyst because the new Mac screenshot baseline was missing at that time; the current PR file list now includes the requested snapshot assets, so Android gate verification is still required.
- Edge-case context from the issue suggests the regression is most visible when items with very different measured widths share a flex line; the reporter also suspects overlap with issues FlexLayout.Grow="1" text cuts off instead of line break on Windows #22371 and FlexLayout misbehaves when Label content has long .Text #28165.
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #34535 | Compute free space as flex_dim - extra_flex_dim, distribute only that free space to grow items, and preserve measured child sizes during growth. |
⏳ PENDING (Gate) | src/Core/src/Layouts/Flex.cs, src/Controls/tests/Core.UnitTests/Layouts/FlexLayoutTests.cs, src/Controls/tests/TestCases.HostApp/Issues/Issue34464.cs, src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34464.cs, snapshot files |
Original PR; adds both unit and UI coverage. |
🚦 Gate — Test Verification
Gate FAILEDResult:
Platform: catalyst
Mode: Full Verification
- Tests FAIL without fix:
- Tests PASS with fix:
Evidence
- Verification on MacCatalyst confirmed the new test detects a failure without the PR fix.
- Verification with the PR fix still failed because the screenshot baseline
FlexLayoutWithBindableLayoutDisplaysLabels.pngwas not available for the Mac test run. - This means the gate cannot validate a PASS-with-fix result on the requested platform.
Gate Result: ✅ PASSED
Result: ✅ PASSED
Platform: android
Mode: Full Verification
- Tests FAIL without fix: ✅
- Tests PASS with fix: ✅
Evidence
verify-tests-fail-without-fixcompleted full verification successfully forIssue34464on Android.- The generated verification report records
FAILwithout fix andPASSwith fix. - Android device logs show the HostApp launching and Appium reaching
HeaderLabel, which is consistent with the successful fix-side UI verification. - The verification report also captured a transient
ADB0010install failure during the broken-baseline run before succeeding on retry; the overall gate result remained✅ PASSED.
🔧 Fix — Analysis & Comparison
Gate FAILEDResult:
Platform: catalyst
Mode: Full Verification
- Tests FAIL without fix:
- Tests PASS with fix:
Evidence
- Verification on MacCatalyst confirmed the new test detects a failure without the PR fix.
- Verification with the PR fix still failed because the screenshot baseline
FlexLayoutWithBindableLayoutDisplaysLabels.pngwas not available for the Mac test run. - This means the gate cannot validate a PASS-with-fix result on the requested platform.
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| 1 | try-fix / claude-opus-4.6 | Prevent layout.flex_dim inflation when grow items exist, so it already represents true free space; preserve measured size by not zeroing the frame. |
✅ PASS | src/Core/src/Layouts/Flex.cs |
Simple and correct, but changes upstream accounting behavior. |
| 2 | try-fix / claude-sonnet-4.6 | Snapshot layout.flex_dim before inflation and use the snapshot in grow calculations while preserving measured size. |
✅ PASS | src/Core/src/Layouts/Flex.cs |
Small local-state alternative; same core math. |
| 3 | try-fix / gpt-5.3-codex | Leave inflated layout.flex_dim intact and subtract each child's proportional share of layout.extra_flex_dim directly in the grow formula. |
✅ PASS | src/Core/src/Layouts/Flex.cs |
Correct but less readable. |
| 4 | try-fix / gemini-3-pro-preview | Disable inflation for grow scenarios and preserve measured child size. | ✅ PASS | src/Core/src/Layouts/Flex.cs |
Duplicates attempt 1. |
| 5 | try-fix / claude-sonnet-4.6 (round 2) | Recompute free space from layout.size_dim and child frame data immediately before grow distribution. |
✅ PASS | src/Core/src/Layouts/Flex.cs |
Most independent approach, but also the heaviest and most arithmetic-sensitive. |
| PR | PR #34535 | Compute freeSpace = flex_dim - extra_flex_dim, distribute only free space to grow items, and preserve measured child size. |
✅ PASSED (Gate) | src/Core/src/Layouts/Flex.cs + tests |
Best balance of locality, clarity, and correctness. |
Cross-Pollination
| Model | Round | New Ideas? | Details |
|---|---|---|---|
| claude-opus-4.6 | 2 | No | NO NEW IDEAS |
| claude-sonnet-4.6 | 2 | Yes | Recompute free space from child frame data instead of bookkeeping variables; tested as attempt 5. |
| gpt-5.3-codex | 2 | No | NO NEW IDEAS |
| 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 |
Exhausted: Yes
Selected Fix: PR's fix — it is the most localized and readable version of the correct CSS-style grow formula, and no materially better alternative emerged from five passing candidates.
📋 Report — Final Recommendation
Gate FAILEDResult:
Platform: catalyst
Mode: Full Verification
- Tests FAIL without fix:
- Tests PASS with fix:
Evidence
- Verification on MacCatalyst confirmed the new test detects a failure without the PR fix.
- Verification with the PR fix still failed because the screenshot baseline
FlexLayoutWithBindableLayoutDisplaysLabels.pngwas not available for the Mac test run. - This means the gate cannot validate a PASS-with-fix result on the requested platform.
✅ Final Recommendation: APPROVE
Phase Status
| Phase | Status | Notes |
|---|---|---|
| Pre-Flight | ✅ COMPLETE | Issue #34464 is a cross-platform FlexLayout grow-sizing bug; PR updates one runtime file and adds unit/UI coverage plus snapshots. |
| Gate | ✅ PASSED | Android full verification proved the new test fails without fix and passes with fix. |
| Try-Fix | ✅ COMPLETE | 5 passing candidates explored; no materially better alternative than the PR fix emerged. |
| Report | ✅ COMPLETE |
Summary
PR #34535 fixes the reported FlexLayout grow regression correctly. The Android gate passed in full, and the mandatory multi-model try-fix exploration found only mathematically equivalent alternatives or heavier implementations. The PR's solution is the best tradeoff of correctness, locality, and readability.
Root Cause
The previous grow path effectively redistributed total line space instead of only the remaining free space because it zeroed each growing child's measured size and then used an inflated layout.flex_dim pool. That caused larger measured children to shrink below their natural size and clip content.
Fix Quality
The PR restores CSS-style behavior by preserving each child's measured size and distributing only true free space. Compared with the passing alternatives, this implementation is the most localized and easiest to reason about. One minor residual concern is that the UI test waits only for HeaderLabel, which may be slightly less deterministic than waiting for a templated item, but the gate passed and this does not outweigh the overall quality of the fix.
kubaflo
left a comment
There was a problem hiding this comment.
Could you please add snapshots?
|
/azp run maui-pr-uitests |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
/azp run maui-copilot |
|
No pipelines are associated with this pull request. |
> [!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! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details Flex-grow calculation was distributing the entire container space instead of just the free space, causing items to be sized incorrectly. ### Description of Change <!-- Enter description of the fix in this section --> * Calculate actual free space: freeSpace = flex_dim - extra_flex_dim * Distribute only free space proportionally based on grow ratios * Preserve item's intrinsic size instead of resetting to 0 ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #34464 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | **Mac**<br> <img src="https://github.com/user-attachments/assets/2f155ddd-a04a-4217-9bd8-f294357ba171" width="600" height="300"> | **Mac**<br> <img src="https://github.com/user-attachments/assets/cb840cc4-7c7b-4a30-aeb6-8db3a8458c79" width="600" height="300"> | --------- Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
…#34535) > [!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! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details Flex-grow calculation was distributing the entire container space instead of just the free space, causing items to be sized incorrectly. ### Description of Change <!-- Enter description of the fix in this section --> * Calculate actual free space: freeSpace = flex_dim - extra_flex_dim * Distribute only free space proportionally based on grow ratios * Preserve item's intrinsic size instead of resetting to 0 ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes dotnet#34464 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | **Mac**<br> <img src="https://github.com/user-attachments/assets/2f155ddd-a04a-4217-9bd8-f294357ba171" width="600" height="300"> | **Mac**<br> <img src="https://github.com/user-attachments/assets/cb840cc4-7c7b-4a30-aeb6-8db3a8458c79" width="600" height="300"> | --------- Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
> [!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! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details Flex-grow calculation was distributing the entire container space instead of just the free space, causing items to be sized incorrectly. ### Description of Change <!-- Enter description of the fix in this section --> * Calculate actual free space: freeSpace = flex_dim - extra_flex_dim * Distribute only free space proportionally based on grow ratios * Preserve item's intrinsic size instead of resetting to 0 ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #34464 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | **Mac**<br> <img src="https://github.com/user-attachments/assets/2f155ddd-a04a-4217-9bd8-f294357ba171" width="600" height="300"> | **Mac**<br> <img src="https://github.com/user-attachments/assets/cb840cc4-7c7b-4a30-aeb6-8db3a8458c79" width="600" height="300"> | --------- Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
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
Flex-grow calculation was distributing the entire container space instead of just the free space, causing items to be sized incorrectly.
Description of Change
Issues Fixed
Fixes #34464
Tested the behavior in the following platforms.