Skip to content

July 13th, Candidate - #36411

Open
kubaflo wants to merge 134 commits into
mainfrom
inflight/candidate
Open

July 13th, Candidate#36411
kubaflo wants to merge 134 commits into
mainfrom
inflight/candidate

Conversation

@kubaflo

@kubaflo kubaflo commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

What's Coming

.NET MAUI inflight/candidate introduces significant improvements across all platforms with focus on quality, performance, and developer experience. This release includes 110 commits with various improvements, bug fixes, and enhancements.

Activityindicator

Animation

Blazor

BlazorWebView

Border

CollectionView

🔧 Fixes

Core Lifecycle

Datepicker

Drawing

Editor

Entry

Essentials

Filepicker

Flyoutpage

General

Gestures

Hybridwebview

Label

Layout

Map

Menubar

Navigation

Picker

RadioButton

Refreshview

SafeArea

ScrollView

Searchbar

Shapes

Shell

SwipeView

Templates

Titlebar

WebView

Window

Xaml

🔧 Fixes
🔧 Infrastructure (6)
🧪 Testing (3)
📦 Other (5)
📝 Issue References

Fixes #4715, Fixes #6016, Fixes #8680, Fixes #11764, Fixes #13323, Fixes #14894, Fixes #16119, Fixes #19667, Fixes #20586, Fixes #22326, Fixes #22507, Fixes #22634, Fixes #22642, Fixes #22683, Fixes #23023, Fixes #23315, Fixes #24533, Fixes #25689, Fixes #28064, Fixes #29066, Fixes #29131, Fixes #29421, Fixes #29898, Fixes #30081, Fixes #30248, Fixes #30515, Fixes #31065, Fixes #31808, Fixes #31824, Fixes #31892, Fixes #32059, Fixes #32221, Fixes #32271, Fixes #32275, Fixes #32435, Fixes #32724, Fixes #32796, Fixes #32832, Fixes #32987, Fixes #33103, Fixes #33110, Fixes #33307, Fixes #33785, Fixes #33833, Fixes #34100, Fixes #34103, Fixes #34257, Fixes #34307, Fixes #34318, Fixes #34422, Fixes #34462, Fixes #34536, Fixes #34931, Fixes #35042, Fixes #35216, Fixes #35386, Fixes #35410, Fixes #35471, Fixes #35490, Fixes #35564, Fixes #35571, Fixes #35572, Fixes #35583, Fixes #35613, Fixes #35650, Fixes #35675, Fixes #35700, Fixes #35736, Fixes #35752, Fixes #35753, Fixes #35755, Fixes #35761, Fixes #35764, Fixes #35771, Fixes #35785, Fixes #35788, Fixes #35795, Fixes #35796, Fixes #35806, Fixes #35809, Fixes #35837, Fixes #35839, Fixes #35844, Fixes #35859, Fixes #35860, Fixes #35862, Fixes #35902, Fixes #35943, Fixes #36010, Fixes #36015, Fixes #36018, Fixes #36032, Fixes #36033, Fixes #36035, Fixes #36059, Fixes #36154, Fixes #36173

Copilot AI review requested due to automatic review settings July 6, 2026 15:32
@kubaflo
kubaflo temporarily deployed to copilot-pat-pool July 6, 2026 15:32 — with GitHub Actions Inactive

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review this pull request because it exceeds the maximum number of files (300). Try reducing the number of changed files and requesting a review from Copilot again.

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 36411

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 36411"
@kubaflo
kubaflo temporarily deployed to copilot-pat-pool July 6, 2026 15:33 — with GitHub Actions Inactive
@kubaflo
kubaflo temporarily deployed to copilot-pat-pool July 6, 2026 15:33 — with GitHub Actions Inactive
@kubaflo
kubaflo temporarily deployed to copilot-pat-pool July 6, 2026 15:39 — with GitHub Actions Inactive
@kubaflo
kubaflo temporarily deployed to copilot-pat-pool July 6, 2026 15:40 — with GitHub Actions Inactive
@github-actions github-actions Bot added area-controls-general General issues that span multiple controls, or common base classes such as View or Element platform/android platform/ios platform/macos macOS / Mac Catalyst platform/windows labels Jul 6, 2026
@kubaflo
kubaflo temporarily deployed to copilot-pat-pool July 6, 2026 15:40 — with GitHub Actions Inactive
@kubaflo
kubaflo force-pushed the inflight/candidate branch from 4c111a3 to 86758bd Compare July 6, 2026 16:12
Copilot AI review requested due to automatic review settings July 7, 2026 08:13

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review this pull request because it exceeds the maximum number of files (300). Try reducing the number of changed files and requesting a review from Copilot again.

KarthikRajaKalaimani and others added 9 commits July 7, 2026 04:27
…s SoftInput (#35586)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Issue Details:

Every MauiView that uses SafeAreaEdges.SoftInput stays alive in memory
after being removed from the screen. Users saw platform=12/12 views
never getting released in iOS and Mac platform.
       
### Root Cause:

When a MAUI view is configured with SafeAreaEdges.SoftInput on iOS or
MacCatalyst, MauiView.SubscribeToKeyboardNotifications() registers two
observers with NSNotificationCenter.DefaultCenter — one for
UIKeyboard.WillShowNotification and one for
UIKeyboard.WillHideNotification. Each call to AddObserver returns an
NSObject token that the notification center holds strongly. Because the
callbacks (OnKeyboardWillShow, OnKeyboardWillHide) are instance methods,
the delegate objects capture a strong reference to this — the MauiView
instance. This creates an unbroken retain chain: NSNotificationCenter →
NSObject token → delegate → MauiView. As long as those observer tokens
are registered, the notification center transitively keeps every
subscribed MauiView alive, regardless of whether the view has been
removed from the visual tree, its handler disconnected, and all
MAUI-side references dropped.
 
The reason the tokens were never removed on detach comes down to a
single guard condition in UpdateKeyboardSubscription(). The method was
structured as if (Window != null) { ... }, meaning all subscription
management — both subscribe and unsubscribe — was gated on the view
being attached to a window. When MovedToWindow() fires with Window ==
null (the standard UIKit signal that a view has been removed from the
hierarchy), UpdateKeyboardSubscription() was called but immediately fell
through without doing anything. UnsubscribeFromKeyboardNotifications()
was never reached, leaving the observer tokens live in the notification
center indefinitely. The result, confirmed by the sandbox repro, was
platform=12/12 alive after 12 forced GC cycles for views using
SafeAreaEdges.SoftInput, versus platform=0/12 for the control case.

### Description of Change:

The fix flattens the conditional in UpdateKeyboardSubscription() so that
the else branch — which calls UnsubscribeFromKeyboardNotifications() —
fires for all cases where the view should not be actively subscribed,
including detach. The original nested structure if (Window != null) { if
(ShouldSubscribe) subscribe; else unsubscribe; } is replaced with if
(Window != null && ShouldSubscribeToKeyboardNotifications()) {
SubscribeToKeyboardNotifications(); } else {
UnsubscribeFromKeyboardNotifications(); }. Now when MovedToWindow()
fires with Window == null, the condition evaluates to false and
UnsubscribeFromKeyboardNotifications() is called, issuing
NSNotificationCenter.DefaultCenter.RemoveObserver(token) for both
keyboard observers. This severs the retain chain and allows the MauiView
to be collected normally by the GC. The change is 9 lines, touches a
single method, and introduces no new state or lifecycle hooks.

**Tested the behavior in the following platforms:**

- [x] Android
- [ ] Windows
- [x] iOS
- [ ] Mac

### Reference:

N/A

### Issues Fixed:

Fixes  #35386         

### Screenshots
| Before  | After  |
|---------|--------|
| <img
src="https://github.com/user-attachments/assets/cbbd452a-6565-4e0b-a17d-12c83204bfe5"
Width="400" Height="600"/> | <img
src="https://github.com/user-attachments/assets/3ebbeba2-9fd1-42ac-a4d5-06d5184f2cc7"
Width="400" Height="600"/> |

---------
…API 36 (Pixel 3 XL) (#31631)

>[!NOTE]
>Are you waiting for the changes in this PR to be merged?
>It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR->Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

This pull request sets up a dedicated Android CI stage for SafeAreaEdges
UI tests, running on a notch-equipped device (Pixel 3 XL skin, Android
API 36). It is a continuation of
#31355.

**Android test pipeline changes (`ui-tests.yml`):**

- Moved `SafeAreaEdges` out of the standard Android test filter batch
into its own dedicated stage, so it no longer runs alongside other tests
on API 30 (which lacks a notch)
- Added a new `androidApiLevelsExtended: [36]` parameter to target
Android API 36 without changing the existing `androidApiLevels: [30]`
configuration
- Created a dedicated stage (`android_ui_tests_safeareaedges`) that runs
SafeAreaEdges tests on Android API 36 using the Pixel 3 XL device skin
(which has a notch/display cutout)

**Device skin support (`ui-tests-steps.yml`):**

- Added deviceType parameter to `ui-tests-steps.yml` to allow specifying
an Android emulator device skin
- When set, appends `--skin="<deviceType>"` to the test runner command,
selecting the correct AVD skin at emulator creation time

Note: This PR contains only the YAML pipeline updates and is a
continuation of [#31355](#31355)


Fixes #32059

---------
…raised (#31786)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->
### Issue Details

- When changing the resolution, rotation, or refresh rate, the
DeviceDisplay.MainDisplayInfoChanged event is not triggered.

### Root Cause of the issue

- DidChangeStatusBarOrientationNotification does not apply to Mac
Catalyst apps because they do not have a mobile-style status bar. On
desktop, changes such as resolution, refresh rate are not reported
through mobile-oriented notifications.

### Description of Change

**Mac Catalyst-specific display handling:**

* Added P/Invoke declarations for Core Graphics APIs in
`DeviceDisplay.ios.cs` to fetch display properties (resolution, refresh
rate, rotation) directly from the system, bypassing potentially stale
UIKit data.
* Updated `GetMainDisplayInfo()` to use Core Graphics APIs on Mac
Catalyst, including logic to calculate orientation and rotation based on
system-reported values.

**Display change event handling:**

* On Mac Catalyst, replaced status bar orientation notifications with
`NSApplicationDidChangeScreenParametersNotification` to reliably detect
display changes (resolution, refresh rate, etc.).

**Equality logic improvements:**

* Updated the `DisplayInfo.Equals()` method to include `RefreshRate` in
equality checks, ensuring all display properties are considered.

### Issues Fixed

<!-- Please make sure that there is a bug logged for the issue being
fixed. The bug should describe the problem and how to reproduce it. -->

Fixes #22634 
Fixes #22642

### Tested the behaviour in the following platforms

- [x] - Windows 
- [x] - Android
- [x] - iOS
- [x] - Mac

### Output
| Before | After |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/44c1c29a-b6d9-4231-b732-54d874d5ac7d">
| <video
src="https://github.com/user-attachments/assets/548ce40f-ee6f-4b7d-ac85-fa445e74f106">
|

<!--
Are you targeting main? All PRs should target the main branch unless
otherwise noted.
-->
…mized window (#29253)

### Issue Detail:
 
On the Windows platform, if the application window is maximized, the
main window X,Y values are in negative (-7, -7). For a non-maximized
window, values are correct.
 
### Root Cause
On Windows, when the application window is maximized, the values of
Window.Y and Window.Height reported during Window_Destroying are offset
by 8 pixels. This occurs because the default window bounds include the
non-client area (e.g., title bar and borders), which is excluded by the
OS when maximizing the window. As a result, the bounds do not accurately
reflect the actual client area used by the application, leading to
incorrect frame values being reported to the virtual view.
 
### Description of Change
To resolve this, the implementation now uses the Windows Desktop Window
Manager (DWM) API to retrieve the extended frame bounds via
DwmGetWindowAttribute with the DWMWA_EXTENDED_FRAME_BOUNDS attribute.
These bounds reflect the full screen-space dimensions of the window,
even when maximized.

In the UpdateVirtualViewFrame method, when the window is in a normal
state, the position and size reported by AppWindow are used directly.
When the window is maximized, the logic switches to use the bounds
provided by the DWM API. This ensures that the virtual view receives
accurate and consistent frame data (X, Y, Width, and Height) regardless
of the window state.

### Validated the behaviour in the following platforms
- [ ] Android
- [x] Windows
- [ ] iOS
- [ ] Mac
### Issues Fixed:
Fixes #29066
 
### Screenshots

| Before  | After |
|---------|--------|
|  <img
src="https://github.com/user-attachments/assets/3d5c192f-b681-491f-971a-6d6c0822ad12">
|  <img
src="https://github.com/user-attachments/assets/255b3ea5-c147-414d-9bce-6dbe119b4b2b"> 
|
…trol (#35669)

> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

This pull request refactors and enhances the RadioButton feature matrix
test pages, focusing on improving the organization and functionality of
the options UI, as well as resetting the view model state more robustly.
The most significant changes are the restructuring of the options page
layout, the addition of a method to reset the RadioButton view model to
its defaults, and some minor test and code quality improvements.

**UI and Layout Improvements:**

* Refactored `RadioButtonOptionsPage.xaml` to group related numeric
options (Border Width, Character Spacing, Corner Radius, Font Size) into
a 2x2 grid for better organization and usability. Removed redundant
individual entry fields for these properties and adjusted row
assignments for all subsequent controls.
[[1]](diffhunk://#diff-28d48ddf94e5d659e0dd4bf27024b6333199e4c1cd7bcb22b4c6dce5d302e224R38-R109)
[[2]](diffhunk://#diff-28d48ddf94e5d659e0dd4bf27024b6333199e4c1cd7bcb22b4c6dce5d302e224L123-R194)
* Added a new "Font Auto Scaling" option as a pair of radio buttons,
replacing the previous font size entry field.
* Updated row indices throughout the options page to reflect the new
layout structure.
[[1]](diffhunk://#diff-28d48ddf94e5d659e0dd4bf27024b6333199e4c1cd7bcb22b4c6dce5d302e224L61-R131)
[[2]](diffhunk://#diff-28d48ddf94e5d659e0dd4bf27024b6333199e4c1cd7bcb22b4c6dce5d302e224L83-R153)
[[3]](diffhunk://#diff-28d48ddf94e5d659e0dd4bf27024b6333199e4c1cd7bcb22b4c6dce5d302e224L97-R167)
[[4]](diffhunk://#diff-28d48ddf94e5d659e0dd4bf27024b6333199e4c1cd7bcb22b4c6dce5d302e224L190-R215)
[[5]](diffhunk://#diff-28d48ddf94e5d659e0dd4bf27024b6333199e4c1cd7bcb22b4c6dce5d302e224L217-R242)
[[6]](diffhunk://#diff-28d48ddf94e5d659e0dd4bf27024b6333199e4c1cd7bcb22b4c6dce5d302e224L275-R306)
[[7]](diffhunk://#diff-28d48ddf94e5d659e0dd4bf27024b6333199e4c1cd7bcb22b4c6dce5d302e224L296-R328)
[[8]](diffhunk://#diff-28d48ddf94e5d659e0dd4bf27024b6333199e4c1cd7bcb22b4c6dce5d302e224L323-R355)
[[9]](diffhunk://#diff-28d48ddf94e5d659e0dd4bf27024b6333199e4c1cd7bcb22b4c6dce5d302e224L350-R383)

**ViewModel and State Management:**

* Added a `ResetToDefaults` method to `RadioButtonViewModel` to
centralize and standardize resetting all properties to their default
values.
* Updated the navigation handler in `RadioButtonControlMainPage` to use
the new `ResetToDefaults` method, ensuring consistent reset behavior
when navigating to the options page.

**Test and Code Quality:**

* Added the `[Category(UITestCategories.Material3)]` attribute to the
`Material3RadioButtonFeatureTests` class instead of individual test
methods for better test categorization.
[[1]](diffhunk://#diff-ba76e0d629a20f403900298a573a972756b9f6351185fa6b23171b77d988055aR12)
[[2]](diffhunk://#diff-ba76e0d629a20f403900298a573a972756b9f6351185fa6b23171b77d988055aL22-L30)
* Named the main radio button in `RadioButtonControlPage.xaml` as
`RadioButtonControlOne` for easier test referencing.

Issue Identified:
1. #35587
… floating glass tab bar (#35523)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Issue Details
- On iOS 26, pages inside a NavigationPage hosted in a TabbedPage do not
extend behind the new floating glass tab bar, leaving a white gap
between the page content and the tab bar.

### Root Cause
- On iOS 26, the tab bar changed from a solid bar to a floating glass
overlay. ParentingViewController.ViewWillAppear was assigning
EdgesForExtendedLayout = UIRectEdge.None for opaque navigation bars,
which prevented content from extending under the tab bar — leaving a
white gap between the page content and the new floating glass bar.

### Description of Change
- Updated NavigationRenderer to extend content layout behind the
floating tab bar when running on iOS/Mac Catalyst 26+ and the tab bar is
visible, preventing content from being clipped.

### Issues Fixed
Fixes #35490

### Validated the behaviour in the following platforms

- [ ] Windows
- [ ] Android
- [x] iOS
- [x] Mac

### Output
| Before | After |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/c4544467-6224-4dd4-bfd7-02c53bca3e8b">
| <video
src="https://github.com/user-attachments/assets/6c7186cd-3e42-4d9c-ad32-5f515a724991">
|
…d by app code (#35686)

<!-- Please keep the note below for people who find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment whether this change resolves your
issue. Thank you!
<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

This pull request improves the way map pin event subscriptions are
managed in the `MapHandler.Android` implementation. The main change is
to ensure that property change event handlers for map pins are only
attached once, and are properly cleaned up, preventing duplicate
subscriptions and potential memory leaks.
### Description of Change
**Pin subscription management improvements:**

* Introduced a `_subscribedPins` `HashSet<IMapPin>` field to track pins
that have event handlers attached, ensuring each pin is subscribed only
once.
* Updated the `AddPins` method to only add a property changed event
handler if the pin hasn't already been subscribed, using the
`_subscribedPins` set.
* Modified the `DisconnectPins` method to iterate over `_subscribedPins`
instead of the pin list, removing event handlers from only those pins
that were actually subscribed, and resetting the tracking set
afterwards.

### Regarding Tests : 
No automated device test included. MapView.OnCreate throws
IllegalStateException when no valid Google Maps API key is present —
even an empty string value fails. This is the same constraint that keeps
`MapTests.cs` behind #if IOS || MACCATALYST. Adding the key to
`AndroidManifest.xml `would expose credentials in the repo, which is not
acceptable.

<!-- Enter description of the fix in this section -->

### Issues Fixed

<!-- Please make sure that there is a bug logged for the issue being
fixed. The bug should describe the problem and how to reproduce it. -->

Fixes #35571 
### Tested the behavior in the following platforms

- [ ] Windows
- [x] Android
- [ ] iOS
- [ ] Mac

| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/72bd098d-7a8f-4248-9ec3-7e30207eb6d4">
| <video
src="https://github.com/user-attachments/assets/703c227e-88b2-457c-b0a0-9e3bb5393da5">
|
<!--
Are you targeting main? All PRs should target the main branch unless
otherwise noted.
-->

---------
<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Description of Change

Stops Android foreground geolocation listening from using the desired
accuracy distance as the platform minimum movement threshold.
`MinimumTime` now controls the requested update cadence without imposing
a hidden 50m+ distance gate for `GeolocationAccuracy.Best`.

The existing accuracy value is still used by the listener to filter out
locations that do not satisfy the requested accuracy.

### Issues Fixed

Fixes #22683

### Validation

- Built `src/Essentials/src/Essentials.csproj` for
`net10.0-android36.0`.

### Manual regression coverage

Automated Android device coverage for this exact regression would
require controlling mock location updates from the test app/device
environment, which is not reliable in the current Essentials device-test
setup. Please validate the PR artifacts with the issue repro or
Essentials geolocation sample:

1. Install this PR's artifacts using the dogfood instructions above.
2. Start foreground listening with `new
GeolocationListeningRequest(GeolocationAccuracy.Best,
TimeSpan.FromSeconds(1))`.
3. Keep the app in the foreground and send or perform multiple location
changes that remain within 50 meters of the previous position.
4. Confirm `LocationChanged` continues firing for those sub-50m updates
instead of stopping after the initial GPS/network callbacks.
5. Confirm updates still include high-accuracy locations; locations
whose reported accuracy is worse than the requested accuracy can still
be filtered by the existing listener accuracy check.

---------
…ns in CollectionView (#29255)

> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Issue Details 

`KeepScrollOffset` mode does not maintain scroll position when new items
are inserted into the CollectionView, resulting in unintended upward
scrolling.

### Root Cause 

When new items are added to the collection, the scroll offset is
recalculated based on the updated layout. This results in incorrect
offset adjustments, causing the scroll position to shift upward instead
of being correctly preserved.

### Description of Change

* Added `AddScrollListener` and `RemoveScrollListener` methods to manage
scroll listeners dynamically. Adjusted the `TrackOffsets` method to
ensure scroll offsets are only adjusted when the first item is reached,
ensuring accurate scroll behavior and preventing unintended upward
scrolling during dynamic item insertions.

### Issues Fixed

Fixes #29131 

* The Following [PR - 27153](#27153)
fixes the `KeepItemsInView` issue on Android.

**Tested the behaviour in the following platforms**

- [x] Android
- [x]  Windows
- [x]  iOS
- [x] Mac

### Output

| Before| After|
|--|--|
| <video
src="https://github.com/user-attachments/assets/5d258709-c128-4cc4-9a73-bf3ad32b1cc3">
| <video
src="https://github.com/user-attachments/assets/8b22544b-cbbd-4d97-a54a-4573ca0290d5">
|

---------
… menu (when visible) (#36713)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

**Summary** 
Revert the changes in the PR #34923 
**Reason**
The fix introduces a major behavioural changes in the SwipeView.
Copilot AI review requested due to automatic review settings July 22, 2026 14:59

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review this pull request because it exceeds the maximum number of files (300). Try reducing the number of changed files and requesting a review from Copilot again.

… ScrollView interaction state after IsEnabled toggles (#36628)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Issue Details
- On iOS and macOS, four tests —
CollectionViewScrollsWhenRefreshViewDisabled,
ScrollViewInitiallyNotEnabledThenEnabled,
ProgressSpinnerWorksWhenReEnabled, and
VerifyCollectionViewIsEnableState — are failing in candidate PR #36411
due to PR #36305.

### Root Cause
- PR #36305 updated ViewExtensions.UpdateIsEnabled to compute
UserInteractionEnabled using both IsEnabled and InputTransparent for
non-UIControl views. However, because CollectionView, RefreshView, and
ScrollView override MapIsEnabled without invoking the shared
implementation, they never adopted this new logic, causing inconsistent
UserInteractionEnabled behavior across enable/disable state changes and
resulting in failures in CollectionViewScrollsWhenRefreshViewDisabled,
ProgressSpinnerWorksWhenReEnabled, VerifyCollectionViewIsEnableState,
and ScrollViewInitiallyNotEnabledThenEnabled.

### Description of Change
- Introduced a new UpdateInteractionState extension method in
ViewExtensions.cs that centralizes the logic for setting
UserInteractionEnabled based on both IsEnabled and InputTransparent, and
updated both UpdateIsEnabled and UpdateInputTransparent to use this
method.
- Updated MapIsEnabled methods in handlers for ItemsViewHandler,
ItemsViewHandler2, RefreshViewHandler, and ScrollViewHandler to call the
base ViewHandler.MapIsEnabled, ensuring interaction state is always
recomputed.


### Issues Fixed
Fixes #36501

### Validated the behaviour in the following platforms

- [ ] Windows
- [ ] Android
- [x] iOS
- [x] Mac

### Output
| TestCase | Before | After |
|----------|----------|----------|
| CollectionViewScrollsWhenRefreshViewDisabled | <img
src="https://github.com/user-attachments/assets/91d4a461-e7c8-4c5c-ae67-578e761fc2f8">
| <img
src="https://github.com/user-attachments/assets/758235b2-2a60-4352-ba6d-f6303be4a451">
|
| ScrollViewInitiallyNotEnabledThenEnabled | <img
src="https://github.com/user-attachments/assets/5fafbe0c-3fb5-41e2-9ae0-2250003c099f">
| <img
src="https://github.com/user-attachments/assets/29f70482-e7dc-4255-b9fe-1485d3a725c3">
|
| ProgressSpinnerWorksWhenReEnabled | <img
src="https://github.com/user-attachments/assets/0dee44b2-09b3-418e-bff9-ec5d3bb11f7d">
| <img
src="https://github.com/user-attachments/assets/cdf9fc11-27fd-48ec-b91d-8b56e6dc83e0">
|
|VerifyCollectionViewIsEnableState | <img
src="https://github.com/user-attachments/assets/a5df9338-3fc8-4d47-8c32-a664e89b6471">
| <img
src="https://github.com/user-attachments/assets/17215ea8-a215-4e08-b68c-ef251d02b995">
|
Copilot AI review requested due to automatic review settings July 25, 2026 09:39

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review this pull request because it exceeds the maximum number of files (300). Try reducing the number of changed files and requesting a review from Copilot again.

…ross platforms (#35632)" (#36887)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

> Supersedes #36883, which was branched off `main` while targeting
`inflight/candidate`. That mismatch dragged in 42 unrelated `main`-only
commits and produced four spurious conflicts in files that have nothing
to do with `SwipeItem`. This branch is built directly on
`inflight/candidate`, so it is a clean single-commit diff.

### Issue Details

This reverts #35632 ("Fix SwipeItem IconImageSource color handling and
rendering across platforms") from the .NET 10 servicing line.

#35632 stopped auto-tinting `SwipeItem.IconImageSource` for PNG/SVG
sources, so those icons now render in their own colors instead of a
contrast color derived from the item background. It shipped in 10.0.90
(SR9) and is causing #36766 — an SVG icon whose fill is `#212121` now
renders black on a black swipe item in dark mode, i.e. effectively
invisible.

The change is a reasonable direction, but it is too breaking for a
servicing release:

- **It removes a legibility guarantee with no replacement.**
`GetTextColor()` picks white or black from background luminosity. #35632
removed that for PNG/SVG but left it in place for the item's label text,
so the text is still contrast-corrected while the icon is not.
- **There is no opt-in.** #23074 was labelled `proposal/open` and asked
for *more configuration*; what shipped was a behavior change with none.
An affected app's only options today are pinning to 10.0.80 or
re-authoring every SVG per theme.
- **It compounds with #36271** (also SR9), which makes `BackgroundColor`
correctly follow `AppThemeBinding`. Before SR9 the stale light
background accidentally preserved contrast; together the two changes
produce black-on-black.
- **The prior behavior was the Xamarin.Forms behavior**, not an
inconsistency — Xamarin tinted every icon unconditionally on both
Android
([`SwipeViewRenderer.cs#L858`](https://github.com/xamarin/Xamarin.Forms/blob/main/Xamarin.Forms.Platform.Android/Renderers/SwipeViewRenderer.cs#L858))
and iOS
([`SwipeViewRenderer.cs#L713`](https://github.com/xamarin/Xamarin.Forms/blob/main/Xamarin.Forms.Platform.iOS/Renderers/SwipeViewRenderer.cs#L713)).

### Description of Change

`git revert` of c78acfe, restoring the previous behavior on all
platforms:

- **Android** — `SetColorFilter(GetTextColor(), SrcAtop)` applied to
every drawable again
- **iOS/Mac** — `AlwaysTemplate` rendering mode on every image again,
with `TintColor = fontImageSource.Color ?? GetTextColor()`
- **Windows** — `MapSourceAsync` back to `ToIconSource()`
(`BitmapIconSource`, whose `ShowAsMonochrome` defaults to `true`); the
`LoadFileIconAsync` helper is removed

The `Issue23074` host-app page, shared test, `cancel_red.svg` and the
`SwipeItemFontAndSvgIconsRenderCorrectly` snapshots are removed with it,
and the SwipeView snapshots are restored to their pre-#35632 baselines.

The revert is scoped strictly to #35632. `MapVisibility` on the Windows
handler — added on `inflight/candidate` after #35632 — is untouched.

**Conflict resolution note:**
`TestCases.iOS.Tests/snapshots/ios/VerifyCollectionViewContentWithIconImageSwipeItem.png`
conflicted because #36202 re-saved it for iOS 18 after #35632 landed.
That test's swipe item has `BackgroundColor = #6A5ACD` (luminosity ≈
0.40 → white), so with this revert `groceries.png` is tinted solid white
again and the pre-#35632 baseline is the correct content. If iOS 18 CI
shows drift unrelated to the tint, this one snapshot may need a re-save
from the CI artifact.

### Follow-up

The behavior change itself is good and should ship — just in .NET 11
rather than servicing, paired with an explicit opt-in API so users get a
real migration path instead of a silent rendering change in a patch
release. That is #36884, which keeps the #35632 behavior and adds
`SwipeItem.IconColor`.

### Issues Fixed

Fixes #36766

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: cb2a11ab-30ba-4020-836a-3acccb5f58cc
Copilot AI review requested due to automatic review settings July 28, 2026 17:02

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review this pull request because it exceeds the maximum number of files (300). Try reducing the number of changed files and requesting a review from Copilot again.

…e - 1 (#36476)

This PR addresses the test failures that occurred in the
inflight/candidate branch: #36411,
and includes updates to improve rendering and test stability across
platforms.

**Test improvement:**
- The SafeArea category now runs on a different Pixel device. As a
result, Issue32586 test cases failed on the current device, so the tests
have been updated to resolve the issue.

**Images:**
- Added base images and valid re-saved images for all platforms.

**Test assertion updates for Shell Flyout footer positioning:**

*
[`src/Controls/tests/DeviceTests/Elements/Shell/ShellFlyoutTests.cs`](diffhunk://#diff-05d107718512cb95857141719a06c5d7d4bd5ad1c842322dc83b9c67b78872f3L175-R177):
Updated assertions to remove unnecessary addition of `safeAreaBottom` to
the footer's Y position, since the safe area is now subtracted from the
content height. This affects both iOS and cross-platform test logic.
[[1]](diffhunk://#diff-05d107718512cb95857141719a06c5d7d4bd5ad1c842322dc83b9c67b78872f3L175-R177)
[[2]](diffhunk://#diff-05d107718512cb95857141719a06c5d7d4bd5ad1c842322dc83b9c67b78872f3L257-R266)
*
[`src/Controls/tests/DeviceTests/Elements/Shell/ShellFlyoutTests.cs`](diffhunk://#diff-05d107718512cb95857141719a06c5d7d4bd5ad1c842322dc83b9c67b78872f3L257-R266):
Adjusted the total flyout height assertion to explicitly include
`safeAreaBottom` below the footer, reflecting the new layout behavior.

**Test marker UI adjustment:**

*
[`src/Controls/tests/TestCases.HostApp/Issues/Issue32586.cs`](diffhunk://#diff-4542190c07831c0fce478af7b6559a846ab8043c0ada58e23c14d1634e7d4541R42):
Set a fixed `HeightRequest` of 50 for the "Top Marker" label to ensure
consistent test layout.


Fixes: #36411

---------

Co-authored-by: devanathan-vaithiyanathan <114395405+devanathan-vaithiyanathan@users.noreply.github.com>
Co-authored-by: HarishKumarSF4517 <harish.kumar@syncfusion.com>
Co-authored-by: LogishaSelvarajSF4525 <logisha.selvaraj@syncfusion.com>
Co-authored-by: SubhikshaSf4851 <subhiksha.c@syncfusion.com>
Co-authored-by: Ahamed-Ali <102580874+Ahamed-Ali@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 29, 2026 13:10

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review this pull request because it exceeds the maximum number of files (300). Try reducing the number of changed files and requesting a review from Copilot again.

…temsSource swap/reset (#36753)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Issue Details
- On iOS 18.5 and Mac (CI only), the
CarouselViewShouldScrollToRightPosition and
VerifyCarouselScrollsToEndItemAfterReset UI test are failing in
candidate PR #36411 due to the fix in PR #35848.

### Root Cause
- PR #35848's _gotoPosition guard in CarouselViewController2 (iOS) is
set by every call to ScrollToPosition and expected to be cleared by the
scroll callback, but two internal scrolls — the
SetValueFromRenderer(Position, 0) in UpdateItemsSource's reset branch
and the forced ScrollToPosition(target, target, animated:false,
forceScroll:true) at the end of CollectionViewUpdated — set it without
producing a callback, so the stale value silently drops the next
programmatic scroll.

### Description of Change
- Cleared _gotoPosition when updating the items source to prevent scroll
targets from the old source affecting the new data.
- Cleared _gotoPosition after resetting the Position property to ensure
future programmatic changes are not suppressed.
- Cleared _gotoPosition during teardown to avoid leftover scroll targets
when the view is re-attached.
- Cleared _gotoPosition after a forced scroll in CollectionViewUpdated
to prevent suppression of later user-initiated scrolls.
- Cleared _gotoPosition after the forced scroll in UpdateLoop() to
prevent it from becoming stale when the Loop property is toggled and the
previous re-centering scroll is skipped or does not generate a callback.



### Issues Fixed
Fixes #36718

### Validated the behaviour in the following platforms

- [ ] Windows
- [ ] Android
- [x] iOS
- [x] Mac

### Output

| TestCase | Before | After |
|----------|----------|----------|
| VerifyCarouselScrollsToEndItemAfterReset | <img
src="https://github.com/user-attachments/assets/a5c7bf90-cd77-4153-bafd-be60a0b90e14">
| <img
src="https://github.com/user-attachments/assets/30823197-0c81-4f0a-9f1e-f591e58c1bc2">
|
| CarouselViewShouldScrollToRightPosition | <img
src="https://github.com/user-attachments/assets/661a65a8-a2ce-4b20-ac8b-4ff70f2c9b4d">
| <img
src="https://github.com/user-attachments/assets/eaaabfd2-f408-4713-9941-5383ef71d9e8">
|
Copilot AI review requested due to automatic review settings July 29, 2026 23:06

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review this pull request because it exceeds the maximum number of files (300). Try reducing the number of changed files and requesting a review from Copilot again.

…ks scroll (#36715)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Description of Change

- Reverts the IsExplicitlyEnabled carve-out introduced in PR #34702,
which bypassed VisualElement's built-in IsEnabled cascading (via
CoerceIsEnabledProperty) specifically for ItemsView touch handling on
Android and iOS. This restores the default behavior, where disabling a
parent (for example, RefreshView.IsEnabled = false) also disables touch
interaction for its child views (for example, CollectionView).

### Reason
IsEnabled cascading from parent to child is expected, by-design behavior
— VisualElement.IsEnabledCore
(src/Controls/src/Core/VisualElement/VisualElement.cs) coerces a child's
IsEnabled to false whenever any ancestor is disabled.

Issue #34666 was filed with an "Expected Behavior" of "Page C6 can
scroll" — but the C6 manual test's own written pass-criteria only checks
that the refresh spinner does not appear; it never specifies that the
CollectionView must remain scrollable. The reporter's expectation goes
beyond what C6 actually tests for, and contradicts IsEnabled 's
cascading behavior (per IsEnabledCore) — the correct API for "block only
the refresh gesture, keep content interactive" is
RefreshView.IsRefreshEnabled = false , not IsEnabled = false .

### Changes
- **VisualElement.cs**: Removed the IsExplicitlyEnabled property
entirely.
- **MauiCarouselRecyclerView.cs (Android)**: Reverted
`OnInterceptTouchEvent` to check plain `IsEnabled` instead of `IsEnabled
&& !IsExplicitlyEnabled`, removing the same `IsExplicitlyEnabled`
carve-out from `CarouselView`'s touch interception.
- **MauiRecyclerView.cs (Android)**: Reverted OnTouchEvent,
DispatchTouchEvent, and OnInterceptTouchEvent to check plain IsEnabled
instead of IsEnabled && !IsExplicitlyEnabled, restoring cascading block
behavior.
- **SelectableItemsViewController.cs / SelectableItemsViewController2.cs
(iOS)**: Reverted ItemSelected, ItemDeselected, and UpdateSelectionMode
to use IsEnabled instead of IsExplicitlyEnabled.
- **Issue34666.cs (both TestCases.Shared.Tests and TestCases.HostApp**):
Updated to reflect the restored, correct behavior:
- Removed the `#if TEST_FAILS_ON_ANDROID` guard entirely so the test now
runs on all platforms, since Android and iOS/macOS both correctly block
scrolling.
- Renamed CollectionViewScrollsWhenRefreshViewDisabled →
CollectionViewDoesNotScrollWhenRefreshViewDisabled.
- Changed the final assertion from "Gelada" (requires successful scroll)
to "Baboon" (confirms scroll is blocked).
- Updated the Issue description from "The C6 page cannot scroll on
Windows and Android platforms" to "Disabling RefreshView cascades
IsEnabled = false to its child CollectionView, preventing scrolling"
since this is now the intended, correct behavior rather than an open
bug.

### Issues Fixed
Relates to #34666 — the underlying
report is describing IsEnabled 's expected, by-design cascading
behavior, not a bug; the correct fix for the reporter's actual use case
is IsRefreshEnabled = false , not IsEnabled = false.
Copilot AI review requested due to automatic review settings July 29, 2026 23:10

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review this pull request because it exceeds the maximum number of files (300). Try reducing the number of changed files and requesting a review from Copilot again.

…en visible) (#36878)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

**Note:** 
This PR was previously merged into the candidate branch but was later
reverted pending behavior confirmation. After revalidating the behavior
with @PureWeen , new PR has been created to bring the fix back into the
candidate branch.
Reverted PR #36713 
 
## Issue Details
 
SwipeView Threshold changes width and offset of the side menu (when
visible) Opened.

## Root Cause
 
The SwipeView.Threshold property is designed for a single purpose:
setting the minimum drag distance a user must swipe before the menu
snaps open. It has nothing to do with how wide the menu
items should appear or where the content settles after the swipe.
However, the platform code on both iOS and Android was incorrectly using
this value in two unrelated calculations.

The first misuse was in GetSwipeItemSize(), where the code checked if
Threshold > 0 and, if so, used the threshold value as the item's width.
This meant that setting Threshold=200 would inflate
every swipe item to 200pt wide, far larger than the intended ~100pt. The
second misuse was in GetSwipeThreshold(ISwipeItems), which had an early
return that directly handed back the Threshold
value as the snap-open distance. So the content would snap to 200pt
offset instead of snapping to the actual menu width. Together, these two
bugs caused both the menu to look bloated and the
content displacement to differ depending on whether Threshold was set.
 
##  Description of Change

The fix removes Threshold from both of those calculations entirely. Item
sizing now uses only the item's configured WidthRequest or the default
SwipeItemWidth, as it should. The snap distance is now computed as
Math.Min(Threshold, menuWidth) — meaning if Threshold is set, it acts as
a cap on how far the user needs to drag, but the content still snaps to
the true menu width. If Threshold is not set, the default behaviour of
60% of menu width is preserved. This was applied consistently across iOS
(MauiSwipeView.cs and SwipeViewExtensions.cs) and Android
(MauiSwipeView.cs).

**Tested the behavior in the following platforms.**
- [x] Android
- [ ] Windows
- [x] iOS
- [x] Mac

**Issue Fixed**
Fixed  #6016 

 
## Screenshots
| Before  | After  |
|---------|--------|
| <img width="320" height="572" alt="image"
src="https://github.com/user-attachments/assets/83ecc2bd-55db-4874-9508-1dadddb1483d"
/> | <img width="319" height="573" alt="image"
src="https://github.com/user-attachments/assets/9f6aa6cc-1762-47ee-a60f-88cdf3b08c36"
/> |
Copilot AI review requested due to automatic review settings July 31, 2026 09:50

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review this pull request because it exceeds the maximum number of files (300). Try reducing the number of changed files and requesting a review from Copilot again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-controls-general General issues that span multiple controls, or common base classes such as View or Element platform/android platform/ios platform/macos macOS / Mac Catalyst platform/windows