[Android] Fix for TabbedPage BottomNavigation BarBackgroundColor not extending to system navigation bar#33428
Conversation
|
/rebase |
5ba38f6 to
1f0808c
Compare
There was a problem hiding this comment.
Pull request overview
This PR fixes an Android edge-to-edge mode issue where TabbedPage with ToolbarPlacement.Bottom did not extend the BarBackgroundColor into the system navigation bar area, leaving a visible gap. The fix changes how window insets are handled in MauiWindowInsetListener to apply bottom padding to the content view instead of the root view, and passes bottom insets through unconsumed so that BottomNavigationView can extend into the navigation bar area.
Changes:
- Modified inset handling logic to apply bottom padding to content view instead of root view when bottom navigation is present
- Removed
appBarHasContentcondition from inset consumption to allowSafeAreaExtensionsoverlap logic to handle padding correctly - Added a test to verify
BottomNavigationViewextends to screen bottom in edge-to-edge mode
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| src/Core/src/Platform/Android/MauiWindowInsetListener.cs | Modified inset handling to pad content view instead of root view for bottom navigation, and pass through bottom insets unconsumed |
| src/Controls/tests/DeviceTests/Elements/TabbedPage/TabbedPageTests.Android.cs | Added test to verify bottom navigation view extends to screen bottom with proper layout positioning |
src/Controls/tests/DeviceTests/Elements/TabbedPage/TabbedPageTests.Android.cs
Outdated
Show resolved
Hide resolved
🤖 AI Summary📊 Expand Full Review🔍 Pre-Flight — Context & Validation📝 Review Session — Merge branch 'fix-33344' of https://github.com/praveenkumarkarunanithi/maui into fix-33344 ·
|
| File | Type | Lines |
|---|---|---|
src/Core/src/Platform/Android/MauiWindowInsetListener.cs |
Fix | +19 / -8 |
src/Controls/tests/DeviceTests/Elements/TabbedPage/TabbedPageTests.Android.cs |
Device Test | +43 / 0 |
PR Fix Summary
When hasBottomNav is true (TabbedPage with ToolbarPlacement.Bottom):
- Before: Padded root view with bottom inset only; consumed bottom insets (set to 0 in returned insets)
- After: Pads
contentViewwith left, right, bottom system bar insets; passes ALL insets through unconsumed
Additional change: Removed appBarHasContent conditional from newSystemBars/newDisplayCutout construction, now always passing top insets through unconsumed.
Prior Agent Review Status
A prior agent review was posted to the PR. Gate FAILED in the prior run. The author has NOT updated the code since then (same commit SHA f614303).
Reviewer Comments (Copilot PR Reviewer - unresolved)
| File:Line | Concern | Status |
|---|---|---|
MauiWindowInsetListener.cs:281 |
Left/right insets on contentView may conflict with CoordinatorLayout NOT ADDRESSED | behavior |
MauiWindowInsetListener.cs:276 |
Comment should clarify padding covers nav bar + system nav NOT ADDRESSED | bar |
TabbedPageTests.Android.cs:250 |
Exact equality (==) for pixel positions is NOT ADDRESSED |
fragile |
Key Concerns
- Left/right insets on contentView (Medium): Adds
systemBars?.LeftandsystemBars?.RighttocontentViewnot in original code and may cause double-padding in landscape mode.padding - Removed
appBarHasContentconditional (Medium): Top insets now ALWAYS passed through; this is unrelated to the bottom nav fix and could affect NavigationPage/Shell with top navigation bars. - Test uses exact equality (Minor):
screenHeight == bottomNavBottomshould useMath.Abs(...) < 2for robustness.
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #33428 | Pad contentView instead of root view; pass all insets through PENDING (Gate) | MauiWindowInsetListener.cs (+19/-8) |
Original PR - 3 unaddressed review comments | unconsumed |
🚦 Gate — Test Verification
📝 Review Session — Merge branch 'fix-33344' of https://github.com/praveenkumarkarunanithi/maui into fix-33344 · f614303
** FAILEDResult:**
Platform: android
Mode: Full Verification (Two-Pass)
Gate Verification Results
| Pass | State | Expected | Actual | Status |
|---|---|---|---|---|
| Pass 1 (WITHOUT fix) | Fix reverted to origin/main | FAIL | FAIL OK | |
| Pass 2 (WITH fix) | Fix applied | PASS | BAD | FAIL |
Critical Finding: Test Does Not Pass With Fix Applied
The test BottomNavigationViewExtendsToScreenBottom failed in both passes:
Failed WITHOUT the fix (Pass 1 - "expected", but for wrong reason)-
Failed WITH the fix (Pass 2 - unexpected)-
Root Cause of Gate Failure
The test BottomNavigationViewExtendsToScreenBottom is located in the DeviceTests project:
src/Controls/tests/DeviceTests/Elements/TabbedPage/TabbedPageTests.Android.cs
The Gate verification uses BuildAndRunHostApp.ps1 which builds and runs the UI Test HostApp (TestCases.HostApp). Device tests are a completely separate project that runs via Helix on CI they cannot be run locally using the HostApp runner.infrastructure
The build succeeded (0 errors) but no tests matching the filter were executed because the test isn't in the HostApp project.
Environment Blocker: Device tests require Helix infrastructure (cloud-based device testing) to they cannot be verified locally with the available test scripts.run
Prior Review Corroboration
The prior agent review (same commit f614303) also found Gate FAILED, describing the test as "passing both with and without the fix" in that environment. This is consistent - in both environments, the Gate infrastructure cannot properly verify this device test.
Gate Status
** FAILED**GATE:
Fix phase (try-fix) skipped: Cannot explore alternative fixes without a reliable local test to verify against.
🔧 Fix — Analysis & Comparison
📝 Review Session — Merge branch 'fix-33344' of https://github.com/praveenkumarkarunanithi/maui into fix-33344 · f614303
Fix Phase: Skipped - Gate Failed
Reason: Phase 3 (try-fix) was skipped because Gate failed.
The test BottomNavigationViewExtendsToScreenBottom is a device test that runs via Helix infrastructure (not locally via the HostApp runner). Without a reliable local test to validate fix candidates against, try-fix exploration cannot be performed.
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #33428 | Pad contentView instead of root view; pass all insets through UNVERIFIED (Gate failed) | MauiWindowInsetListener.cs (+19/-8) |
Test doesn't run locally | unconsumed |
Exhausted: N/A (skipped due to Gate failure - environment blocker)
Selected Fix: N/A - Cannot select without reliable tests
📋 Report — Final Recommendation
📝 Review Session — Merge branch 'fix-33344' of https://github.com/praveenkumarkarunanithi/maui into fix-33344 · f614303
Final Recommendation: REQUEST CHANGES##
Summary
PR #33428 addresses a real regression in .NET MAUI 10 where TabbedPage with ToolbarPlacement.Bottom doesn't extend BarBackgroundColor into the system navigation bar area on Android 15+ in Edge-to-Edge mode. The core fix direction (padding contentView instead of the root view, passing insets through unconsumed) is correct in principle. However, the PR has three significant technical issues plus a test verification problem that require the author's attention before it can be merged.
Root Cause Analysis
In Android Edge-to-Edge mode (API 35+), MauiWindowInsetListener.ApplyDefaultWindowInsets was applying bottom padding to the root view and consuming bottom insets (setting them to 0 in the returned WindowInsetsCompat). Since BottomNavigationView never received the system navigation bar insets, it could not extend its background color into the navigation bar leaving a visible gap between the tab bar and the screen edge.area
Gate Verification
- Platform tested: Android
- Test:
BottomNavigationViewExtendsToScreenBottominTabbedPageTests.Android.cs(DeviceTests) - Gate Environment blocker: the test is a device test (Helix infrastructure) and cannot be verified locally via the HostApp runner. Both passes failed, consistent with the prior agent review which also found Gate FAILED.FAILED status:
Fix Analysis
| Change | Assessment | Verdict |
|---|---|---|
| Pad instead of root view | prevents content area from being squished by the system nav bar | Correct Good |
| Pass bottom insets through unconsumed | allows to extend its background into nav bar area | Required Good |
Apply left/right insets to contentView |
Not needed for the fix; may cause unexpected padding in landscape mode with Remove | cutouts |
Remove appBarHasContent from top insets |
Unrelated change; changes inset behavior for ALL layouts (NavigationPage, Shell); regression Revert | risk |
| Test uses exact equality for pixel positions | Fragile; 1px rounding differences common on Fix | Android |
Required Changes
Issue 1 (Critical): Test does not reliably verify the fix
The test BottomNavigationViewExtendsToScreenBottom measures whether BottomNavigationView's bottom pixel coordinate equals the screen height. In Edge-to-Edge mode, BottomNavigationView is often already laid out to the physical screen bottom regardless of inset the visual gap is caused by the background color not extending, not by the view's position being different.state
A more reliable test would:
- Verify that
contentView's bottom padding equals the system navigation bar inset height whenhasBottomNavis true - OR verify that the root view does NOT have bottom padding in the bottom-nav scenario
Issue 2 (Medium): Remove left/right insets from contentView padding
The original code only applied bottom padding to the root view. The fix introduces left/right insets on contentView which:
- Are not needed for the bug fix
- Were not in the original code
- May cause unexpected behavior in landscape orientation with display cutouts
// Change this:
contentView?.SetPadding(
systemBars?.Left ?? 0,
0,
systemBars?.Right ?? 0,
bottomInset);
// To this:
contentView?.SetPadding(0, 0, 0, bottomInset);Issue 3 (Medium): Revert the appBarHasContent inset consumption change
Removing the appBarHasContent ? 0 : systemBars?.Top ?? 0 conditional changes behavior for all layouts, not just TabbedPage bottom navigation. This is unrelated to the bug fix, was not explained in the PR description, and has no accompanying tests for NavigationPage/Shell scenarios.
// Revert to original:
var newSystemBars = Insets.Of(
systemBars?.Left ?? 0,
appBarHasContent ? 0 : systemBars?.Top ?? 0,
systemBars?.Right ?? 0,
hasBottomNav ? 0 : systemBars?.Bottom ?? 0
) ?? Insets.None;Issue 4 (Minor): Test tolerance
// Change:
Assert.True(screenHeight == bottomNavBottom, ...);
// To:
Assert.True(Math.Abs(screenHeight - bottomNavBottom) < 2, ...);Prior Review Status
This is the second agent review of this PR. The prior review (posted 2026-02-17) made the same recommendations. The author has NOT addressed any of the concerns since the review was posted (same commit SHA f614303).
There are also 3 unresolved inline review comments from the Copilot PR Reviewer (Jan 16, 2026) that align with findings none have been addressed.above
📋 Expand PR Finalization Review
Title: ✅ Good
Current: [Android] Fix for TabbedPage BottomNavigation BarBackgroundColor not extending to system navigation bar
Description: ✅ Good
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 Android Edge-to-Edge mode, the MauiWindowInsetListener was applying padding to the root view and consuming bottom insets. This prevented BottomNavigationView from receiving the system navigation bar insets, so it could not extend its background color into the navigation bar area—resulting in a visible gap between the tab bar and the screen edge.
Description of Change
When a TabbedPage uses ToolbarPlacement.Bottom, the fix applies bottom padding to contentView (the fragment container) instead of the root view, and passes bottom insets through without consuming them. This allows BottomNavigationView to receive the insets and extend its background color into the system navigation bar area, eliminating the gap. Additionally, removed the appBarHasContent check from inset consumption since SafeAreaExtensions overlap logic already correctly determines padding for child views based on their screen position.
Issues Fixed
Fixes #33344
Tested the behaviour in the following platforms
- Android
- Windows
- iOS
- Mac
Note:
This issue is Android-specific. Windows and macOS do not have a system navigation bar area at the bottom of the screen.
Screenshots
| Before Issue Fix | After Issue Fix |
|---|---|
![]() |
![]() |
Code Review: ✅ Passed
Code Review Findings — PR #33428
🟡 Suggestions
1. Test assertion uses exact pixel equality — could be fragile
File: src/Controls/tests/DeviceTests/Elements/TabbedPage/TabbedPageTests.Android.cs
Code:
Assert.True(screenHeight == bottomNavBottom,
$"BottomNavigationView should extend to screen bottom. Expected bottom at {screenHeight}px, but was at {bottomNavBottom}px (gap of {screenHeight - bottomNavBottom}px)");Problem: Pixel-exact equality (==) between BottomNavigationView's bottom and the DecorView's height may fail due to sub-pixel rounding or density differences on some devices/emulators.
Recommendation: Use a small tolerance (e.g., ±1px) to avoid flakiness:
var gap = screenHeight - bottomNavBottom;
Assert.True(Math.Abs(gap) <= 1,
$"BottomNavigationView should extend to screen bottom. Expected bottom at {screenHeight}px, but was at {bottomNavBottom}px (gap of {gap}px)");Or use Assert.Equal(screenHeight, bottomNavBottom) for a cleaner failure message without the tolerance concern.
2. Reconstructed Insets are identical to originals — effectively a pass-through
File: src/Core/src/Platform/Android/MauiWindowInsetListener.cs
Code (lines 291–308):
var newSystemBars = Insets.Of(
systemBars?.Left ?? 0,
systemBars?.Top ?? 0,
systemBars?.Right ?? 0,
systemBars?.Bottom ?? 0
) ?? Insets.None;
var newDisplayCutout = Insets.Of(
displayCutout?.Left ?? 0,
displayCutout?.Top ?? 0,
displayCutout?.Right ?? 0,
displayCutout?.Bottom ?? 0
) ?? Insets.None;Observation: After the fix, newSystemBars and newDisplayCutout are now exact copies of the original values (no values are consumed/zeroed). The Insets reconstruction code is logically equivalent to passing insets unchanged. This isn't a bug, but it's unnecessary complexity that makes the code harder to reason about.
Recommendation (low priority): Simplify to just pass through the original insets:
// Previously consumed certain insets; now all passed through as SafeAreaExtensions handles positioning
return insets;This makes the intent explicit and eliminates the dead Insets-construction code. However, this is purely cosmetic and can be left for a follow-up cleanup.
✅ Looks Good
-
Core fix approach is correct: Moving bottom padding from the root view to
contentViewis the right Android pattern. The root view consuming bottom insets was the root cause ofBottomNavigationViewnot being able to extend into the gesture bar area. -
Removal of
appBarHasContentfrom inset forwarding is justified: The AppBarLayout already applies its own top padding directly (appBarLayout.SetPadding(...)). Consuming top insets in the forwarded values was redundant sinceSafeAreaExtensionsuses screen-position-based overlap detection rather than relying on consumed insets. Passing insets through avoids over-consuming them for child views. -
contentViewpadding includes horizontal insets: The new content-view padding (contentView?.SetPadding(systemBars?.Left ?? 0, 0, systemBars?.Right ?? 0, bottomInset)) correctly includes left/right side insets — an improvement over the old root-view padding that only handled bottom (v.SetPadding(0, 0, 0, bottomInset)). -
Null-safe content view reset: The
elsebranch resetscontentView?.SetPadding(0, 0, 0, 0)to handle the case where bottom navigation is dynamically removed. -
Test is well-structured: The test correctly verifies the end-to-end behavior (BottomNavigationView reaching the screen bottom) rather than just testing an internal API, providing good regression coverage.
kubaflo
left a comment
There was a problem hiding this comment.
Hi @praveenkumarkarunanithi what do you think about the suggestions from AI Summary
…extending to system navigation bar (dotnet#33428) ### Root Cause In Android `Edge-to-Edge` mode, the `MauiWindowInsetListener` was applying padding to the root view and consuming bottom insets. This prevented `BottomNavigationView` from receiving the system navigation bar insets, so it could not extend its background color into the navigation bar area—resulting in a visible gap between the tab bar and the screen edge. ### Description of Change When a `TabbedPage` uses `ToolbarPlacement.Bottom`, the fix applies bottom padding to `contentView` (the fragment container) instead of the root view, and passes bottom insets through without consuming them. This allows `BottomNavigationView` to receive the insets and extend its background color into the system navigation bar area, eliminating the gap. ### Issues Fixed Fixes dotnet#33344 Tested the behaviour in the following platforms - [x] Android - [ ] Windows - [x] iOS - [ ] Mac **Note:** This issue is Android-specific. Windows and macOS do not have a system navigation bar area at the bottom of the screen. ### Screenshots | Before Issue Fix | After Issue Fix | |------------------|-----------------| | <img width="350" alt="withoutfix" src="https://github.com/user-attachments/assets/878a0361-c0cd-4621-a063-94bbc757d15c" /> | <img width="350" alt="withfix" src="https://github.com/user-attachments/assets/ed552f1e-d75f-4275-856a-b8bf993a0dcd" /> |
…extending to system navigation bar (#33428) ### Root Cause In Android `Edge-to-Edge` mode, the `MauiWindowInsetListener` was applying padding to the root view and consuming bottom insets. This prevented `BottomNavigationView` from receiving the system navigation bar insets, so it could not extend its background color into the navigation bar area—resulting in a visible gap between the tab bar and the screen edge. ### Description of Change When a `TabbedPage` uses `ToolbarPlacement.Bottom`, the fix applies bottom padding to `contentView` (the fragment container) instead of the root view, and passes bottom insets through without consuming them. This allows `BottomNavigationView` to receive the insets and extend its background color into the system navigation bar area, eliminating the gap. ### Issues Fixed Fixes #33344 Tested the behaviour in the following platforms - [x] Android - [ ] Windows - [x] iOS - [ ] Mac **Note:** This issue is Android-specific. Windows and macOS do not have a system navigation bar area at the bottom of the screen. ### Screenshots | Before Issue Fix | After Issue Fix | |------------------|-----------------| | <img width="350" alt="withoutfix" src="https://github.com/user-attachments/assets/878a0361-c0cd-4621-a063-94bbc757d15c" /> | <img width="350" alt="withfix" src="https://github.com/user-attachments/assets/ed552f1e-d75f-4275-856a-b8bf993a0dcd" /> |
…extending to system navigation bar (#33428) ### Root Cause In Android `Edge-to-Edge` mode, the `MauiWindowInsetListener` was applying padding to the root view and consuming bottom insets. This prevented `BottomNavigationView` from receiving the system navigation bar insets, so it could not extend its background color into the navigation bar area—resulting in a visible gap between the tab bar and the screen edge. ### Description of Change When a `TabbedPage` uses `ToolbarPlacement.Bottom`, the fix applies bottom padding to `contentView` (the fragment container) instead of the root view, and passes bottom insets through without consuming them. This allows `BottomNavigationView` to receive the insets and extend its background color into the system navigation bar area, eliminating the gap. ### Issues Fixed Fixes #33344 Tested the behaviour in the following platforms - [x] Android - [ ] Windows - [x] iOS - [ ] Mac **Note:** This issue is Android-specific. Windows and macOS do not have a system navigation bar area at the bottom of the screen. ### Screenshots | Before Issue Fix | After Issue Fix | |------------------|-----------------| | <img width="350" alt="withoutfix" src="https://github.com/user-attachments/assets/878a0361-c0cd-4621-a063-94bbc757d15c" /> | <img width="350" alt="withfix" src="https://github.com/user-attachments/assets/ed552f1e-d75f-4275-856a-b8bf993a0dcd" /> |
<!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### RootCause of the issue - In PR #33428, the WindowInsetsCompat.Builder block in MauiWindowInsetListener.ApplyDefaultWindowInsets was simplified to return insets; to standardize inset handling. This change was unrelated to the actual fix for #33344, which only required passing the bottom inset through as unconsumed. As part of that refactor, top inset consumption was also removed, changing the prior contract where the top inset was consumed when appBarHasContent = true. While normal safe-area scenarios worked correctly, transient layout states (e.g., temporary Height = 0 during keyboard dismissal, rotation, animation, or dynamic item generation) triggered a second inset dispatch. In those moments, the top inset satisfied the overlap condition and was applied to content before SafeAreaExtensions could normalize it, causing test failures. Bottom insets did not regress because their overlap condition cannot be met in the same transient state. ### Description of Change - Restored the original behavior by consuming the top inset when appBarHasContent = true, while continuing to pass the bottom inset through unconsumed (the only change required for #33344). This retains the Android edge-to-edge fix and restores deterministic safe-area handling. ### Test failures - EntryScrollTest, HorizontalStackLayout_Spacing_WithLandscape, VerticalStackLayout_Spacing_WithLandscape, VerifyBindableLayoutWithGridItemTemplate - (EntryScrollTest)Test fails due to #33428 this PR ### Issues Fixed Fixes #34509
<!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### RootCause of the issue - In PR dotnet#33428, the WindowInsetsCompat.Builder block in MauiWindowInsetListener.ApplyDefaultWindowInsets was simplified to return insets; to standardize inset handling. This change was unrelated to the actual fix for dotnet#33344, which only required passing the bottom inset through as unconsumed. As part of that refactor, top inset consumption was also removed, changing the prior contract where the top inset was consumed when appBarHasContent = true. While normal safe-area scenarios worked correctly, transient layout states (e.g., temporary Height = 0 during keyboard dismissal, rotation, animation, or dynamic item generation) triggered a second inset dispatch. In those moments, the top inset satisfied the overlap condition and was applied to content before SafeAreaExtensions could normalize it, causing test failures. Bottom insets did not regress because their overlap condition cannot be met in the same transient state. ### Description of Change - Restored the original behavior by consuming the top inset when appBarHasContent = true, while continuing to pass the bottom inset through unconsumed (the only change required for dotnet#33344). This retains the Android edge-to-edge fix and restores deterministic safe-area handling. ### Test failures - EntryScrollTest, HorizontalStackLayout_Spacing_WithLandscape, VerticalStackLayout_Spacing_WithLandscape, VerifyBindableLayoutWithGridItemTemplate - (EntryScrollTest)Test fails due to dotnet#33428 this PR ### Issues Fixed Fixes dotnet#34509
…extending to system navigation bar (#33428) ### Root Cause In Android `Edge-to-Edge` mode, the `MauiWindowInsetListener` was applying padding to the root view and consuming bottom insets. This prevented `BottomNavigationView` from receiving the system navigation bar insets, so it could not extend its background color into the navigation bar area—resulting in a visible gap between the tab bar and the screen edge. ### Description of Change When a `TabbedPage` uses `ToolbarPlacement.Bottom`, the fix applies bottom padding to `contentView` (the fragment container) instead of the root view, and passes bottom insets through without consuming them. This allows `BottomNavigationView` to receive the insets and extend its background color into the system navigation bar area, eliminating the gap. ### Issues Fixed Fixes #33344 Tested the behaviour in the following platforms - [x] Android - [ ] Windows - [x] iOS - [ ] Mac **Note:** This issue is Android-specific. Windows and macOS do not have a system navigation bar area at the bottom of the screen. ### Screenshots | Before Issue Fix | After Issue Fix | |------------------|-----------------| | <img width="350" alt="withoutfix" src="https://github.com/user-attachments/assets/878a0361-c0cd-4621-a063-94bbc757d15c" /> | <img width="350" alt="withfix" src="https://github.com/user-attachments/assets/ed552f1e-d75f-4275-856a-b8bf993a0dcd" /> |
### Root Cause of the issue - The failing test: `SetVisibility(Visibility.Collapsed)` device test on iOS. Why it fails: PR #28983's fix maps Visibility → MapIsRunning in ActivityIndicatorHandler, which bypasses the standard ViewExtensions.UpdateVisibility path. The standard path calls Collapse() to add a CollapseConstraint (an NSLayoutConstraint that zeros the view's size). The PR's UpdateIsRunning only sets Hidden = true — it never calls Collapse() - Crash in the FeatureMatrix Navigation Page Scenario in the iOS 26 PR #34326 added an else block in UpdateBarTextColor() that explicitly sets BackButtonAppearance = null, BackIndicatorImage = null, and BackIndicatorTransitionMaskImage = null on the navigation bar when no custom color is applied. On iOS versions before 26, assigning null to these properties was treated as "use system defaults." On iOS 26, the Liquid Glass rendering pipeline reads these properties during push/pop navigation transitions and throws an exception when it encounters an explicit null — it expects either an unset property or a valid object. Since useCustomColor is false by default (no IconColor set), this crashes on every standard page navigation. - Setting ThumbTintList = null in the else block removes the tint entirely, causing the thumb to appear white instead of the default blue, because SwitchCompat does not re-resolve its theme colors once the tint list is cleared. - SetAdjustViewBounds(false) was being applied to all images regardless of their Aspect value. When this property is false, Android’s ImageView does not resize itself based on the image’s intrinsic aspect ratio and instead expands to fill the available space. As a result, an Image control with the default AspectFit setting ignored its height constraint and overflowed its container, causing the image to appear taller than expected in the screenshot test.(LoadAndVerifyGif, ThemeRelated feature tests) - PR #29144 changed the group-detection guard in ObservableGroupedSource (iOS and Android) from is IEnumerable to is ICollection to prevent strings (which implement IEnumerable<char>) from being treated as groups. While the intent was correct, the change was too broad. Custom group types that implement only IEnumerable<T> were also excluded. As a result, _groupCount became zero on iOS and _groups remained empty on Android, causing grouped CollectionView rendering failures and IndexOutOfRangeException during Add/Remove operations. - StepperHandler.iOS.cs compiles for both iOS and Mac Catalyst. On Mac Catalyst / macOS 26, OperatingSystem.IsIOS() and IsIOSVersionAtLeast(26) both return true, and the screen is always landscape. As a result, the 20pt glass pill compensation was incorrectly applied, inflating GetDesiredSize(1,1) to width = 21. (Native View Bounding Box is not empty - device Test failures) - In PR #33428, the WindowInsetsCompat.Builder block in MauiWindowInsetListener.ApplyDefaultWindowInsets was simplified to return insets; to standardize inset handling. This change was unrelated to the actual fix for #33344, which only required passing the bottom inset through as unconsumed. As part of that refactor, top inset consumption was also removed, changing the prior contract where the top inset was consumed when appBarHasContent = true. While normal safe-area scenarios worked correctly, transient layout states (e.g., temporary Height = 0 during keyboard dismissal, rotation, animation, or dynamic item generation) triggered a second inset dispatch. In those moments, the top inset satisfied the overlap condition and was applied to content before SafeAreaExtensions could normalize it, causing test failures. Bottom insets did not regress because their overlap condition cannot be met in the same transient state. (EntryScrollTest, HorizontalStackLayout_Spacing_WithLandscape, VerticalStackLayout_Spacing_WithLandscape and so on failures) ### Description of Change - Handles the three Visibility cases the same way as ViewExtensions.UpdateVisibility: `Visible`: Calls Inflate() (restores layout size) and sets Hidden = false — identical to UpdateVisibility. Additionally starts/stops the animation based on IsRunning. `Hidden`: Calls Inflate() (preserves layout space) and sets Hidden = true — identical to UpdateVisibility. The indicator keeps its layout footprint but is invisible. `Collapsed`: Sets Hidden = true and calls Collapse() (zeros out layout size via constraints) — identical to UpdateVisibility. The indicator is both invisible and takes up no space. - Removed the else block entirely. When no custom color is applied, these properties should remain untouched. The system defaults work correctly on their own — there is no need to explicitly reset them to null - Removed the else block from UpdateThumbColor in SwitchExtensions.cs. The default thumb color is managed by SwitchCompat internally from the Material theme, so no explicit reset is needed. - Restored the correct logic in ImageViewExtensions.UpdateAspect to call SetAdjustViewBounds based on the image’s Aspect value: - The guard has been updated from is ICollection to is IEnumerable && not string in the ObservableGroupedSource implementations for both iOS and Android (GroupsCount(), UpdateGroupTracking(), Add(), Remove()). This change specifically excludes string while allowing legitimate custom group types that implement only IEnumerable<T>. The fix restores the behavior for Issue22320 while keeping all Issue29141 scenarios working correctly. -Added !OperatingSystem.IsMacCatalyst() to the guard condition in GetDesiredSize, restricting the 20pt compensation to real iOS 26+ only — as intended in the original PR comment. - Restored the original behavior by consuming the top inset when appBarHasContent = true, while continuing to pass the bottom inset through unconsumed (the only change required for #33344). This retains the Android edge-to-edge fix and restores deterministic safe-area handling. ### Testing related description of change EditorNoOverlapAfterRotateToLandscape, EditorNoOverlapAfterRotateToPortrait, EntryFocusedShouldNotCauseGapAfterRotation Added cropLeft to remove the navbar on Android and re-saved the image due to entry text changes in this commit – 8d17a6d, 91047fb. DrawStringShouldDrawText – The automation ID set to GraphicsView was not found by Appium on the Windows platform, so a test condition was added for Windows to take the image directly instead of waiting for the GraphicsView. Added the base images for iOS 26 and Mac that were not added previously. Re-saved the images that failed due to the wrong iOS version image being added in the PR. Re-saved the test images that failed due to this fix PR: #31254 — e.g., GraphicsViewFeatureTests and others. Resaved the slider-related test images due to this fix PR — #34064. ### Issues Fixed Fixes #34437 ### Tested the behaviour in the following platforms - [x] iOS - [x] Mac --------- Co-authored-by: SyedAbdulAzeem <syedabdulazeem.a@syncfusion.com> Co-authored-by: Vignesh-SF3580 <102575140+Vignesh-SF3580@users.noreply.github.com> Co-authored-by: TamilarasanSF4853 <tamilarasan.velu@syncfusion.com> Co-authored-by: LogishaSelvarajSF4525 <logisha.selvaraj@syncfusion.com>
…extending to system navigation bar (#33428) ### Root Cause In Android `Edge-to-Edge` mode, the `MauiWindowInsetListener` was applying padding to the root view and consuming bottom insets. This prevented `BottomNavigationView` from receiving the system navigation bar insets, so it could not extend its background color into the navigation bar area—resulting in a visible gap between the tab bar and the screen edge. ### Description of Change When a `TabbedPage` uses `ToolbarPlacement.Bottom`, the fix applies bottom padding to `contentView` (the fragment container) instead of the root view, and passes bottom insets through without consuming them. This allows `BottomNavigationView` to receive the insets and extend its background color into the system navigation bar area, eliminating the gap. ### Issues Fixed Fixes #33344 Tested the behaviour in the following platforms - [x] Android - [ ] Windows - [x] iOS - [ ] Mac **Note:** This issue is Android-specific. Windows and macOS do not have a system navigation bar area at the bottom of the screen. ### Screenshots | Before Issue Fix | After Issue Fix | |------------------|-----------------| | <img width="350" alt="withoutfix" src="https://github.com/user-attachments/assets/878a0361-c0cd-4621-a063-94bbc757d15c" /> | <img width="350" alt="withfix" src="https://github.com/user-attachments/assets/ed552f1e-d75f-4275-856a-b8bf993a0dcd" /> |
<!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### RootCause of the issue - In PR #33428, the WindowInsetsCompat.Builder block in MauiWindowInsetListener.ApplyDefaultWindowInsets was simplified to return insets; to standardize inset handling. This change was unrelated to the actual fix for #33344, which only required passing the bottom inset through as unconsumed. As part of that refactor, top inset consumption was also removed, changing the prior contract where the top inset was consumed when appBarHasContent = true. While normal safe-area scenarios worked correctly, transient layout states (e.g., temporary Height = 0 during keyboard dismissal, rotation, animation, or dynamic item generation) triggered a second inset dispatch. In those moments, the top inset satisfied the overlap condition and was applied to content before SafeAreaExtensions could normalize it, causing test failures. Bottom insets did not regress because their overlap condition cannot be met in the same transient state. ### Description of Change - Restored the original behavior by consuming the top inset when appBarHasContent = true, while continuing to pass the bottom inset through unconsumed (the only change required for #33344). This retains the Android edge-to-edge fix and restores deterministic safe-area handling. ### Test failures - EntryScrollTest, HorizontalStackLayout_Spacing_WithLandscape, VerticalStackLayout_Spacing_WithLandscape, VerifyBindableLayoutWithGridItemTemplate - (EntryScrollTest)Test fails due to #33428 this PR ### Issues Fixed Fixes #34509
### Root Cause of the issue - The failing test: `SetVisibility(Visibility.Collapsed)` device test on iOS. Why it fails: PR #28983's fix maps Visibility → MapIsRunning in ActivityIndicatorHandler, which bypasses the standard ViewExtensions.UpdateVisibility path. The standard path calls Collapse() to add a CollapseConstraint (an NSLayoutConstraint that zeros the view's size). The PR's UpdateIsRunning only sets Hidden = true — it never calls Collapse() - Crash in the FeatureMatrix Navigation Page Scenario in the iOS 26 PR #34326 added an else block in UpdateBarTextColor() that explicitly sets BackButtonAppearance = null, BackIndicatorImage = null, and BackIndicatorTransitionMaskImage = null on the navigation bar when no custom color is applied. On iOS versions before 26, assigning null to these properties was treated as "use system defaults." On iOS 26, the Liquid Glass rendering pipeline reads these properties during push/pop navigation transitions and throws an exception when it encounters an explicit null — it expects either an unset property or a valid object. Since useCustomColor is false by default (no IconColor set), this crashes on every standard page navigation. - Setting ThumbTintList = null in the else block removes the tint entirely, causing the thumb to appear white instead of the default blue, because SwitchCompat does not re-resolve its theme colors once the tint list is cleared. - SetAdjustViewBounds(false) was being applied to all images regardless of their Aspect value. When this property is false, Android’s ImageView does not resize itself based on the image’s intrinsic aspect ratio and instead expands to fill the available space. As a result, an Image control with the default AspectFit setting ignored its height constraint and overflowed its container, causing the image to appear taller than expected in the screenshot test.(LoadAndVerifyGif, ThemeRelated feature tests) - PR #29144 changed the group-detection guard in ObservableGroupedSource (iOS and Android) from is IEnumerable to is ICollection to prevent strings (which implement IEnumerable<char>) from being treated as groups. While the intent was correct, the change was too broad. Custom group types that implement only IEnumerable<T> were also excluded. As a result, _groupCount became zero on iOS and _groups remained empty on Android, causing grouped CollectionView rendering failures and IndexOutOfRangeException during Add/Remove operations. - StepperHandler.iOS.cs compiles for both iOS and Mac Catalyst. On Mac Catalyst / macOS 26, OperatingSystem.IsIOS() and IsIOSVersionAtLeast(26) both return true, and the screen is always landscape. As a result, the 20pt glass pill compensation was incorrectly applied, inflating GetDesiredSize(1,1) to width = 21. (Native View Bounding Box is not empty - device Test failures) - In PR #33428, the WindowInsetsCompat.Builder block in MauiWindowInsetListener.ApplyDefaultWindowInsets was simplified to return insets; to standardize inset handling. This change was unrelated to the actual fix for #33344, which only required passing the bottom inset through as unconsumed. As part of that refactor, top inset consumption was also removed, changing the prior contract where the top inset was consumed when appBarHasContent = true. While normal safe-area scenarios worked correctly, transient layout states (e.g., temporary Height = 0 during keyboard dismissal, rotation, animation, or dynamic item generation) triggered a second inset dispatch. In those moments, the top inset satisfied the overlap condition and was applied to content before SafeAreaExtensions could normalize it, causing test failures. Bottom insets did not regress because their overlap condition cannot be met in the same transient state. (EntryScrollTest, HorizontalStackLayout_Spacing_WithLandscape, VerticalStackLayout_Spacing_WithLandscape and so on failures) ### Description of Change - Handles the three Visibility cases the same way as ViewExtensions.UpdateVisibility: `Visible`: Calls Inflate() (restores layout size) and sets Hidden = false — identical to UpdateVisibility. Additionally starts/stops the animation based on IsRunning. `Hidden`: Calls Inflate() (preserves layout space) and sets Hidden = true — identical to UpdateVisibility. The indicator keeps its layout footprint but is invisible. `Collapsed`: Sets Hidden = true and calls Collapse() (zeros out layout size via constraints) — identical to UpdateVisibility. The indicator is both invisible and takes up no space. - Removed the else block entirely. When no custom color is applied, these properties should remain untouched. The system defaults work correctly on their own — there is no need to explicitly reset them to null - Removed the else block from UpdateThumbColor in SwitchExtensions.cs. The default thumb color is managed by SwitchCompat internally from the Material theme, so no explicit reset is needed. - Restored the correct logic in ImageViewExtensions.UpdateAspect to call SetAdjustViewBounds based on the image’s Aspect value: - The guard has been updated from is ICollection to is IEnumerable && not string in the ObservableGroupedSource implementations for both iOS and Android (GroupsCount(), UpdateGroupTracking(), Add(), Remove()). This change specifically excludes string while allowing legitimate custom group types that implement only IEnumerable<T>. The fix restores the behavior for Issue22320 while keeping all Issue29141 scenarios working correctly. -Added !OperatingSystem.IsMacCatalyst() to the guard condition in GetDesiredSize, restricting the 20pt compensation to real iOS 26+ only — as intended in the original PR comment. - Restored the original behavior by consuming the top inset when appBarHasContent = true, while continuing to pass the bottom inset through unconsumed (the only change required for #33344). This retains the Android edge-to-edge fix and restores deterministic safe-area handling. ### Testing related description of change EditorNoOverlapAfterRotateToLandscape, EditorNoOverlapAfterRotateToPortrait, EntryFocusedShouldNotCauseGapAfterRotation Added cropLeft to remove the navbar on Android and re-saved the image due to entry text changes in this commit – 8d17a6d, 91047fb. DrawStringShouldDrawText – The automation ID set to GraphicsView was not found by Appium on the Windows platform, so a test condition was added for Windows to take the image directly instead of waiting for the GraphicsView. Added the base images for iOS 26 and Mac that were not added previously. Re-saved the images that failed due to the wrong iOS version image being added in the PR. Re-saved the test images that failed due to this fix PR: #31254 — e.g., GraphicsViewFeatureTests and others. Resaved the slider-related test images due to this fix PR — #34064. ### Issues Fixed Fixes #34437 ### Tested the behaviour in the following platforms - [x] iOS - [x] Mac --------- Co-authored-by: SyedAbdulAzeem <syedabdulazeem.a@syncfusion.com> Co-authored-by: Vignesh-SF3580 <102575140+Vignesh-SF3580@users.noreply.github.com> Co-authored-by: TamilarasanSF4853 <tamilarasan.velu@syncfusion.com> Co-authored-by: LogishaSelvarajSF4525 <logisha.selvaraj@syncfusion.com>
…extending to system navigation bar (#33428) ### Root Cause In Android `Edge-to-Edge` mode, the `MauiWindowInsetListener` was applying padding to the root view and consuming bottom insets. This prevented `BottomNavigationView` from receiving the system navigation bar insets, so it could not extend its background color into the navigation bar area—resulting in a visible gap between the tab bar and the screen edge. ### Description of Change When a `TabbedPage` uses `ToolbarPlacement.Bottom`, the fix applies bottom padding to `contentView` (the fragment container) instead of the root view, and passes bottom insets through without consuming them. This allows `BottomNavigationView` to receive the insets and extend its background color into the system navigation bar area, eliminating the gap. ### Issues Fixed Fixes #33344 Tested the behaviour in the following platforms - [x] Android - [ ] Windows - [x] iOS - [ ] Mac **Note:** This issue is Android-specific. Windows and macOS do not have a system navigation bar area at the bottom of the screen. ### Screenshots | Before Issue Fix | After Issue Fix | |------------------|-----------------| | <img width="350" alt="withoutfix" src="https://github.com/user-attachments/assets/878a0361-c0cd-4621-a063-94bbc757d15c" /> | <img width="350" alt="withfix" src="https://github.com/user-attachments/assets/ed552f1e-d75f-4275-856a-b8bf993a0dcd" /> |
<!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### RootCause of the issue - In PR #33428, the WindowInsetsCompat.Builder block in MauiWindowInsetListener.ApplyDefaultWindowInsets was simplified to return insets; to standardize inset handling. This change was unrelated to the actual fix for #33344, which only required passing the bottom inset through as unconsumed. As part of that refactor, top inset consumption was also removed, changing the prior contract where the top inset was consumed when appBarHasContent = true. While normal safe-area scenarios worked correctly, transient layout states (e.g., temporary Height = 0 during keyboard dismissal, rotation, animation, or dynamic item generation) triggered a second inset dispatch. In those moments, the top inset satisfied the overlap condition and was applied to content before SafeAreaExtensions could normalize it, causing test failures. Bottom insets did not regress because their overlap condition cannot be met in the same transient state. ### Description of Change - Restored the original behavior by consuming the top inset when appBarHasContent = true, while continuing to pass the bottom inset through unconsumed (the only change required for #33344). This retains the Android edge-to-edge fix and restores deterministic safe-area handling. ### Test failures - EntryScrollTest, HorizontalStackLayout_Spacing_WithLandscape, VerticalStackLayout_Spacing_WithLandscape, VerifyBindableLayoutWithGridItemTemplate - (EntryScrollTest)Test fails due to #33428 this PR ### Issues Fixed Fixes #34509
### Root Cause of the issue - The failing test: `SetVisibility(Visibility.Collapsed)` device test on iOS. Why it fails: PR #28983's fix maps Visibility → MapIsRunning in ActivityIndicatorHandler, which bypasses the standard ViewExtensions.UpdateVisibility path. The standard path calls Collapse() to add a CollapseConstraint (an NSLayoutConstraint that zeros the view's size). The PR's UpdateIsRunning only sets Hidden = true — it never calls Collapse() - Crash in the FeatureMatrix Navigation Page Scenario in the iOS 26 PR #34326 added an else block in UpdateBarTextColor() that explicitly sets BackButtonAppearance = null, BackIndicatorImage = null, and BackIndicatorTransitionMaskImage = null on the navigation bar when no custom color is applied. On iOS versions before 26, assigning null to these properties was treated as "use system defaults." On iOS 26, the Liquid Glass rendering pipeline reads these properties during push/pop navigation transitions and throws an exception when it encounters an explicit null — it expects either an unset property or a valid object. Since useCustomColor is false by default (no IconColor set), this crashes on every standard page navigation. - Setting ThumbTintList = null in the else block removes the tint entirely, causing the thumb to appear white instead of the default blue, because SwitchCompat does not re-resolve its theme colors once the tint list is cleared. - SetAdjustViewBounds(false) was being applied to all images regardless of their Aspect value. When this property is false, Android’s ImageView does not resize itself based on the image’s intrinsic aspect ratio and instead expands to fill the available space. As a result, an Image control with the default AspectFit setting ignored its height constraint and overflowed its container, causing the image to appear taller than expected in the screenshot test.(LoadAndVerifyGif, ThemeRelated feature tests) - PR #29144 changed the group-detection guard in ObservableGroupedSource (iOS and Android) from is IEnumerable to is ICollection to prevent strings (which implement IEnumerable<char>) from being treated as groups. While the intent was correct, the change was too broad. Custom group types that implement only IEnumerable<T> were also excluded. As a result, _groupCount became zero on iOS and _groups remained empty on Android, causing grouped CollectionView rendering failures and IndexOutOfRangeException during Add/Remove operations. - StepperHandler.iOS.cs compiles for both iOS and Mac Catalyst. On Mac Catalyst / macOS 26, OperatingSystem.IsIOS() and IsIOSVersionAtLeast(26) both return true, and the screen is always landscape. As a result, the 20pt glass pill compensation was incorrectly applied, inflating GetDesiredSize(1,1) to width = 21. (Native View Bounding Box is not empty - device Test failures) - In PR #33428, the WindowInsetsCompat.Builder block in MauiWindowInsetListener.ApplyDefaultWindowInsets was simplified to return insets; to standardize inset handling. This change was unrelated to the actual fix for #33344, which only required passing the bottom inset through as unconsumed. As part of that refactor, top inset consumption was also removed, changing the prior contract where the top inset was consumed when appBarHasContent = true. While normal safe-area scenarios worked correctly, transient layout states (e.g., temporary Height = 0 during keyboard dismissal, rotation, animation, or dynamic item generation) triggered a second inset dispatch. In those moments, the top inset satisfied the overlap condition and was applied to content before SafeAreaExtensions could normalize it, causing test failures. Bottom insets did not regress because their overlap condition cannot be met in the same transient state. (EntryScrollTest, HorizontalStackLayout_Spacing_WithLandscape, VerticalStackLayout_Spacing_WithLandscape and so on failures) ### Description of Change - Handles the three Visibility cases the same way as ViewExtensions.UpdateVisibility: `Visible`: Calls Inflate() (restores layout size) and sets Hidden = false — identical to UpdateVisibility. Additionally starts/stops the animation based on IsRunning. `Hidden`: Calls Inflate() (preserves layout space) and sets Hidden = true — identical to UpdateVisibility. The indicator keeps its layout footprint but is invisible. `Collapsed`: Sets Hidden = true and calls Collapse() (zeros out layout size via constraints) — identical to UpdateVisibility. The indicator is both invisible and takes up no space. - Removed the else block entirely. When no custom color is applied, these properties should remain untouched. The system defaults work correctly on their own — there is no need to explicitly reset them to null - Removed the else block from UpdateThumbColor in SwitchExtensions.cs. The default thumb color is managed by SwitchCompat internally from the Material theme, so no explicit reset is needed. - Restored the correct logic in ImageViewExtensions.UpdateAspect to call SetAdjustViewBounds based on the image’s Aspect value: - The guard has been updated from is ICollection to is IEnumerable && not string in the ObservableGroupedSource implementations for both iOS and Android (GroupsCount(), UpdateGroupTracking(), Add(), Remove()). This change specifically excludes string while allowing legitimate custom group types that implement only IEnumerable<T>. The fix restores the behavior for Issue22320 while keeping all Issue29141 scenarios working correctly. -Added !OperatingSystem.IsMacCatalyst() to the guard condition in GetDesiredSize, restricting the 20pt compensation to real iOS 26+ only — as intended in the original PR comment. - Restored the original behavior by consuming the top inset when appBarHasContent = true, while continuing to pass the bottom inset through unconsumed (the only change required for #33344). This retains the Android edge-to-edge fix and restores deterministic safe-area handling. ### Testing related description of change EditorNoOverlapAfterRotateToLandscape, EditorNoOverlapAfterRotateToPortrait, EntryFocusedShouldNotCauseGapAfterRotation Added cropLeft to remove the navbar on Android and re-saved the image due to entry text changes in this commit – 8d17a6d, 91047fb. DrawStringShouldDrawText – The automation ID set to GraphicsView was not found by Appium on the Windows platform, so a test condition was added for Windows to take the image directly instead of waiting for the GraphicsView. Added the base images for iOS 26 and Mac that were not added previously. Re-saved the images that failed due to the wrong iOS version image being added in the PR. Re-saved the test images that failed due to this fix PR: #31254 — e.g., GraphicsViewFeatureTests and others. Resaved the slider-related test images due to this fix PR — #34064. ### Issues Fixed Fixes #34437 ### Tested the behaviour in the following platforms - [x] iOS - [x] Mac --------- Co-authored-by: SyedAbdulAzeem <syedabdulazeem.a@syncfusion.com> Co-authored-by: Vignesh-SF3580 <102575140+Vignesh-SF3580@users.noreply.github.com> Co-authored-by: TamilarasanSF4853 <tamilarasan.velu@syncfusion.com> Co-authored-by: LogishaSelvarajSF4525 <logisha.selvaraj@syncfusion.com>
<!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### RootCause of the issue - In PR dotnet#33428, the WindowInsetsCompat.Builder block in MauiWindowInsetListener.ApplyDefaultWindowInsets was simplified to return insets; to standardize inset handling. This change was unrelated to the actual fix for dotnet#33344, which only required passing the bottom inset through as unconsumed. As part of that refactor, top inset consumption was also removed, changing the prior contract where the top inset was consumed when appBarHasContent = true. While normal safe-area scenarios worked correctly, transient layout states (e.g., temporary Height = 0 during keyboard dismissal, rotation, animation, or dynamic item generation) triggered a second inset dispatch. In those moments, the top inset satisfied the overlap condition and was applied to content before SafeAreaExtensions could normalize it, causing test failures. Bottom insets did not regress because their overlap condition cannot be met in the same transient state. ### Description of Change - Restored the original behavior by consuming the top inset when appBarHasContent = true, while continuing to pass the bottom inset through unconsumed (the only change required for dotnet#33344). This retains the Android edge-to-edge fix and restores deterministic safe-area handling. ### Test failures - EntryScrollTest, HorizontalStackLayout_Spacing_WithLandscape, VerticalStackLayout_Spacing_WithLandscape, VerifyBindableLayoutWithGridItemTemplate - (EntryScrollTest)Test fails due to dotnet#33428 this PR ### Issues Fixed Fixes dotnet#34509
- The failing test: `SetVisibility(Visibility.Collapsed)` device test on iOS. Why it fails: PR dotnet#28983's fix maps Visibility → MapIsRunning in ActivityIndicatorHandler, which bypasses the standard ViewExtensions.UpdateVisibility path. The standard path calls Collapse() to add a CollapseConstraint (an NSLayoutConstraint that zeros the view's size). The PR's UpdateIsRunning only sets Hidden = true — it never calls Collapse() - Crash in the FeatureMatrix Navigation Page Scenario in the iOS 26 PR dotnet#34326 added an else block in UpdateBarTextColor() that explicitly sets BackButtonAppearance = null, BackIndicatorImage = null, and BackIndicatorTransitionMaskImage = null on the navigation bar when no custom color is applied. On iOS versions before 26, assigning null to these properties was treated as "use system defaults." On iOS 26, the Liquid Glass rendering pipeline reads these properties during push/pop navigation transitions and throws an exception when it encounters an explicit null — it expects either an unset property or a valid object. Since useCustomColor is false by default (no IconColor set), this crashes on every standard page navigation. - Setting ThumbTintList = null in the else block removes the tint entirely, causing the thumb to appear white instead of the default blue, because SwitchCompat does not re-resolve its theme colors once the tint list is cleared. - SetAdjustViewBounds(false) was being applied to all images regardless of their Aspect value. When this property is false, Android’s ImageView does not resize itself based on the image’s intrinsic aspect ratio and instead expands to fill the available space. As a result, an Image control with the default AspectFit setting ignored its height constraint and overflowed its container, causing the image to appear taller than expected in the screenshot test.(LoadAndVerifyGif, ThemeRelated feature tests) - PR dotnet#29144 changed the group-detection guard in ObservableGroupedSource (iOS and Android) from is IEnumerable to is ICollection to prevent strings (which implement IEnumerable<char>) from being treated as groups. While the intent was correct, the change was too broad. Custom group types that implement only IEnumerable<T> were also excluded. As a result, _groupCount became zero on iOS and _groups remained empty on Android, causing grouped CollectionView rendering failures and IndexOutOfRangeException during Add/Remove operations. - StepperHandler.iOS.cs compiles for both iOS and Mac Catalyst. On Mac Catalyst / macOS 26, OperatingSystem.IsIOS() and IsIOSVersionAtLeast(26) both return true, and the screen is always landscape. As a result, the 20pt glass pill compensation was incorrectly applied, inflating GetDesiredSize(1,1) to width = 21. (Native View Bounding Box is not empty - device Test failures) - In PR dotnet#33428, the WindowInsetsCompat.Builder block in MauiWindowInsetListener.ApplyDefaultWindowInsets was simplified to return insets; to standardize inset handling. This change was unrelated to the actual fix for dotnet#33344, which only required passing the bottom inset through as unconsumed. As part of that refactor, top inset consumption was also removed, changing the prior contract where the top inset was consumed when appBarHasContent = true. While normal safe-area scenarios worked correctly, transient layout states (e.g., temporary Height = 0 during keyboard dismissal, rotation, animation, or dynamic item generation) triggered a second inset dispatch. In those moments, the top inset satisfied the overlap condition and was applied to content before SafeAreaExtensions could normalize it, causing test failures. Bottom insets did not regress because their overlap condition cannot be met in the same transient state. (EntryScrollTest, HorizontalStackLayout_Spacing_WithLandscape, VerticalStackLayout_Spacing_WithLandscape and so on failures) - Handles the three Visibility cases the same way as ViewExtensions.UpdateVisibility: `Visible`: Calls Inflate() (restores layout size) and sets Hidden = false — identical to UpdateVisibility. Additionally starts/stops the animation based on IsRunning. `Hidden`: Calls Inflate() (preserves layout space) and sets Hidden = true — identical to UpdateVisibility. The indicator keeps its layout footprint but is invisible. `Collapsed`: Sets Hidden = true and calls Collapse() (zeros out layout size via constraints) — identical to UpdateVisibility. The indicator is both invisible and takes up no space. - Removed the else block entirely. When no custom color is applied, these properties should remain untouched. The system defaults work correctly on their own — there is no need to explicitly reset them to null - Removed the else block from UpdateThumbColor in SwitchExtensions.cs. The default thumb color is managed by SwitchCompat internally from the Material theme, so no explicit reset is needed. - Restored the correct logic in ImageViewExtensions.UpdateAspect to call SetAdjustViewBounds based on the image’s Aspect value: - The guard has been updated from is ICollection to is IEnumerable && not string in the ObservableGroupedSource implementations for both iOS and Android (GroupsCount(), UpdateGroupTracking(), Add(), Remove()). This change specifically excludes string while allowing legitimate custom group types that implement only IEnumerable<T>. The fix restores the behavior for Issue22320 while keeping all Issue29141 scenarios working correctly. -Added !OperatingSystem.IsMacCatalyst() to the guard condition in GetDesiredSize, restricting the 20pt compensation to real iOS 26+ only — as intended in the original PR comment. - Restored the original behavior by consuming the top inset when appBarHasContent = true, while continuing to pass the bottom inset through unconsumed (the only change required for dotnet#33344). This retains the Android edge-to-edge fix and restores deterministic safe-area handling. EditorNoOverlapAfterRotateToLandscape, EditorNoOverlapAfterRotateToPortrait, EntryFocusedShouldNotCauseGapAfterRotation Added cropLeft to remove the navbar on Android and re-saved the image due to entry text changes in this commit – dotnet@8d17a6d, dotnet@91047fb. DrawStringShouldDrawText – The automation ID set to GraphicsView was not found by Appium on the Windows platform, so a test condition was added for Windows to take the image directly instead of waiting for the GraphicsView. Added the base images for iOS 26 and Mac that were not added previously. Re-saved the images that failed due to the wrong iOS version image being added in the PR. Re-saved the test images that failed due to this fix PR: dotnet#31254 — e.g., GraphicsViewFeatureTests and others. Resaved the slider-related test images due to this fix PR — dotnet#34064. Fixes dotnet#34437 - [x] iOS - [x] Mac --------- Co-authored-by: SyedAbdulAzeem <syedabdulazeem.a@syncfusion.com> Co-authored-by: Vignesh-SF3580 <102575140+Vignesh-SF3580@users.noreply.github.com> Co-authored-by: TamilarasanSF4853 <tamilarasan.velu@syncfusion.com> Co-authored-by: LogishaSelvarajSF4525 <logisha.selvaraj@syncfusion.com>
<!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### RootCause of the issue - In PR dotnet#33428, the WindowInsetsCompat.Builder block in MauiWindowInsetListener.ApplyDefaultWindowInsets was simplified to return insets; to standardize inset handling. This change was unrelated to the actual fix for dotnet#33344, which only required passing the bottom inset through as unconsumed. As part of that refactor, top inset consumption was also removed, changing the prior contract where the top inset was consumed when appBarHasContent = true. While normal safe-area scenarios worked correctly, transient layout states (e.g., temporary Height = 0 during keyboard dismissal, rotation, animation, or dynamic item generation) triggered a second inset dispatch. In those moments, the top inset satisfied the overlap condition and was applied to content before SafeAreaExtensions could normalize it, causing test failures. Bottom insets did not regress because their overlap condition cannot be met in the same transient state. ### Description of Change - Restored the original behavior by consuming the top inset when appBarHasContent = true, while continuing to pass the bottom inset through unconsumed (the only change required for dotnet#33344). This retains the Android edge-to-edge fix and restores deterministic safe-area handling. ### Test failures - EntryScrollTest, HorizontalStackLayout_Spacing_WithLandscape, VerticalStackLayout_Spacing_WithLandscape, VerifyBindableLayoutWithGridItemTemplate - (EntryScrollTest)Test fails due to dotnet#33428 this PR ### Issues Fixed Fixes dotnet#34509
- The failing test: `SetVisibility(Visibility.Collapsed)` device test on iOS. Why it fails: PR dotnet#28983's fix maps Visibility → MapIsRunning in ActivityIndicatorHandler, which bypasses the standard ViewExtensions.UpdateVisibility path. The standard path calls Collapse() to add a CollapseConstraint (an NSLayoutConstraint that zeros the view's size). The PR's UpdateIsRunning only sets Hidden = true — it never calls Collapse() - Crash in the FeatureMatrix Navigation Page Scenario in the iOS 26 PR dotnet#34326 added an else block in UpdateBarTextColor() that explicitly sets BackButtonAppearance = null, BackIndicatorImage = null, and BackIndicatorTransitionMaskImage = null on the navigation bar when no custom color is applied. On iOS versions before 26, assigning null to these properties was treated as "use system defaults." On iOS 26, the Liquid Glass rendering pipeline reads these properties during push/pop navigation transitions and throws an exception when it encounters an explicit null — it expects either an unset property or a valid object. Since useCustomColor is false by default (no IconColor set), this crashes on every standard page navigation. - Setting ThumbTintList = null in the else block removes the tint entirely, causing the thumb to appear white instead of the default blue, because SwitchCompat does not re-resolve its theme colors once the tint list is cleared. - SetAdjustViewBounds(false) was being applied to all images regardless of their Aspect value. When this property is false, Android’s ImageView does not resize itself based on the image’s intrinsic aspect ratio and instead expands to fill the available space. As a result, an Image control with the default AspectFit setting ignored its height constraint and overflowed its container, causing the image to appear taller than expected in the screenshot test.(LoadAndVerifyGif, ThemeRelated feature tests) - PR dotnet#29144 changed the group-detection guard in ObservableGroupedSource (iOS and Android) from is IEnumerable to is ICollection to prevent strings (which implement IEnumerable<char>) from being treated as groups. While the intent was correct, the change was too broad. Custom group types that implement only IEnumerable<T> were also excluded. As a result, _groupCount became zero on iOS and _groups remained empty on Android, causing grouped CollectionView rendering failures and IndexOutOfRangeException during Add/Remove operations. - StepperHandler.iOS.cs compiles for both iOS and Mac Catalyst. On Mac Catalyst / macOS 26, OperatingSystem.IsIOS() and IsIOSVersionAtLeast(26) both return true, and the screen is always landscape. As a result, the 20pt glass pill compensation was incorrectly applied, inflating GetDesiredSize(1,1) to width = 21. (Native View Bounding Box is not empty - device Test failures) - In PR dotnet#33428, the WindowInsetsCompat.Builder block in MauiWindowInsetListener.ApplyDefaultWindowInsets was simplified to return insets; to standardize inset handling. This change was unrelated to the actual fix for dotnet#33344, which only required passing the bottom inset through as unconsumed. As part of that refactor, top inset consumption was also removed, changing the prior contract where the top inset was consumed when appBarHasContent = true. While normal safe-area scenarios worked correctly, transient layout states (e.g., temporary Height = 0 during keyboard dismissal, rotation, animation, or dynamic item generation) triggered a second inset dispatch. In those moments, the top inset satisfied the overlap condition and was applied to content before SafeAreaExtensions could normalize it, causing test failures. Bottom insets did not regress because their overlap condition cannot be met in the same transient state. (EntryScrollTest, HorizontalStackLayout_Spacing_WithLandscape, VerticalStackLayout_Spacing_WithLandscape and so on failures) - Handles the three Visibility cases the same way as ViewExtensions.UpdateVisibility: `Visible`: Calls Inflate() (restores layout size) and sets Hidden = false — identical to UpdateVisibility. Additionally starts/stops the animation based on IsRunning. `Hidden`: Calls Inflate() (preserves layout space) and sets Hidden = true — identical to UpdateVisibility. The indicator keeps its layout footprint but is invisible. `Collapsed`: Sets Hidden = true and calls Collapse() (zeros out layout size via constraints) — identical to UpdateVisibility. The indicator is both invisible and takes up no space. - Removed the else block entirely. When no custom color is applied, these properties should remain untouched. The system defaults work correctly on their own — there is no need to explicitly reset them to null - Removed the else block from UpdateThumbColor in SwitchExtensions.cs. The default thumb color is managed by SwitchCompat internally from the Material theme, so no explicit reset is needed. - Restored the correct logic in ImageViewExtensions.UpdateAspect to call SetAdjustViewBounds based on the image’s Aspect value: - The guard has been updated from is ICollection to is IEnumerable && not string in the ObservableGroupedSource implementations for both iOS and Android (GroupsCount(), UpdateGroupTracking(), Add(), Remove()). This change specifically excludes string while allowing legitimate custom group types that implement only IEnumerable<T>. The fix restores the behavior for Issue22320 while keeping all Issue29141 scenarios working correctly. -Added !OperatingSystem.IsMacCatalyst() to the guard condition in GetDesiredSize, restricting the 20pt compensation to real iOS 26+ only — as intended in the original PR comment. - Restored the original behavior by consuming the top inset when appBarHasContent = true, while continuing to pass the bottom inset through unconsumed (the only change required for dotnet#33344). This retains the Android edge-to-edge fix and restores deterministic safe-area handling. EditorNoOverlapAfterRotateToLandscape, EditorNoOverlapAfterRotateToPortrait, EntryFocusedShouldNotCauseGapAfterRotation Added cropLeft to remove the navbar on Android and re-saved the image due to entry text changes in this commit – dotnet@8d17a6d, dotnet@91047fb. DrawStringShouldDrawText – The automation ID set to GraphicsView was not found by Appium on the Windows platform, so a test condition was added for Windows to take the image directly instead of waiting for the GraphicsView. Added the base images for iOS 26 and Mac that were not added previously. Re-saved the images that failed due to the wrong iOS version image being added in the PR. Re-saved the test images that failed due to this fix PR: dotnet#31254 — e.g., GraphicsViewFeatureTests and others. Resaved the slider-related test images due to this fix PR — dotnet#34064. Fixes dotnet#34437 - [x] iOS - [x] Mac --------- Co-authored-by: SyedAbdulAzeem <syedabdulazeem.a@syncfusion.com> Co-authored-by: Vignesh-SF3580 <102575140+Vignesh-SF3580@users.noreply.github.com> Co-authored-by: TamilarasanSF4853 <tamilarasan.velu@syncfusion.com> Co-authored-by: LogishaSelvarajSF4525 <logisha.selvaraj@syncfusion.com>
## 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
…extending to system navigation bar (dotnet#33428) ### Root Cause In Android `Edge-to-Edge` mode, the `MauiWindowInsetListener` was applying padding to the root view and consuming bottom insets. This prevented `BottomNavigationView` from receiving the system navigation bar insets, so it could not extend its background color into the navigation bar area—resulting in a visible gap between the tab bar and the screen edge. ### Description of Change When a `TabbedPage` uses `ToolbarPlacement.Bottom`, the fix applies bottom padding to `contentView` (the fragment container) instead of the root view, and passes bottom insets through without consuming them. This allows `BottomNavigationView` to receive the insets and extend its background color into the system navigation bar area, eliminating the gap. ### Issues Fixed Fixes dotnet#33344 Tested the behaviour in the following platforms - [x] Android - [ ] Windows - [x] iOS - [ ] Mac **Note:** This issue is Android-specific. Windows and macOS do not have a system navigation bar area at the bottom of the screen. ### Screenshots | Before Issue Fix | After Issue Fix | |------------------|-----------------| | <img width="350" alt="withoutfix" src="https://github.com/user-attachments/assets/878a0361-c0cd-4621-a063-94bbc757d15c" /> | <img width="350" alt="withfix" src="https://github.com/user-attachments/assets/ed552f1e-d75f-4275-856a-b8bf993a0dcd" /> |


Root Cause
In Android
Edge-to-Edgemode, theMauiWindowInsetListenerwas applying padding to the root view and consuming bottom insets. This preventedBottomNavigationViewfrom receiving the system navigation bar insets, so it could not extend its background color into the navigation bar area—resulting in a visible gap between the tab bar and the screen edge.Description of Change
When a
TabbedPageusesToolbarPlacement.Bottom, the fix applies bottom padding tocontentView(the fragment container) instead of the root view, and passes bottom insets through without consuming them. This allowsBottomNavigationViewto receive the insets and extend its background color into the system navigation bar area, eliminating the gap.Issues Fixed
Fixes #33344
Tested the behaviour in the following platforms
Note:
This issue is Android-specific. Windows and macOS do not have a system navigation bar area at the bottom of the screen.
Screenshots