[iOS] Flyout Items Not Displayed in RightToLeft FlowDirection in Landscape - fix#26762
Conversation
|
/azp run |
|
Azure Pipelines successfully started running 3 pipeline(s). |
jsuarezruiz
left a comment
There was a problem hiding this comment.
Could you include a test? Let me know if needs something.
5d1e2b8 to
c234902
Compare
Done :) |
c234902 to
37f1950
Compare
|
Azure Pipelines successfully started running 3 pipeline(s). |
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/XFIssue/Issue2818.cs
Outdated
Show resolved
Hide resolved
|
/rebase |
37f1950 to
4da51bc
Compare
|
Azure Pipelines successfully started running 3 pipeline(s). |
4da51bc to
dc81db8
Compare
|
/azp run |
|
Azure Pipelines successfully started running 3 pipeline(s). |
Replaced fixed delay with a polling loop to wait for the window width to stabilize after foregrounding the app. This change reduces test flakiness on platforms where layout size may temporarily change before settling.
|
Azure Pipelines successfully started running 3 pipeline(s). |
🤖 AI Summary📊 Expand Full Review🔍 Pre-Flight — Context & Validation📝 Review Session — Stabilize window size check in Issue2818 test ·
|
| Reviewer | Comment | Status |
|---|---|---|
| jsuarezruiz | Requested test be added Resolved - test added | |
| jfversluis | Asked about Task.Delay usage Resolved - author used polling loop instead |
Potential Concerns
- The
[Issue]attribute inTestCases.HostApp/Issues/XFIssue/Issue2818.cshasPlatformAffected.Androidthough the issue is iOS-specific. The test itself runs on iOS (the #if guard condition controls platform). - The polling loop in
RootViewSizeDoesntChangeAfterBackground(50100ms max = 5s) is a valid pattern per UITest guidelines.
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #26762 | Correct flyout X position in RTL+landscape: `frame.Width - flyoutFrame. PENDING (Gate) | PhoneFlyoutPageRenderer.cs (+1/-1) |
Original PR | Width` |
🚦 Gate — Test Verification
📝 Review Session — Stabilize window size check in Issue2818 test · bef57ff
** PARTIAL - Environment IssueResult:**
Platform: ios
Mode: Full Verification
Test Results
| Check | Expected | Actual | Result |
|---|---|---|---|
| Tests WITHOUT fix | FAIL | FAIL | |
| Tests WITH fix | PASS | FAIL |
Detailed Results (WITH fix)
RootViewMovesAndContentIsVisible- PASSED [4 sec] - This test directly validates the RTL flyout positioning fix
RootViewSizeDoesntChangeAfterBackground- FAILED [5 sec] - TearDown error:Unable To Rotate Device-LabelWithPaddingIsNotTruncated- PASSED [545 ms]
Analysis
The Gate failure is due to an environment issue in TearDown, NOT a failure of the fix itself:
- The test body of
RootViewSizeDoesntChangeAfterBackgroundappears to have passed (no assertion error was thrown - only TearDown failed) - The TearDown calls
App.SetOrientationPortrait()which throwsOpenQA.Selenium.UnknownErrorException : Unable To Rotate Device- this is an iOS 26 simulator infrastructure issue - The primary test (which directly tests the RTL flyout visibility bug) PASSED
Conclusion
Gate is marked as FAILED due to the environment-related TearDown rotation issue. The fix behavior itself appears correct based on the primary test passing.
🔧 Fix — Analysis & Comparison
📝 Review Session — Stabilize window size check in Issue2818 test · bef57ff
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #26762 | Correct flyout X position in RTL+landscape: | , TearDown env | PhoneFlyoutPageRenderer.cs (+1/-1) |
Original PR |
Exhausted: N/A - Fix phase skipped (Gate failed due to environment issue)
Selected Fix: PR's fix - Gate failure was due to an environment/infrastructure issue (iOS simulator Unable To Rotate Device in TearDown), not a failure of the fix logic. Primary test RootViewMovesAndContentIsVisible PASSED.
Reason for Skipping Fix Phase
Gate failed with . Per autonomous execution rules, when Gate fails due to environment issues, the Fix phase is skipped and we proceed to Report. The primary test () that directly validates the RTL flyout positioning bug PASSED .
📋 Report — Final Recommendation
📝 Review Session — Stabilize window size check in Issue2818 test · bef57ff
Final Recommendation: APPROVE
Summary
PR #26762 fixes a 1-line bug in PhoneFlyoutPageRenderer.cs that caused the flyout panel to be incorrectly positioned when FlowDirection is RightToLeft in landscape orientation on iOS. The fix is correct, minimal, and the primary validation test passed.
Root Cause
In LayoutChildren(), the RTL flyout X position was calculated as:
flyoutFrame.X = (int)(flyoutFrame.Width * .25);This formula doesn't position the flyout at the right edge of the screen. In landscape mode (e.g., frame.Width=844, flyoutFrame.Width=312), this gives X= placing the flyout partially overlapping the content from the left side, making flyout items appear hidden.78
The fix correctly calculates the right-aligned position:
flyoutFrame.X = (int)(frame.Width - flyoutFrame.Width);This positions the flyout so its right edge aligns with the screen's right edge (X=532 for the example above), which is the correct RTL behavior.
Fix Quality
Implementation (PhoneFlyoutPageRenderer.cs Excellent):
- Minimal 1-line change in exactly the right location
- Mathematically correct:
frame.Width - flyoutFrame.Widthis the standard formula for right-aligning an element - No side effects on other code paths (only applies when
IsRTL && !FlyoutOverlapsDetailsInPopoverMode)
Tests (Issue2818.cs Good):
- Correctly removes
TEST_FAILS_ON_IOSfrom the compile guard, enabling the existingRootViewMovesAndContentIsVisibletest on iOS - Adds
RootViewSizeDoesntChangeAfterBackgroundto validate post-background stability - Uses polling loop (50100ms max) which is a valid UITest pattern
Test Results
| Test | Status | Notes |
|---|---|---|
| PASSED | Primary test: validates RTL flyout visibility | |
| ` TearDown env error | Test body likely passed; TearDown rotation fails on iOS 26 simulator | RootViewSizeDoesntChangeAfterBackground` |
Gate Environment issue with iOS 26 simulator rotation in TearDown, NOT a fix regression.PARTIAL Status:
Minor Issue Found
The [Issue] attribute in TestCases.HostApp/Issues/XFIssue/Issue2818.cs has PlatformAffected.Android but the bug affects iOS. This doesn't affect test execution (the #if guard controls compilation) but is semantically incorrect. Not a blocker.
PR Title & Description Assessment
- Title:
- Description: Links to issue, includes before/after videos. Minimal but adequate.
Reviewer Feedback Addressed
- jsuarezruizs request for tests Tests added:
- jfversluiss question about delays Resolved with polling loop approach:
Conclusion
The fix is correct and well-targeted. The Gate failure is due to an iOS 26 simulator environment issue with the rotation call (), not a problem with the fix itself. The test that directly validates the reported bug () PASSED . This PR should be approved.
📋 Expand PR Finalization Review
Title: ⚠️ Needs Update
Current: [iOS] Flyout Items Not Displayed in RightToLeft FlowDirection in Landscape - fix
Recommended: follows the
Description: ❌ Needs Rewrite
Description needs updates. See details below.
✨ 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
In PhoneFlyoutPageRenderer.LayoutChildren(), when IsRTL && !FlyoutOverlapsDetailsInPopoverMode, the flyout panel's X position was calculated as:
flyoutFrame.X = (int)(flyoutFrame.Width * .25);This formula positions the flyout at 25% of its own width from the left edge — not at the right side of the screen. In landscape orientation (where frame.Width is large), this places the flyout far off to the left, making its content invisible or clipped rather than right-aligned as expected for RTL layout.
Description of Change
PhoneFlyoutPageRenderer.cs — 1-line fix:
// Before
flyoutFrame.X = (int)(flyoutFrame.Width * .25);
// After
flyoutFrame.X = (int)(frame.Width - flyoutFrame.Width);frame.Width - flyoutFrame.Width is the standard right-align formula: it positions the flyout so its right edge aligns with the screen's right edge, which is the correct position for an RTL flyout panel.
Issue2818.cs (test) — two changes:
-
Removed
TEST_FAILS_ON_IOScompile guard. The test was previously skipped on iOS because the RTL flyout was broken. The fix makes iOS behavior correct, so the guard is no longer needed. -
Added
RootViewSizeDoesntChangeAfterBackgroundtest (async) with a polling loop (up to 5s / 50 × 100ms) to wait for window size to stabilize after backgrounding/foregrounding the app. This prevents flakiness caused by intermediate layout sizes during window restoration on iOS.
Issues Fixed
Fixes #26726
Platforms Tested
- iOS (primary — fix targets iOS RTL landscape flyout behavior)
- Android (not affected —
PhoneFlyoutPageRendereris iOS-only) - Windows (not affected)
- Mac Catalyst (test still excluded via
TEST_FAILS_ON_CATALYSTguard)
Code Review: ⚠️ Issues Found
Code Review — PR #26762
✅ Looks Good
PhoneFlyoutPageRenderer.cs — Implementation fix is correct and minimal
frame.Width - flyoutFrame.Widthis the standard right-align formula and is mathematically correct- The change is scoped strictly to the
IsRTL && !FlyoutOverlapsDetailsInPopoverModebranch — no side effects on other code paths - 1-line change in exactly the right location
Test guard correctly updated
- Removing
TEST_FAILS_ON_IOSis the right action — the comment explained the guard existed specifically because of issue Flyout Items Not Displayed in RightToLeft FlowDirection on iOS in Landscape Orientation and Hamburger Icon Positioned Incorrectly #26726, which this PR fixes
🟡 Suggestions
1. Trailing whitespace on [Test] attribute (minor)
File: src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/XFIssue/Issue2818.cs, line 37
[Test]
public async Task RootViewSizeDoesntChangeAfterBackground()There are two trailing spaces after [Test]. Not functionally significant, but inconsistent with repo style.
Recommendation: Remove the trailing whitespace.
2. Pre-existing: PlatformAffected.Android in HostApp [Issue] attribute
File: src/Controls/tests/TestCases.HostApp/Issues/XFIssue/Issue2818.cs, line 4
[Issue(IssueTracker.Github, 2818, "Right-to-Left FlyoutPage in Xamarin.Forms Hamburger icon issue", PlatformAffected.Android)]The PlatformAffected is Android, but issue #2818 (and the related #26726 being fixed here) affects iOS. This is a pre-existing annotation, but since this PR is enabling the test on iOS, updating it to PlatformAffected.iOS (or PlatformAffected.All) would be semantically correct.
Recommendation: Consider updating to PlatformAffected.iOS or PlatformAffected.All as part of this PR. Not a blocker.
3. Polling loop uses cached element reference (low risk — likely fine)
File: src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/XFIssue/Issue2818.cs, lines 53–63
var newWindowSize = App.WaitForElement("RootLayout");
// ...
while (newWindowSize.GetRect().Width != windowSize.GetRect().Width && retries-- > 0)
{
await Task.Delay(100);
}newWindowSize is fetched once before the loop. Inside the loop, newWindowSize.GetRect() is called on the same cached element reference. In Appium/Selenium, GetRect() on a cached element typically makes a live query to the driver each time, so this should yield fresh measurements on each iteration. However, the same is true for windowSize.GetRect() — both are live queries, so the comparison should be correct.
Observation: The intent is clear and the pattern is acceptable. However, if GetRect() ever returns a stale value on a cached element, the polling would not work as intended. An alternative would be to call App.WaitForElement("RootLayout") inside the loop to get a fresh element reference each iteration.
Recommendation: Low risk as-is. Optional improvement: fetch a fresh newWindowSize inside the loop for clarity, or add a comment noting that GetRect() is a live Appium query.
🔴 Critical Issues
None.
…scape - fix (#26762) Description needs updates. See details below. ### ✨ Suggested PR Description <!-- 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! ### Root Cause In `PhoneFlyoutPageRenderer.LayoutChildren()`, when `IsRTL && !FlyoutOverlapsDetailsInPopoverMode`, the flyout panel's X position was calculated as: ```csharp flyoutFrame.X = (int)(flyoutFrame.Width * .25); ``` This formula positions the flyout at 25% of its own width from the left edge — not at the right side of the screen. In landscape orientation (where `frame.Width` is large), this places the flyout far off to the left, making its content invisible or clipped rather than right-aligned as expected for RTL layout. ### Description of Change **`PhoneFlyoutPageRenderer.cs`** — 1-line fix: ```csharp // Before flyoutFrame.X = (int)(flyoutFrame.Width * .25); // After flyoutFrame.X = (int)(frame.Width - flyoutFrame.Width); ``` `frame.Width - flyoutFrame.Width` is the standard right-align formula: it positions the flyout so its right edge aligns with the screen's right edge, which is the correct position for an RTL flyout panel. **`Issue2818.cs`** (test) — two changes: 1. Removed `TEST_FAILS_ON_IOS` compile guard. The test was previously skipped on iOS because the RTL flyout was broken. The fix makes iOS behavior correct, so the guard is no longer needed. 2. Added `RootViewSizeDoesntChangeAfterBackground` test (async) with a polling loop (up to 5s / 50 × 100ms) to wait for window size to stabilize after backgrounding/foregrounding the app. This prevents flakiness caused by intermediate layout sizes during window restoration on iOS. ### Issues Fixed Fixes #26726 ### Platforms Tested - [x] iOS (primary — fix targets iOS RTL landscape flyout behavior) - [ ] Android (not affected — `PhoneFlyoutPageRenderer` is iOS-only) - [ ] Windows (not affected) - [ ] Mac Catalyst (test still excluded via `TEST_FAILS_ON_CATALYST` guard) </details> <details>
…scape - fix (#26762) Description needs updates. See details below. ### ✨ Suggested PR Description <!-- 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! ### Root Cause In `PhoneFlyoutPageRenderer.LayoutChildren()`, when `IsRTL && !FlyoutOverlapsDetailsInPopoverMode`, the flyout panel's X position was calculated as: ```csharp flyoutFrame.X = (int)(flyoutFrame.Width * .25); ``` This formula positions the flyout at 25% of its own width from the left edge — not at the right side of the screen. In landscape orientation (where `frame.Width` is large), this places the flyout far off to the left, making its content invisible or clipped rather than right-aligned as expected for RTL layout. ### Description of Change **`PhoneFlyoutPageRenderer.cs`** — 1-line fix: ```csharp // Before flyoutFrame.X = (int)(flyoutFrame.Width * .25); // After flyoutFrame.X = (int)(frame.Width - flyoutFrame.Width); ``` `frame.Width - flyoutFrame.Width` is the standard right-align formula: it positions the flyout so its right edge aligns with the screen's right edge, which is the correct position for an RTL flyout panel. **`Issue2818.cs`** (test) — two changes: 1. Removed `TEST_FAILS_ON_IOS` compile guard. The test was previously skipped on iOS because the RTL flyout was broken. The fix makes iOS behavior correct, so the guard is no longer needed. 2. Added `RootViewSizeDoesntChangeAfterBackground` test (async) with a polling loop (up to 5s / 50 × 100ms) to wait for window size to stabilize after backgrounding/foregrounding the app. This prevents flakiness caused by intermediate layout sizes during window restoration on iOS. ### Issues Fixed Fixes #26726 ### Platforms Tested - [x] iOS (primary — fix targets iOS RTL landscape flyout behavior) - [ ] Android (not affected — `PhoneFlyoutPageRenderer` is iOS-only) - [ ] Windows (not affected) - [ ] Mac Catalyst (test still excluded via `TEST_FAILS_ON_CATALYST` guard) </details> <details>
…scape - fix (#26762) Description needs updates. See details below. ### ✨ Suggested PR Description <!-- 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! ### Root Cause In `PhoneFlyoutPageRenderer.LayoutChildren()`, when `IsRTL && !FlyoutOverlapsDetailsInPopoverMode`, the flyout panel's X position was calculated as: ```csharp flyoutFrame.X = (int)(flyoutFrame.Width * .25); ``` This formula positions the flyout at 25% of its own width from the left edge — not at the right side of the screen. In landscape orientation (where `frame.Width` is large), this places the flyout far off to the left, making its content invisible or clipped rather than right-aligned as expected for RTL layout. ### Description of Change **`PhoneFlyoutPageRenderer.cs`** — 1-line fix: ```csharp // Before flyoutFrame.X = (int)(flyoutFrame.Width * .25); // After flyoutFrame.X = (int)(frame.Width - flyoutFrame.Width); ``` `frame.Width - flyoutFrame.Width` is the standard right-align formula: it positions the flyout so its right edge aligns with the screen's right edge, which is the correct position for an RTL flyout panel. **`Issue2818.cs`** (test) — two changes: 1. Removed `TEST_FAILS_ON_IOS` compile guard. The test was previously skipped on iOS because the RTL flyout was broken. The fix makes iOS behavior correct, so the guard is no longer needed. 2. Added `RootViewSizeDoesntChangeAfterBackground` test (async) with a polling loop (up to 5s / 50 × 100ms) to wait for window size to stabilize after backgrounding/foregrounding the app. This prevents flakiness caused by intermediate layout sizes during window restoration on iOS. ### Issues Fixed Fixes #26726 ### Platforms Tested - [x] iOS (primary — fix targets iOS RTL landscape flyout behavior) - [ ] Android (not affected — `PhoneFlyoutPageRenderer` is iOS-only) - [ ] Windows (not affected) - [ ] Mac Catalyst (test still excluded via `TEST_FAILS_ON_CATALYST` guard) </details> <details>
…scape - fix (#26762) Description needs updates. See details below. ### ✨ Suggested PR Description <!-- 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! ### Root Cause In `PhoneFlyoutPageRenderer.LayoutChildren()`, when `IsRTL && !FlyoutOverlapsDetailsInPopoverMode`, the flyout panel's X position was calculated as: ```csharp flyoutFrame.X = (int)(flyoutFrame.Width * .25); ``` This formula positions the flyout at 25% of its own width from the left edge — not at the right side of the screen. In landscape orientation (where `frame.Width` is large), this places the flyout far off to the left, making its content invisible or clipped rather than right-aligned as expected for RTL layout. ### Description of Change **`PhoneFlyoutPageRenderer.cs`** — 1-line fix: ```csharp // Before flyoutFrame.X = (int)(flyoutFrame.Width * .25); // After flyoutFrame.X = (int)(frame.Width - flyoutFrame.Width); ``` `frame.Width - flyoutFrame.Width` is the standard right-align formula: it positions the flyout so its right edge aligns with the screen's right edge, which is the correct position for an RTL flyout panel. **`Issue2818.cs`** (test) — two changes: 1. Removed `TEST_FAILS_ON_IOS` compile guard. The test was previously skipped on iOS because the RTL flyout was broken. The fix makes iOS behavior correct, so the guard is no longer needed. 2. Added `RootViewSizeDoesntChangeAfterBackground` test (async) with a polling loop (up to 5s / 50 × 100ms) to wait for window size to stabilize after backgrounding/foregrounding the app. This prevents flakiness caused by intermediate layout sizes during window restoration on iOS. ### Issues Fixed Fixes #26726 ### Platforms Tested - [x] iOS (primary — fix targets iOS RTL landscape flyout behavior) - [ ] Android (not affected — `PhoneFlyoutPageRenderer` is iOS-only) - [ ] Windows (not affected) - [ ] Mac Catalyst (test still excluded via `TEST_FAILS_ON_CATALYST` guard) </details> <details>
…scape - fix (#26762) Description needs updates. See details below. ### ✨ Suggested PR Description <!-- 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! ### Root Cause In `PhoneFlyoutPageRenderer.LayoutChildren()`, when `IsRTL && !FlyoutOverlapsDetailsInPopoverMode`, the flyout panel's X position was calculated as: ```csharp flyoutFrame.X = (int)(flyoutFrame.Width * .25); ``` This formula positions the flyout at 25% of its own width from the left edge — not at the right side of the screen. In landscape orientation (where `frame.Width` is large), this places the flyout far off to the left, making its content invisible or clipped rather than right-aligned as expected for RTL layout. ### Description of Change **`PhoneFlyoutPageRenderer.cs`** — 1-line fix: ```csharp // Before flyoutFrame.X = (int)(flyoutFrame.Width * .25); // After flyoutFrame.X = (int)(frame.Width - flyoutFrame.Width); ``` `frame.Width - flyoutFrame.Width` is the standard right-align formula: it positions the flyout so its right edge aligns with the screen's right edge, which is the correct position for an RTL flyout panel. **`Issue2818.cs`** (test) — two changes: 1. Removed `TEST_FAILS_ON_IOS` compile guard. The test was previously skipped on iOS because the RTL flyout was broken. The fix makes iOS behavior correct, so the guard is no longer needed. 2. Added `RootViewSizeDoesntChangeAfterBackground` test (async) with a polling loop (up to 5s / 50 × 100ms) to wait for window size to stabilize after backgrounding/foregrounding the app. This prevents flakiness caused by intermediate layout sizes during window restoration on iOS. ### Issues Fixed Fixes #26726 ### Platforms Tested - [x] iOS (primary — fix targets iOS RTL landscape flyout behavior) - [ ] Android (not affected — `PhoneFlyoutPageRenderer` is iOS-only) - [ ] Windows (not affected) - [ ] Mac Catalyst (test still excluded via `TEST_FAILS_ON_CATALYST` guard) </details> <details>
## What's Coming .NET MAUI inflight/candidate introduces significant improvements across all platforms with focus on quality, performance, and developer experience. This release includes 66 commits with various improvements, bug fixes, and enhancements. ## Activityindicator - [Android] Implemented material3 support for ActivityIndicator by @Dhivya-SF4094 in #33481 <details> <summary>🔧 Fixes</summary> - [Implement material3 support for ActivityIndicator](#33479) </details> - [iOS] Fix: ActivityIndicator IsRunning ignores IsVisible when set to true by @bhavanesh2001 in #28983 <details> <summary>🔧 Fixes</summary> - [[iOS] [ActivityIndicator] `IsRunning` ignores `IsVisible` when set to `true`](#28968) </details> ## Button - [iOS] Button RTL text and image overlap - fix by @kubaflo in #29041 ## Checkbox - [iOS/MacCatalyst] Fix CheckBox foreground color not resetting when set to null by @Ahamed-Ali in #34284 <details> <summary>🔧 Fixes</summary> - [[iOS] Color of the checkBox control is not properly worked on dynamic scenarios](#34278) </details> ## CollectionView - [iOS] Fix: CollectionView does not clear selection when SelectedItem is set to null by @Tamilarasan-Paranthaman in #30420 <details> <summary>🔧 Fixes</summary> - [CollectionView not being able to remove selected item highlight on iOS](#30363) - [[MAUI] Select items traces are preserved](#26187) </details> - [iOS] CV2 ItemsLayout update by @kubaflo in #28675 <details> <summary>🔧 Fixes</summary> - [CollectionView CollectionViewHandler2 doesnt change ItemsLayout on DataTrigger](#28656) - [iOS CollectionView doesn't respect a change to ItemsLayout when using Items2.CollectionViewHandler2](#31259) </details> - [iOS][CV2] Fix CollectionView renders large empty space at bottom of view by @devanathan-vaithiyanathan in #31215 <details> <summary>🔧 Fixes</summary> - [[iOS] [MacCatalyst] CollectionView renders large empty space at bottom of view](#17799) - [[iOS/Mac] CollectionView2 EmptyView takes up large horizontal space even when the content is small](#33201) </details> - [iOS] Fixed issue where group Header/Footer template was set to all items when IsGrouped was true for an ObservableCollection by @Tamilarasan-Paranthaman in #29144 <details> <summary>🔧 Fixes</summary> - [[iOS] Group Header/Footer Repeated for All Items When IsGrouped is True for ObservableCollection in CollectionView](#29141) </details> - [Android] Fix CollectionView selection crash with HeaderTemplate by @NirmalKumarYuvaraj in #34275 <details> <summary>🔧 Fixes</summary> - [[Bug] [Android] System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index](#34247) </details> ## DateTimePicker - [iOS] Fix TimePicker AM/PM frequently changes when the app is closed and reopened by @devanathan-vaithiyanathan in #31066 <details> <summary>🔧 Fixes</summary> - [[iOS] TimePicker AM/PM frequently changes when the app is closed and reopened](#30837) - [Maui 10 iOS TimePicker Strange Characters in place of AM/PM](#33722) </details> - Android TimePicker ignores 24 hour system setting when using Format Property - fix by @kubaflo in #28797 <details> <summary>🔧 Fixes</summary> - [Android TimePicker ignores 24 hour system setting when using Format Property](#28784) </details> ## Drawing - [iOS, Mac, Windows] GraphicsView: Fix Background/BackgroundColor not updating by @NirmalKumarYuvaraj in #31254 <details> <summary>🔧 Fixes</summary> - [[iOS, Mac, Windows] GraphicsView does not change the Background/BackgroundColor](#31239) </details> - [iOS] GraphicsView DrawString - fix by @kubaflo in #26304 <details> <summary>🔧 Fixes</summary> - [DrawString not rendering in iOS.](#24450) - [GraphicsView DrawString not rendering in iOS](#8486) - [DrawString doesn't work on maccatalyst](#4993) </details> - [Android] - Fix Shadow Rendering For Transparent Fill, Stroke (Lines), and Text on Shapes by @prakashKannanSf3972 in #29528 <details> <summary>🔧 Fixes</summary> - [Ellipse Transparency Not Rendered When Drawing Arc Inside the Ellipse Using GraphicsView on Android](#29394) </details> - Revert "[iOS, Mac, Windows] GraphicsView: Fix Background/BackgroundColor not updating (#31254)" by @Ahamed-Ali via @Copilot in #34508 ## Entry - [iOS 26] Fix Entry MaxLength not enforced due to new multi-range delegate by @kubaflo in #32045 <details> <summary>🔧 Fixes</summary> - [iOS 26 - The MaxLength property value is not respected on an Entry control.](#32016) - [.NET MAUI Entry Maximum Length not working on iOS and macOS](#33316) </details> - [iOS] Fixed Entry with IsPassword toggling loses previously entered text by @SubhikshaSf4851 in #30572 <details> <summary>🔧 Fixes</summary> - [Entry with IsPassword toggling loses previously entered text on iOS when IsPassword is re-enabled](#30085) </details> ## Essentials - Fix for FilePicker PickMultipleAsync nullable reference type by @SuthiYuvaraj in #33163 <details> <summary>🔧 Fixes</summary> - [FilePicker PickMultipleAsync nullable reference type](#33114) </details> - Replace deprecated NetworkReachability with NWPathMonitor on iOS/macOS by @jfversluis via @Copilot in #32354 <details> <summary>🔧 Fixes</summary> - [NetworkReachability is obsolete on iOS/maccatalyst 17.4+](#32312) - [Use NWPathMonitor on iOS for Essentials Connectivity](#2574) </details> ## Essentials Connectivity - Update Android Connectivity implementation to use modern APIs by @jfversluis via @Copilot in #30348 <details> <summary>🔧 Fixes</summary> - [Update the Android Connectivity implementation to user modern APIs](#30347) </details> ## Flyout - [iOS] Fixed Flyout icon not updating when root page changes using InsertPageBefore by @Vignesh-SF3580 in #29924 <details> <summary>🔧 Fixes</summary> - [[iOS] Flyout icon not replaced by back button when root page is changed using InsertPageBefore](#29921) </details> ## Flyoutpage - [iOS] Flyout Items Not Displayed in RightToLeft FlowDirection in Landscape - fix by @kubaflo in #26762 <details> <summary>🔧 Fixes</summary> - [Flyout Items Not Displayed in RightToLeft FlowDirection on iOS in Landscape Orientation and Hamburger Icon Positioned Incorrectly](#26726) </details> ## Image - [Android] Implemented Material3 support for Image by @Dhivya-SF4094 in #33661 <details> <summary>🔧 Fixes</summary> - [Implement Material3 support for Image](#33660) </details> ## Keyboard - [iOS] Fix gap at top of view after rotating device while Entry keyboard is visible by @praveenkumarkarunanithi in #34328 <details> <summary>🔧 Fixes</summary> - [Focusing and entering texts on entry control causes a gap at the top after rotating simulator.](#33407) </details> ## Label - [Android] Support for images inside HTML label by @kubaflo in #21679 <details> <summary>🔧 Fixes</summary> - [Label with HTML TextType does not display images on Android](#21044) </details> - [fix] ContentLabel Moved to a nested class to prevent CS0122 in external source generators by @SubhikshaSf4851 in #34514 <details> <summary>🔧 Fixes</summary> - [[MAUI] Building Maui App with sample content results CS0122 errors.](#34512) </details> ## Layout - Optimize ordering of children in Flex layout by @symbiogenesis in #21961 - [Android] Fix control size properties not available during Loaded event by @Vignesh-SF3580 in #31590 <details> <summary>🔧 Fixes</summary> - [CollectionView on Android does not provide height, width, logical children once loaded, works fine on Windows](#14364) - [Control's Loaded event invokes before calling its measure override method.](#14160) </details> ## Mediapicker - [iOS/Android] MediaPicker: Fix image orientation when RotateImage=true by @michalpobuta in #33892 <details> <summary>🔧 Fixes</summary> - [MediaPicker.PickPhotosAsync does not preserve image orientation](#32650) </details> ## Modal - [Windows] Fix modal page keyboard focus not shifting to newly opened modal by @jfversluis in #34212 <details> <summary>🔧 Fixes</summary> - [Keyboard focus does not shift to a newly opened modal page: Pressing enter clicks the button on the page beneath the modal page](#22938) </details> ## Navigation - [iOS26] Apply view margins in title view by @kubaflo in #32205 <details> <summary>🔧 Fixes</summary> - [NavigationPage TitleView iOS 26](#32200) </details> - [iOS] System.NullReferenceException at NavigationRenderer.SetStatusBarStyle() by @kubaflo in #29564 <details> <summary>🔧 Fixes</summary> - [System.NullReferenceException at NavigationRenderer.SetStatusBarStyle()](#29535) </details> - [iOS 26] Fix back button color not applied for NavigationPage by @Shalini-Ashokan in #34326 <details> <summary>🔧 Fixes</summary> - [[iOS] Color not applied to the Back button text or image on iOS 26](#33966) </details> ## Picker - Fix Picker layout on Mac Catalyst 26+ by @kubaflo in #33146 <details> <summary>🔧 Fixes</summary> - [[MacOS 26] Text on picker options are not centered on macOS 26.1](#33229) </details> ## Progressbar - [Android] Implemented Material3 support for ProgressBar by @SyedAbdulAzeemSF4852 in #33926 <details> <summary>🔧 Fixes</summary> - [Implement Material3 support for Progressbar](#33925) </details> ## RadioButton - [iOS, Mac] Fix for RadioButton TextColor for plain Content not working by @HarishwaranVijayakumar in #31940 <details> <summary>🔧 Fixes</summary> - [RadioButton: TextColor for plain Content not working on iOS](#18011) </details> - [All Platforms] Fix RadioButton warning when ControlTemplate is set with View content by @kubaflo in #33839 <details> <summary>🔧 Fixes</summary> - [Seeking clarification on RadioButton + ControlTemplate + Content documentation](#33829) </details> - Visual state change for disabled RadioButton by @kubaflo in #23471 <details> <summary>🔧 Fixes</summary> - [RadioButton disabled UI issue - iOS](#18668) </details> ## SafeArea - [Android] Fix for TabbedPage BottomNavigation BarBackgroundColor not extending to system navigation bar by @praveenkumarkarunanithi in #33428 <details> <summary>🔧 Fixes</summary> - [[Android] TabbedPage BottomNavigation BarBackgroundColor does not extend to system navigation bar area in Edge-to-Edge mode](#33344) </details> ## ScrollView - [Android] ScrollView: Fix HorizontalScrollBarVisibility not updating immediately at runtime by @SubhikshaSf4851 in #33528 <details> <summary>🔧 Fixes</summary> - [Runtime Scrollbar visibility not updating correctly on Android and macOS platforms.](#33400) </details> - Fixed crash when calling ItemsView.ScrollTo on unloaded CollectionView by @kubaflo in #25444 <details> <summary>🔧 Fixes</summary> - [App crashes when calling ItemsView.ScrollTo on unloaded CollectionView](#23014) </details> ## Shell - [Shell] Update logic for iOS large title display in ShellItemRenderer by @kubaflo in #33246 - [iOS][Shell] Fix navigation lifecycle and back button for More tab (>5 tabs) by @kubaflo in #27932 <details> <summary>🔧 Fixes</summary> - [OnAppearing and OnNavigatedTo does not work when using extended Tabbar (tabbar with more than 5 tabs) on IOS.](#27799) - [Shell.BackButtonBehavior does not work when using extended Tabbar (tabbar with more than 5 tabs)on IOS.](#27800) - [Shell TabBar More button causes ViewModel command binding disconnection on back navigation](#30862) - [Content page onappearing not firing if tabs are on the more tab on IOS](#31166) </details> - [iOS 26] Fix tab bar ghosting when navigating from modal to tabbed Shell content by @SubhikshaSf4851 in #34254 <details> <summary>🔧 Fixes</summary> - [[iOS] Tab bar ghosting issue on iOS 26 (liquid glass)](#34143) </details> - Fix for Shell tab visibility not updating when navigating back multiple pages by @BagavathiPerumal in #34403 <details> <summary>🔧 Fixes</summary> - [Changing Shell Tab Visibility when navigating back multiple pages ignores Shell Tab Visibility](#33351) </details> - [iOS/Mac] Fixed OnBackButtonPressed not firing for Shell Navigation Bar Button by @Dhivya-SF4094 in #34401 <details> <summary>🔧 Fixes</summary> - [[iOS] OnBackButtonPressed not firing for Shell Navigation Bar button](#34190) </details> ## Slider - [iOS] Fix for Slider ThumbImageSource is not centered properly on iOS 26 by @HarishwaranVijayakumar in #34019 <details> <summary>🔧 Fixes</summary> - [[iOS 26] Slider ThumbImageSource is not centered properly](#33967) </details> - [Android] Fix improper rendering of ThumbimageSource in Slider by @NirmalKumarYuvaraj in #34064 <details> <summary>🔧 Fixes</summary> - [[Slider] MAUI Slider thumb image is big on android](#13258) </details> ## Stepper - [iOS] Fix Stepper layout overlap in landscape on iOS 26 by @Vignesh-SF3580 in #34325 <details> <summary>🔧 Fixes</summary> - [[.NET10] D10 - Customize cursor position - Rotating simulator makes the button and label overlap](#34273) </details> ## SwipeView - [iOS] SwipeView: Honor FontImageSource.Color in SwipeItem icon by @kubaflo in #27389 <details> <summary>🔧 Fixes</summary> - [[iOS] SwipeView: SwipeItem.IconImageSource.FontImageSource color value not honored](#27377) </details> ## Switch - [Android] Fix Switch thumb shadow missing when ThumbColor is set by @Shalini-Ashokan in #33960 <details> <summary>🔧 Fixes</summary> - [Android Switch Control Thumb Shadow](#19676) </details> ## Toolbar - [iOS/Mac Catalyst 26] Fix Shell.ForegroundColor not applied to ToolbarItems by @SyedAbdulAzeemSF4852 in #34085 <details> <summary>🔧 Fixes</summary> - [[iOS26] Shell.ForegroundColor is not applied to ToolbarItems](#34083) </details> - [Android] VoiceOver on Toolbar Item by @kubaflo in #29596 <details> <summary>🔧 Fixes</summary> - [VoiceOver on Toolbar Item](#29573) - [SemanticProperties do not work on ToolbarItems](#23623) </details> <details> <summary>🧪 Testing (11)</summary> - [Testing] Additional Feature Matrix Test Cases for CollectionView by @TamilarasanSF4853 in #32432 - [Testing] Feature Matrix UITest Cases for VisualStateManager by @LogishaSelvarajSF4525 in #34146 - [Testing] Feature Matrix UITest Cases for Clip by @TamilarasanSF4853 in #34121 - [Testing] Feature matrix UITest Cases for Map Control by @HarishKumarSF4517 in #31656 - [Testing] Feature matrix UITest Cases for Visual Transform Control by @HarishKumarSF4517 in #32799 - [Testing] Feature Matrix UITest Cases for Shell Pages by @NafeelaNazhir in #33945 - [Testing] Feature Matrix UITest Cases for Triggers by @HarishKumarSF4517 in #34152 - [Testing] Refactoring Feature Matrix UITest Cases for CheckBox Control by @LogishaSelvarajSF4525 in #34283 - Resolve UI test Build Sample failures - Candidate March 16 by @Ahamed-Ali in #34442 - Fix the failures in the Candidate branch- March 16 by @Ahamed-Ali in #34453 <details> <summary>🔧 Fixes</summary> - [March 16th, Candidate](#34437) </details> - Fixed the iOS 18.5 Candidate failures (March 16,2026) by @Ahamed-Ali in #34593 <details> <summary>🔧 Fixes</summary> - [March 16th, Candidate](#34437) </details> </details> <details> <summary>📦 Other (2)</summary> - Fixed candidate test failures caused by PR #33428. by @Ahamed-Ali in #34515 <details> <summary>🔧 Fixes</summary> - [[.NET10] On Android, there's a big space at the top for I, M and N2 & N3](#34509) </details> - Revert "[iOS] Button RTL text and image overlap - fix (#29041)" in b0497af </details> <details> <summary>📝 Issue References</summary> Fixes #2574, Fixes #4993, Fixes #8486, Fixes #13258, Fixes #14160, Fixes #14364, Fixes #17799, Fixes #18011, Fixes #18668, Fixes #19676, Fixes #21044, Fixes #22938, Fixes #23014, Fixes #23623, Fixes #24450, Fixes #26187, Fixes #26726, Fixes #27377, Fixes #27799, Fixes #27800, Fixes #28656, Fixes #28784, Fixes #28968, Fixes #29141, Fixes #29394, Fixes #29535, Fixes #29573, Fixes #29921, Fixes #30085, Fixes #30347, Fixes #30363, Fixes #30837, Fixes #30862, Fixes #31166, Fixes #31239, Fixes #31259, Fixes #32016, Fixes #32200, Fixes #32312, Fixes #32650, Fixes #33114, Fixes #33201, Fixes #33229, Fixes #33316, Fixes #33344, Fixes #33351, Fixes #33400, Fixes #33407, Fixes #33479, Fixes #33660, Fixes #33722, Fixes #33829, Fixes #33925, Fixes #33966, Fixes #33967, Fixes #34083, Fixes #34143, Fixes #34190, Fixes #34247, Fixes #34273, Fixes #34278, Fixes #34437, Fixes #34509, Fixes #34512 </details> **Full Changelog**: main...inflight/candidate
…scape - fix (dotnet#26762) Description needs updates. See details below. ### ✨ Suggested PR Description <!-- 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! ### Root Cause In `PhoneFlyoutPageRenderer.LayoutChildren()`, when `IsRTL && !FlyoutOverlapsDetailsInPopoverMode`, the flyout panel's X position was calculated as: ```csharp flyoutFrame.X = (int)(flyoutFrame.Width * .25); ``` This formula positions the flyout at 25% of its own width from the left edge — not at the right side of the screen. In landscape orientation (where `frame.Width` is large), this places the flyout far off to the left, making its content invisible or clipped rather than right-aligned as expected for RTL layout. ### Description of Change **`PhoneFlyoutPageRenderer.cs`** — 1-line fix: ```csharp // Before flyoutFrame.X = (int)(flyoutFrame.Width * .25); // After flyoutFrame.X = (int)(frame.Width - flyoutFrame.Width); ``` `frame.Width - flyoutFrame.Width` is the standard right-align formula: it positions the flyout so its right edge aligns with the screen's right edge, which is the correct position for an RTL flyout panel. **`Issue2818.cs`** (test) — two changes: 1. Removed `TEST_FAILS_ON_IOS` compile guard. The test was previously skipped on iOS because the RTL flyout was broken. The fix makes iOS behavior correct, so the guard is no longer needed. 2. Added `RootViewSizeDoesntChangeAfterBackground` test (async) with a polling loop (up to 5s / 50 × 100ms) to wait for window size to stabilize after backgrounding/foregrounding the app. This prevents flakiness caused by intermediate layout sizes during window restoration on iOS. ### Issues Fixed Fixes dotnet#26726 ### Platforms Tested - [x] iOS (primary — fix targets iOS RTL landscape flyout behavior) - [ ] Android (not affected — `PhoneFlyoutPageRenderer` is iOS-only) - [ ] Windows (not affected) - [ ] Mac Catalyst (test still excluded via `TEST_FAILS_ON_CATALYST` guard) </details> <details>
Description needs updates. See details below.
✨ 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
In
PhoneFlyoutPageRenderer.LayoutChildren(), whenIsRTL && !FlyoutOverlapsDetailsInPopoverMode, the flyout panel's X position was calculated as:This formula positions the flyout at 25% of its own width from the left edge — not at the right side of the screen. In landscape orientation (where
frame.Widthis large), this places the flyout far off to the left, making its content invisible or clipped rather than right-aligned as expected for RTL layout.Description of Change
PhoneFlyoutPageRenderer.cs— 1-line fix:frame.Width - flyoutFrame.Widthis the standard right-align formula: it positions the flyout so its right edge aligns with the screen's right edge, which is the correct position for an RTL flyout panel.Issue2818.cs(test) — two changes:Removed
TEST_FAILS_ON_IOScompile guard. The test was previously skipped on iOS because the RTL flyout was broken. The fix makes iOS behavior correct, so the guard is no longer needed.Added
RootViewSizeDoesntChangeAfterBackgroundtest (async) with a polling loop (up to 5s / 50 × 100ms) to wait for window size to stabilize after backgrounding/foregrounding the app. This prevents flakiness caused by intermediate layout sizes during window restoration on iOS.Issues Fixed
Fixes #26726
Platforms Tested
PhoneFlyoutPageRendereris iOS-only)TEST_FAILS_ON_CATALYSTguard)Details