Conversation
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 34294Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 34294" |
There was a problem hiding this comment.
Pull request overview
Updates the candidate branch with a set of cross-platform fixes and behavior adjustments across Controls, including memory-leak regression coverage, handler selection for Android Material3, and several platform-specific UI correctness fixes.
Changes:
- Enable/expand leak regression coverage (NavigationPage on Android) and add an Android device test for StackNavigationManager disconnect cleanup.
- Improve platform UI behavior: disabled state propagation (Windows tabs/Shell), swipe state reset on iOS, toolbar/menu item race-condition guarding on Android, and assorted navigation/shell fixes.
- Introduce Shape versioning via an overridden
OnPropertyChangedand update PublicAPI baselines accordingly.
Reviewed changes
Copilot reviewed 41 out of 657 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| src/Controls/tests/DeviceTests/Memory/MemoryTests.cs | Enables NavigationPage leak coverage on Android and updates issue notes. |
| src/Controls/tests/DeviceTests/Elements/NavigationPage/NavigationPageTests.Android.cs | Adds a device test asserting StackNavigationManager clears references on disconnect. |
| src/Controls/src/Core/TabbedPage/TabbedPage.Windows.cs | Propagates per-tab IsEnabled into the Windows tab view model. |
| src/Controls/src/Core/SwipeView/SwipeView.cs | Closes SwipeView on iOS cell reuse when BindingContext changes. |
| src/Controls/src/Core/Shapes/Shape.cs | Adds version tracking and overrides OnPropertyChanged to bump a version counter. |
| src/Controls/src/Core/PublicAPI/netstandard/PublicAPI.Unshipped.txt | Records new protected override API surface for Shape. |
| src/Controls/src/Core/PublicAPI/net/PublicAPI.Unshipped.txt | Records new protected override API surface for Shape. |
| src/Controls/src/Core/PublicAPI/net-windows/PublicAPI.Unshipped.txt | Records new protected override API surface for Shape. |
| src/Controls/src/Core/PublicAPI/net-tizen/PublicAPI.Unshipped.txt | Records new protected override API surface for Shape. |
| src/Controls/src/Core/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt | Records new protected override API surface for Shape. |
| src/Controls/src/Core/PublicAPI/net-ios/PublicAPI.Unshipped.txt | Records new protected override API surface for Shape. |
| src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt | Records new overrides for Android Items RecyclerView touch handling plus Shape override. |
| src/Controls/src/Core/Platform/iOS/Extensions/FormattedStringExtensions.cs | Uses shared font resolution helper for spans. |
| src/Controls/src/Core/Platform/Windows/TabbedPage/TabbedPageStyle.xaml | Binds Windows NavigationViewItem IsEnabled to the view model. |
| src/Controls/src/Core/Platform/Windows/Extensions/FormattedStringExtensions.cs | Uses shared font resolution helper for spans. |
| src/Controls/src/Core/Platform/Android/Extensions/ToolbarExtensions.cs | Adds guard against stale async icon callbacks and requests insets after layout param changes. |
| src/Controls/src/Core/Platform/Android/Extensions/FormattedStringExtensions.cs | Uses shared font resolution helper for spans. |
| src/Controls/src/Core/NavigationPage/NavigationPageToolbar.cs | Re-applies toolbar changes when FlyoutLayoutBehavior changes. |
| src/Controls/src/Core/NavigationPage/NavigationPage.cs | Removes duplicate RemoveFromInnerChildren call. |
| src/Controls/src/Core/Label/Label.cs | Removes the handler attribute (handler selection moved to registration). |
| src/Controls/src/Core/Label/Label.Android.cs | Updates layout-changed wiring for both Material and non-Material platform views; detaches on handler changes. |
| src/Controls/src/Core/Hosting/AppHostBuilderExtensions.cs | Conditionally registers Material3 handler variants on Android for several controls. |
| src/Controls/src/Core/Handlers/Shell/ShellItemHandler.Windows.cs | Updates Windows Shell tab view models on property changes; unsubscribes on disconnect. |
| src/Controls/src/Core/Handlers/Items2/iOS/ItemsViewDelegator2.cs | Adjusts scrolled-offset bookkeeping when no items are visible. |
| src/Controls/src/Core/Handlers/Items2/ItemsViewHandler2.iOS.cs | Uses actual scroll direction when mapping scroll-to position. |
| src/Controls/src/Core/Handlers/Items/iOS/ItemsViewDelegator.cs | Adjusts scrolled-offset bookkeeping when no items are visible. |
| src/Controls/src/Core/Handlers/Items/Android/RecyclerViewScrollListener.cs | Avoids firing initial spurious scroll event and adjusts RemainingItemsThresholdReached logic. |
| src/Controls/src/Core/Handlers/Items/Android/MauiRecyclerView.cs | Adds disabled touch handling overrides. |
| src/Controls/src/Core/FontExtensions.cs | Adds Span.GetEffectiveFont helper used by platform formatted-string extensions. |
| src/Controls/src/Core/FlyoutPage/FlyoutPage.cs | Triggers toolbar re-evaluation on orientation change for Android/Windows. |
| src/Controls/src/Core/Editor/Editor.Mapper.cs | Adds Material3-specific mapping for EditorHandler2 on Android. |
| src/Controls/src/Core/Editor/Editor.Android.cs | Adds MapText overload for EditorHandler2. |
| src/Controls/src/Core/ContentPresenter.cs | Changes binding-context propagation behavior. |
| src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellItemRendererBase.cs | Disposes ShellContentFragment pages when removed from fragment map. |
| src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellFlyoutTemplatedContentRenderer.cs | Ensures vertical scroll mode is applied after flyout content update; removes redundant layout manager assignment. |
| src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellFlyoutRenderer.cs | Reorders flow direction update to run regardless of flyout content availability. |
| src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellFlyoutRecyclerAdapter.cs | Fixes item measurement when flyout vertical scroll is not enabled. |
| src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellContentFragment.cs | Adds explicit page disposal that disconnects handlers. |
| src/Controls/src/Core/Compatibility/Handlers/NavigationPage/iOS/NavigationRenderer.cs | Adds iOS/MacCatalyst version-gated tint updates and title view resizing handling. |
| src/Controls/src/Core/Compatibility/Handlers/FlyoutPage/iOS/PhoneFlyoutPageRenderer.cs | Applies safe-area inset adjustment to the FlyoutPage container frame. |
| src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/maui-sc.aotprofile.txt | Removes two Android PlatformInterop methods from the AOT profile. |
Comments suppressed due to low confidence (1)
src/Controls/src/Core/Handlers/Shell/ShellItemHandler.Windows.cs:219
MapMenuItems()subscribes toitem.PropertyChangedevery time it runs, but there’s no corresponding unsubscribe for already-subscribed items during remaps; this can cause duplicate handlers and repeated updates. Consider tracking subscribed items (e.g., aHashSet<BaseShellItem>) and only subscribing once, or explicitly unsubscribing before re-subscribing when rebuilding the menu.
foreach (var item in shellItemController.GetItems())
{
item.PropertyChanged += OnShellItemPropertyChanged;
if (Routing.IsImplicit(item))
items.Add(item.CurrentItem);
else
items.Add(item);
}
| MauiTextView _mauiTextView; | ||
| MauiMaterialTextView _mauiMaterialTextView; | ||
|
|
||
| private protected override void OnHandlerChangedCore() | ||
| { | ||
| base.OnHandlerChangedCore(); | ||
|
|
||
| if (Handler != null) | ||
| // Detach from previous views | ||
| DetachLayoutChanged(); | ||
|
|
||
| if (Handler is not ILabelHandler { PlatformView: var platformView }) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| switch (platformView) | ||
| { | ||
| if (Handler is LabelHandler labelHandler && labelHandler.PlatformView is MauiTextView mauiTextView) | ||
| { | ||
| _mauiTextView = mauiTextView; | ||
| case MauiTextView textView: | ||
| _mauiTextView = textView; | ||
| _mauiTextView.LayoutChanged += OnLayoutChanged; | ||
| } | ||
| break; | ||
| case MauiMaterialTextView materialTextView: | ||
| _mauiMaterialTextView = materialTextView; | ||
| _mauiMaterialTextView.LayoutChanged += OnLayoutChanged; | ||
| break; | ||
| } | ||
| else | ||
| } | ||
|
|
||
| void DetachLayoutChanged() | ||
| { | ||
| if (_mauiTextView is not null) | ||
| { | ||
| if (_mauiTextView != null) | ||
| { | ||
| _mauiTextView.LayoutChanged -= OnLayoutChanged; | ||
| _mauiTextView = null; | ||
| } | ||
| _mauiTextView.LayoutChanged -= OnLayoutChanged; | ||
| _mauiTextView = null; | ||
| } | ||
|
|
||
| if (_mauiMaterialTextView is not null) | ||
| { | ||
| _mauiMaterialTextView.LayoutChanged -= OnLayoutChanged; | ||
| _mauiMaterialTextView = null; | ||
| } | ||
| } |
There was a problem hiding this comment.
_mauiTextView and _mauiMaterialTextView are declared as non-nullable but are assigned null and are not definitely assigned at construction. This can introduce nullable warnings (and potentially fail builds if warnings are elevated). Make both fields nullable (e.g., MauiTextView?) and keep the detach logic unchanged.
| public override bool OnTouchEvent(MotionEvent e) | ||
| { | ||
| // If ItemsView is disabled, don't handle touch events | ||
| if (ItemsView?.IsEnabled == false) | ||
| { | ||
| return false; | ||
| } | ||
|
|
||
| return base.OnTouchEvent(e); | ||
| } | ||
|
|
||
| public override bool OnInterceptTouchEvent(MotionEvent e) | ||
| { | ||
| // If ItemsView is disabled, intercept all touch events to prevent interactions | ||
| if (ItemsView?.IsEnabled == false) | ||
| { | ||
| return true; | ||
| } | ||
|
|
||
| return base.OnInterceptTouchEvent(e); | ||
| } |
There was a problem hiding this comment.
OnInterceptTouchEvent returns true when disabled (intercepts), but OnTouchEvent returns false (doesn't handle). This combination can lead to inconsistent/undefined touch dispatch (e.g., event intercepted from children but not consumed). If the intent is to block interaction, prefer consuming touches when disabled (typically return true from OnTouchEvent as well), or avoid intercepting altogether.
| var itemsSource = ItemsViewAdapter.ItemsSource; | ||
| int headerValue = itemsSource.HasHeader ? 1 : 0; | ||
| int footerValue = itemsSource.HasFooter ? 1 : 0; | ||
|
|
||
| // Calculate actual data item count (excluding header and footer positions) | ||
| int actualItemCount = ItemsViewAdapter.ItemCount - footerValue - headerValue; | ||
|
|
||
| // Ensure we're within the data items region (not in header/footer) | ||
| if (Last < headerValue || Last > actualItemCount) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| // Check if we're at or within threshold distance from the last data item | ||
| bool isThresholdReached = (Last == actualItemCount - 1) || (actualItemCount - 1 - Last <= _itemsView.RemainingItemsThreshold); | ||
|
|
||
| switch (_itemsView.RemainingItemsThreshold) | ||
| if (isThresholdReached) | ||
| { | ||
| case -1: | ||
| return; | ||
| case 0: | ||
| if (Last == ItemsViewAdapter.ItemsSource.Count - 1) | ||
| _itemsView.SendRemainingItemsThresholdReached(); | ||
| break; | ||
| default: | ||
| if (ItemsViewAdapter.ItemsSource.Count - 1 - Last <= _itemsView.RemainingItemsThreshold) | ||
| _itemsView.SendRemainingItemsThresholdReached(); | ||
| break; | ||
| _itemsView.SendRemainingItemsThresholdReached(); | ||
| } |
There was a problem hiding this comment.
Last is an adapter position (includes header), but actualItemCount - 1 is a data-index. When a header is present, the threshold calculation becomes off-by-one (or more) and may fire early/late. Fix by translating Last into a data index (e.g., lastDataIndex = Last - headerValue) and comparing against actualItemCount - 1; also adjust the bounds check to use adapter positions consistently (e.g., ensure Last < headerValue + actualItemCount).
| var flags = BindingFlags.NonPublic | BindingFlags.Instance; | ||
| var currentPageField = typeof(StackNavigationManager).GetField("_currentPage", flags); | ||
| var fragmentContainerViewField = typeof(StackNavigationManager).GetField("_fragmentContainerView", flags); | ||
| var fragmentManagerField = typeof(StackNavigationManager).GetField("_fragmentManager", flags); | ||
|
|
||
| Assert.NotNull(currentPageField); | ||
| Assert.NotNull(fragmentContainerViewField); | ||
| Assert.NotNull(fragmentManagerField); | ||
|
|
||
| await AssertEventually(() => | ||
| currentPageField.GetValue(tab1SnManager) == null && | ||
| fragmentContainerViewField.GetValue(tab1SnManager) == null && | ||
| fragmentManagerField.GetValue(tab1SnManager) == null && | ||
| currentPageField.GetValue(tab2SnManager) == null && | ||
| fragmentContainerViewField.GetValue(tab2SnManager) == null && | ||
| fragmentManagerField.GetValue(tab2SnManager) == null, | ||
| message: "StackNavigationManager fields were not cleared after Disconnect()"); |
There was a problem hiding this comment.
This test depends on private-field names via reflection (_currentPage, _fragmentContainerView, _fragmentManager), which is brittle and can fail on refactors unrelated to the behavior being tested. If possible, prefer asserting observable behavior (e.g., no retained references via WeakReference/GC-based checks) or expose an internal test hook (e.g., InternalsVisibleTo) that can validate cleanup without hard-coding private field names.
| SetInheritedBindingContext(BottomItems, BindingContext); | ||
|
|
||
| // In Windows and Android, new cells are created when rebinding, so _isOpen is false. | ||
| // In iOS, CollectionView reuses cells, so SwipeView remain open (_isOpen = true). |
There was a problem hiding this comment.
Fix grammar: change 'SwipeView remain open' to 'SwipeView remains open'.
| // In iOS, CollectionView reuses cells, so SwipeView remain open (_isOpen = true). | |
| // In iOS, CollectionView reuses cells, so SwipeView remains open (_isOpen = true). |
| public abstract partial class Shape : View, IShapeView, IShape, IVersionedShape | ||
| { | ||
| WeakBrushChangedProxy? _fillProxy = null; | ||
| WeakBrushChangedProxy? _strokeProxy = null; | ||
| EventHandler? _fillChanged, _strokeChanged; | ||
| int _version; |
There was a problem hiding this comment.
Overriding OnPropertyChanged on a public control adds protected API surface and changes the behavior observed by derived types (it’s now part of Shape’s override chain). Please confirm this is acceptable for the target release (API/binary-compat expectations) and consider whether version increments should be limited to shape-render-affecting properties to avoid unnecessary invalidation/version churn on unrelated property changes.
| unchecked | ||
| { | ||
| // Increase the version before propagating the property changed notification | ||
| // so that any code responding to the notification can get the latest version. | ||
| ++_version; | ||
| } | ||
|
|
||
| base.OnPropertyChanged(propertyName); | ||
| } | ||
|
|
There was a problem hiding this comment.
Overriding OnPropertyChanged on a public control adds protected API surface and changes the behavior observed by derived types (it’s now part of Shape’s override chain). Please confirm this is acceptable for the target release (API/binary-compat expectations) and consider whether version increments should be limited to shape-render-affecting properties to avoid unnecessary invalidation/version churn on unrelated property changes.
| unchecked | |
| { | |
| // Increase the version before propagating the property changed notification | |
| // so that any code responding to the notification can get the latest version. | |
| ++_version; | |
| } | |
| base.OnPropertyChanged(propertyName); | |
| } | |
| if (IsVersionAffectingProperty(propertyName)) | |
| { | |
| unchecked | |
| { | |
| // Increase the version before propagating the property changed notification | |
| // so that any code responding to the notification can get the latest version. | |
| ++_version; | |
| } | |
| } | |
| base.OnPropertyChanged(propertyName); | |
| } | |
| bool IsVersionAffectingProperty(string? propertyName) | |
| { | |
| // When propertyName is null, we conservatively assume the change may affect rendering. | |
| if (propertyName is null) | |
| return true; | |
| // Limit version increments to properties that affect the rendered shape. | |
| return propertyName == nameof(Fill) || | |
| propertyName == nameof(Stroke); | |
| } |
| #if ANDROID | ||
| if (RuntimeFeature.IsMaterial3Enabled) | ||
| { | ||
| handlersCollection.AddHandler<Label, LabelHandler2>(); | ||
| } | ||
| else | ||
| { | ||
| handlersCollection.AddHandler<Label, LabelHandler>(); | ||
| } | ||
| #else | ||
| handlersCollection.AddHandler<Label, LabelHandler>(); | ||
| #endif | ||
| #if ANDROID | ||
| if (RuntimeFeature.IsMaterial3Enabled) | ||
| { | ||
| handlersCollection.AddHandler<Editor, EditorHandler2>(); | ||
| } | ||
| else | ||
| { | ||
| handlersCollection.AddHandler<Editor, EditorHandler>(); | ||
| } | ||
| #else | ||
| handlersCollection.AddHandler<Editor, EditorHandler>(); | ||
| #endif |
There was a problem hiding this comment.
The Material3 handler selection pattern is duplicated for multiple controls (Label/Editor/Picker/RadioButton/TimePicker). Consider factoring this into a small helper (or a local function) to reduce repetition and the risk of future inconsistencies when adding/removing Material3 handler variants.
… - 1 (#34334) This PR addresses the UI test image failures that occurred in the inflight/candidate branch #34294 and includes updates to improve rendering and test stability across platforms. ### Controls Handler Registration * Simplified the logic for registering handlers for controls like `Label`, `Editor`, `Picker`, `RadioButton`, and `TimePicker` in `AppHostBuilderExtensions.cs`. The new approach registers all fallback handlers together, reducing duplicated code and improving maintainability. ### * In the NavigationRootManager class, the line _rootView.SetTitleBar(null, null); was added in this PR #34032 by a contributor due to an AI minor suggestion, but this line causes an issue when swapping pages, so the TitlebarWorksWhenSwitchingPage test fails. Setting SetTitleBar to null is already implemented in the WindowHandler class in the [DisconnectHandler](https://github.com/dotnet/maui/blob/main/src/Core/src/Handlers/Window/WindowHandler.Windows.cs#L55) method, so I have removed this line _rootView.SetTitleBar(null, null); from the PR [34032](#34032). ### Image Resave: * Resaved images: DownSizeImageAppearProperly, Material3CheckBoxFeatureTests, Material3CheckBox_DefaultAppearance, DownSizeImageAppearProperly, VerifyLinearGradientBrushWithStrokeAndOpacity, VerifyRadialGradientBrushWithOpacity, VerifyRadialGradientBrushWithShadowAndOpacity, VerifyLinearGradientBrushWithOpacity, VerifyLinearGradientBrushWithShadowAndOpacity, DarkTheme_VerifyVisualState. These PR fixes address the issues: #33173, #31567, #33590, #34036 * Added the base images for iOS 26, Mac, and Windows. ### Test Stability and Platform-Specific Handling * Added a platform-specific ignore for a Shell flyout test on iOS 26 due to a known bug, improving test reliability and clarity about platform limitations. * Updated a CollectionView scroll test to wait for specific elements on Windows, ensuring the test works correctly across platforms. ### DatePicker Handler Tests * Introduced a helper method `EnsureDialogCreated` in `DatePickerHandlerTests.Android.cs` to reliably create the native dialog before reading min/max values, addressing issues caused by lazy dialog creation after a recent PR. This helper is now used in relevant tests to improve robustness. [[1]](diffhunk://#diff-de28fdea458f311cfcc7e767c7e9e2a4c7c36e4d065ae2ebf2a25b420f183c29R26) [[2]](diffhunk://#diff-de28fdea458f311cfcc7e767c7e9e2a4c7c36e4d065ae2ebf2a25b420f183c29R54) [[3]](diffhunk://#diff-de28fdea458f311cfcc7e767c7e9e2a4c7c36e4d065ae2ebf2a25b420f183c29R131-R146) * Clarified the DatePicker test logic in `DatePickerTests.cs` to ensure the `DateSelected` event fires correctly regardless of dialog state, improving test reliability on Android. ### Test Case Organization * Removed the obsolete `VerifyFlyoutPage_IsEnabled` test and renumbered the remaining FlyoutPage tests in `FlyoutPageFeatureTests.cs` to maintain sequential order and consistency. [[1]](diffhunk://#diff-a20c8165e92130c8ebbda3af607c3dd309cf1c1b6c85942abd6ed81132510fb3L176-R177) [[2]](diffhunk://#diff-a20c8165e92130c8ebbda3af607c3dd309cf1c1b6c85942abd6ed81132510fb3L204-R191) [[3]](diffhunk://#diff-a20c8165e92130c8ebbda3af607c3dd309cf1c1b6c85942abd6ed81132510fb3L222-R209) [[4]](diffhunk://#diff-a20c8165e92130c8ebbda3af607c3dd309cf1c1b6c85942abd6ed81132510fb3L240-R227) [[5]](diffhunk://#diff-a20c8165e92130c8ebbda3af607c3dd309cf1c1b6c85942abd6ed81132510fb3L254-R241) [[6]](diffhunk://#diff-a20c8165e92130c8ebbda3af607c3dd309cf1c1b6c85942abd6ed81132510fb3L268-R255) [[7]](diffhunk://#diff-a20c8165e92130c8ebbda3af607c3dd309cf1c1b6c85942abd6ed81132510fb3L284-R271) [[8]](diffhunk://#diff-a20c8165e92130c8ebbda3af607c3dd309cf1c1b6c85942abd6ed81132510fb3L299-R286) [[9]](diffhunk://#diff-a20c8165e92130c8ebbda3af607c3dd309cf1c1b6c85942abd6ed81132510fb3L310-R297) [[10]](diffhunk://#diff-a20c8165e92130c8ebbda3af607c3dd309cf1c1b6c85942abd6ed81132510fb3L327-R314) [[11]](diffhunk://#diff-a20c8165e92130c8ebbda3af607c3dd309cf1c1b6c85942abd6ed81132510fb3L340-R327) [[12]](diffhunk://#diff-a20c8165e92130c8ebbda3af607c3dd309cf1c1b6c85942abd6ed81132510fb3L357-R344) [[13]](diffhunk://#diff-a20c8165e92130c8ebbda3af607c3dd309cf1c1b6c85942abd6ed81132510fb3L376-R363) [[14]](diffhunk://#diff-a20c8165e92130c8ebbda3af607c3dd309cf1c1b6c85942abd6ed81132510fb3L387-R374) [[15]](diffhunk://#diff-a20c8165e92130c8ebbda3af607c3dd309cf1c1b6c85942abd6ed81132510fb3L400-R387)
|
/rebase |
>[!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 introduces a new Shell feature matrix to the test cases host app, enabling comprehensive testing and demonstration of Shell and Shell Flyout capabilities. The changes add new pages, controls, and a view model to support customizable Shell Flyout behaviors and UI elements, including dynamic menu items and property bindings. The tests validate the Shell Flyout Page , including properties such as FlyoutBehavior, FlyoutHeader, FlyoutFooter, FlyoutBackdrop, FlyoutBackgroundColor, FlyoutBackgroundImage, FlyoutBackgroundImageAspect, FlyoutVerticalScrollMode, FlyoutIcon, FlyoutDisplayOptions, FlyoutWidth, FlyoutHeight, FlyoutItemIsVisible, FlyoutHeaderBehavior, MenuItemTemplate, ItemTemplate, FlyoutIsPresented. **Shell feature matrix integration:** * Added `ShellFeaturePage` and `ShellFeatureMainPage` to the feature matrix, allowing navigation to a new Shell test area from the core views. (`CorePageView.cs`, `ShellFeaturePage.xaml`, `ShellFeaturePage.xaml.cs`) [[1]](diffhunk://#diff-adf403d0453beb6436df5f6e4d418d2f62d9c7a1b549a22b048879127df36a38R120) [[2]](diffhunk://#diff-429088ce96d697ab4ebcb64f4f34eab95990318df0e699a206770e487cc5f99cR1-R16) [[3]](diffhunk://#diff-d9fe6832827db8c2b917b1667eb42de532a901608d7f118f002848d9a7fc5018R1-R26) **Shell Flyout demonstration and customization:** * Introduced `ShellFlyoutControlPage` with extensive bindings for Shell Flyout properties and templates, supporting dynamic customization and demonstration of Shell Flyout features. (`ShellFlyoutControlPage.xaml`, `ShellFlyoutControlPage.xaml.cs`) [[1]](diffhunk://#diff-3a9efdaa6e9a34aee2ebe539712716dad7cdcdd706c3ba78eb3740128120541eR1-R81) [[2]](diffhunk://#diff-bee4c2ead6ccb4b4e65b00d9fa652b7a497d40c0f130d5d6de20c27edd8cfb79R1-R48) * Implemented event handlers and logic for toggling the flyout, changing flyout behavior, and navigating to options, as well as generating 40 dynamic menu items for testing. (`ShellFlyoutControlPage.xaml.cs`) **ViewModel for Shell Flyout customization:** * Added `ShellViewModel` with bindable properties for all Shell Flyout aspects (e.g., header, footer, behavior, templates, background, etc.), enabling property change notifications and supporting UI binding in the Shell Flyout demonstration. (`ShellViewModel.cs`) #### Issues Identified - #32416 - #32417 - #32419 - #32476 https://github.com/user-attachments/assets/7b4eb1a6-f994-4510-b4cd-cfeb901edf88
…orientation change (#31962) ### Root Cause On Android and Windows, the `FlyoutPage` toolbar button did not update correctly when the device orientation changed. The `NavigationPageToolbar` lacked orientation change detection, so `ShouldShowToolbarButton()` was never re-evaluated after rotation. ### Description of Change On orientation change, `FlyoutPage.OnMainDisplayInfoChanged` now fires `OnPropertyChanged(nameof(FlyoutLayoutBehavior))` on Android and Windows. This propagates through the existing `ToolbarTracker.PagePropertyChanged` pipeline to `NavigationPageToolbar`, which re-evaluates `ShouldShowToolbarButton()` via `ApplyChanges()`. `NavigationPageToolbar` was updated to listen for `FlyoutLayoutBehavior` property changes alongside its existing property filters. iOS is excluded as it handles this natively through `PhoneFlyoutPageRenderer.ViewWillTransitionToSize()`. ### Issues Fixed Fixes #24468 Tested the behaviour in the following platforms - [x] Android - [x] Windows - [x] iOS - [ ] Mac **Note:** The fix was implemented and tested on Android, iOS, and Windows platforms, as orientation changes could not be performed on macOS. ### Output Video Before Issue Fix | After Issue Fix | |----------|----------| |<video width="40" height="60" alt="Before Fix" src="https://github.com/user-attachments/assets/1ad9c143-c087-4fd1-aa8c-5bd59e86519e">|<video width="50" height="40" alt="After Fix" src="https://github.com/user-attachments/assets/b219267a-e830-490f-994a-570fa6d928b3">|
… iOS (#29265) ### Root Cause On iOS devices with notches (iPhone X and newer), the FlyoutPage.Flyout content was rendering beneath the status bar because `PhoneFlyoutPageRenderer` ignored safe area insets and positioned the flyout. Although individual ContentPages honor safe areas when ios:Page.UseSafeArea is true, the Flyout container did not. ### Description of Change The fix checks whether the FlyoutPage implements `ISafeAreaView` and respects the safe area settings. If` ios:Page.UseSafeArea` is enabled and the platform is iOS 11 or higher, the Flyout container’s frame is adjusted by shifting its Y origin to match the top safe area inset and reducing its height accordingly. This ensures that all child content, including CollectionView and other controls, render below the notch or status bar. To apply this fix effectively, developers must explicitly set `ios:Page.UseSafeArea="true"` on the FlyoutPage, as the `UseSafeArea property` defaults to false for FlyoutPage. ### Issues Fixed Fixes #29170 Tested the behaviour in the following platforms - [x] Android - [x] Windows - [x] iOS - [x] Mac ### Note This issue is specific to iOS devices with notches or status bar areas. ### Screenshots | Before Issue Fix | After Issue Fix | |------------------|-----------------| | <img width="350" alt="withoutfix" src="https://github.com/user-attachments/assets/b21dda5c-276f-4636-8505-d9fa5b28b479" /> | <img width="350" alt="withfix" src="https://github.com/user-attachments/assets/8fac5454-3745-46e4-905a-f01a587b2265" /> |
…ollectionView has Header and Footer both defined (#29618) <!-- 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 Description In Android, the `RemainingThresholdReached` command is not triggered when both a `Header` and a `Footer` are defined for the collection. ### RootCause The `SendRemainingThresholdReached` method is triggered based on the `LastVisibleIndex` and the `ItemCount` provided by the ItemAdapter. However, on Android, when both a Header and a Footer are defined, the ItemCount consider it, leading to incorrect triggering logic. ### Description of Change Updated the logic to ensure that the ItemCount correctly includes both the Header and Footer. This change ensures that the Footer becomes visible as expected and that the SendRemainingThresholdReached command is properly executed. ### Issues Fixed Fixes #29588 ### Tested the behaviour in the following platforms - [x] Android - [x] Windows - [x] iOS - [x] Mac ### Output Screenshot Before Issue Fix | After Issue Fix | |----------|----------| |<video width="40" height="60" alt="Before Fix" src="https://github.com/user-attachments/assets/919c566b-c5f4-431f-9498-2b7f254e73d9">|<video width="50" height="40" alt="After Fix" src="https://github.com/user-attachments/assets/ad7490d5-410c-43a8-b4bd-8702a2bfc48f">| --------- Co-authored-by: MartyIX <203266+MartyIX@users.noreply.github.com>
### Issue Details In the Shell, when the Tab.isEnabled property is set to false, the tab should be non-interactive and prevent user interaction. the current behavior allows the tab to be clicked. ### Root Cause In Windows, implementation property for IsEnabled property is not handled. ### Description of change For the Windows platform, a new IsEnabled property was introduced in NavigationViewItemViewModel and registered within NavigationViewItem in the TabbedPageXaml.Windows page. The BaseShellItem.IsEnabled property is now mapped to this newly added property in the view model. Additionally, support was added to handle runtime updates by responding to property-changed events, ensuring the enabled state reflects changes dynamically. ### Validated the Behavior in the following Platforms - [ ] Android - [ ] iOS - [ ] mac - [x] WinUI ### Issue fixed Fixes #5161 Fixes #32996 ### Screenshots | Before Issue Fix | After Issue Fix | |--|--| |<video src="https://github.com/user-attachments/assets/26173aef-ec99-4549-b88d-7e0a6f629052">|<video src='https://github.com/user-attachments/assets/a4eada5e-c5e7-4a0f-b312-af131813d4bf'>| --------- Co-authored-by: Dhivya-SF4094 <127717131+Dhivya-SF4094@users.noreply.github.com>
### Description of Change Updated the Syncfusion Toolkit version from 1.0.8 to 1.0.9
…34036) <!-- 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 On iOS/MacCatalyst 26+, toolbar items show in their original image color instead of the color set by the app through BarTextColor. The custom tint color is ignored and the image appears with its own natural color. ### Root Cause Before iOS/MacCatalyst 26, the navigation bar applied its tint color over toolbar item images automatically, overriding their original color. iOS 26 stopped doing this — now toolbar items keep their original image color and ignore the navigation bar's tint. ### Description of Change After setting the navigation bar color, manually apply that same color to each toolbar item. This is done in two places — once when the color changes, and once when toolbar items are added to the page. Validated the behavior in the following platforms - [x] Android - [x] Windows - [x] iOS - [x] Mac ### Issues Fixed Fixes #33970 ### Output ScreenShot |Before|After| |--|--| | <video src="https://github.com/user-attachments/assets/114728d1-0ebf-4f9a-9132-90b8ad041b1b" >| <video src="https://github.com/user-attachments/assets/a6175fde-fcb5-4490-ae7b-b4b56aa8815a">|
> [!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 adds a comprehensive new brushes feature matrix test page to the controls test app, enabling interactive testing and configuration of brush, stroke, and shadow features, including solid, linear, and radial gradients. It introduces two new pages—one for visualizing and comparing brush features and another for configuring brush options—along with the necessary navigation and event handling logic. **New Brushes Feature Matrix functionality:** * Added a new entry for "Brushes Feature Matrix" to the gallery page factory list, making the new test page accessible from the app's main navigation. * Implemented the `BrushesControlPage` and `BrushesControlMainPage` classes to provide a navigation page and main content page for brush feature testing, including event handlers for comparing brushes and navigating to options. * Created the `BrushesControlPage.xaml` UI, which displays the current brush, stroke, and shadow settings, allows brush comparison, and shows selected color details. **Brush options and customization:** * Added a detailed `BrushesOptionsPage` (XAML and code-behind) that lets users select and configure brush types (none, solid, linear, radial), shadow types, stroke types, opacity, alternate variants, and color selections, with all changes bound to a shared `BrushesViewModel`. [[1]](diffhunk://#diff-a0b81253f3786054d00a4400d1fca4280fef128db5e618e0fae7bc845b7b70d8R1-R242) [[2]](diffhunk://#diff-f1180dfb2805a40c7a208076e415971e8e6639f58b9091c0a166c975671374d8R1-R130) https://github.com/user-attachments/assets/c4280d48-ebb3-45d3-a5bf-3388ea32e459
…r. (#33643) <!-- 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. !!!!!!! --> ### Description of Change <!-- Enter description of the fix in this section --> This pull request fixes a bug in the `CircleOnPropertyChanged` method of the Android map handler where the circle's stroke color was incorrectly applied to FillColor instead of StrokeColor. Root Cause: A copy-paste error in `CircleOnPropertyChanged` caused the Stroke paint to be assigned to nativeCircle.FillColor instead of nativeCircle.StrokeColor. The sibling methods PolygonOnPropertyChanged and PolylineOnPropertyChanged correctly set StrokeColor, but the circle method had the wrong property name. Fix: Changed the assignment from nativeCircle.FillColor to nativeCircle.StrokeColor when mapping mauiCircle.Stroke to the native circle, ensuring stroke and fill colors are applied to the correct native properties. Bug fix and code clarity improvements: * Fixed assignment to set `nativeCircle.StrokeColor` (instead of `FillColor`) from the `Stroke` property, ensuring the circle's stroke color is updated correctly. * Added braces and an explicit null check for `nativeCircle` to improve code readability and prevent potential null reference errors. ### 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 #33642 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> ### Output | Before | After | |--|--| | <video src="https://github.com/user-attachments/assets/f3559741-e794-403c-a590-c9c871f25995"> |<video src="https://github.com/user-attachments/assets/6174a836-082c-4ae8-9a93-09649b92f9b6"> |
<!-- 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. !!!!!!! --> ### Root cause: `FlowDirection` changes were not applied when _flyoutContent was null. Because the method returned early, the FlowDirection update logic did not executed on dynamic updates. But this check is not required for tabbar. ### Description of Change : Updated `OnShellPropertyChanged` in `ShellFlyoutRenderer.cs` to always process FlowDirection changes before checking _flyoutContent, ensuring flow direction updates apply correctly even when the flyout has not yet been created. ### 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 #32993 ### Tested the behavior in the following platforms - [x] Windows - [x] Android - [x] iOS - [x] Mac | Before Issue Fix | After Issue Fix | |----------|----------| | <video src="https://github.com/user-attachments/assets/9eafa422-53a8-449b-ba15-6462d16353d4"> | <video src="https://github.com/user-attachments/assets/5a20cc1d-abf5-4f5c-b0d6-5a8b5512e517"> | <!-- 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! ### Issue Detail When using Shell's GoToAsync() with replace navigation (e.g., `GoToAsync("../otherpage")`), the removed page is not properly cleaned up on Android. The page handler remains referenced, preventing garbage collection and causing memory accumulation over navigations. ### Root Cause On Android, Shell uses Fragments to display pages. During replace navigation, a new page is pushed while the old page is popped, but references to the old page are still retained. Because the page handler and associated resources are not explicitly disposed, pages can accumulate in memory over time ### Description of Change When Remove occurs, the code now directly calls DisposePage() on the associated ShellContentFragment. The DisposePage method calls Destroy to clean up UI resources, invokes DisconnectHandlers on the page, and nullifies the page reference. ### Tested the behavior in the following platforms - [x] Android - [x] Windows - [x] iOS - [x] Mac ### Issues Fixed Fixes #25134 ### Screenshots | Before Issue Fix | After Issue Fix | |----------|----------| | <video width="300" height="600" src="https://github.com/user-attachments/assets/e1b35b27-1144-45be-a522-77fbb07bae02"> | <video width="300" height="600" src="https://github.com/user-attachments/assets/bb450c26-4459-43ac-9a4f-b92fed0cefdd">) |
…age loading (#33590) <!-- 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 Stream-based and resource-based image loading consumed excessive memory on Android versus XAML image loading. Images were loaded at display dimensions instead of original dimensions, affecting all apps using embedded resources or streams. ### Root Cause Glide upscaled stream-based images to display dimensions without size constraints. XAML had proper size handling, but stream loading lacked overrides, causing memory to scale with screen size not image size. ### Description of Change Added size override in PlatformInterop.java to preserve original image dimensions. This prevents upscaling to display dimensions, making all loading methods produce consistent memory usage. Validated the behavior in the following platforms - [x] Android - [ ] Windows - [ ] iOS - [ ] Mac ### Issues Fixed Fixes #33239 ### Output ScreenShot | Before | After | |---------|--------| | <img width="352" height="759" alt="33239-BeforeFix" src="https://github.com/user-attachments/assets/a1ed4f05-e39a-4d1f-a974-2dc589bf7d78" /> | <img width="352" height="759" alt="33239-AfterFix" src="https://github.com/user-attachments/assets/64b067bc-da36-4690-a077-8022ac621223" /> |
…33853) <!-- 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 CollectionView’s programmatic ScrollTo does not work when using a horizontal ItemsLayout on iOS/MacCatalyst. After calling ScrollTo(index, position: ScrollToPosition.Start, animate: true), the scroll position remains unchanged. ### Root Cause In the CV2 iOS handler, the scroll direction is hardcoded to Vertical instead of using the actual layout direction. As a result, horizontal layouts receive incorrect scroll position calculations. ### Description of Change Replace the hardcoded vertical direction with a dynamic call that retrieves the actual scroll direction from the controller. This ensures that horizontal layouts receive the correct scroll position values. ### Fix reference I have fixed the issue in the same way as CV1, by referring to the following code. https://github.com/dotnet/maui/blob/52f9fc2a308b518890cf6def72abe422ac997d85/src/Controls/src/Core/Handlers/Items/ItemsViewHandler.iOS.cs#L110 Validated the behavior in the following platforms - [x] Android - [x] Windows - [x] iOS - [x] Mac ### Issues Fixed Fixes #33852 ### Output ScreenShot |Before|After| |--|--| | <video src="https://github.com/user-attachments/assets/1d510715-83bf-412c-a8a3-6f8362dd52bd" >| <video src="https://github.com/user-attachments/assets/0283113a-33ed-4d14-9d1d-a18ab9f2e2d0">|
… TemplateBinding (#30880) <!-- 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 When using a `ContentPresenter` with an **explicit** `TemplateBinding` to a custom `BindableProperty` in a `ControlTemplate`, child elements inside the `ContentPresenter` do not inherit the binding context. This causes data bindings (e.g. `Command`) to fail silently. **Repro:** Create a `ContentView` subclass with a custom `BindableProperty` of type `View` (e.g. `MyContent`), use it in a `ControlTemplate` with `ContentPresenter.ContentProperty` explicitly bound to that property via `TemplateBinding`, and place a `Button` with a `Command` binding inside. The command will not fire. ### Root Cause `ContentPresenter` overrides `SetChildInheritedBindingContext` with an intentional no-op: ```csharp // We never want to use the standard inheritance mechanism, we will get this set by our parent ``` This design came from the Xamarin.Forms era where the binding context was assumed to be set through a different propagation path. With the **default** `ContentPresenter` behavior (content bound via `ContentConverter` on `IContentView.Content`), the binding context eventually propagates correctly because the ControlTemplate's content tree is wired up through `ParentOverride` and the templated parent. However, with an **explicit** `TemplateBinding` to a custom `BindableProperty`, the binding resolves directly without going through the templated parent propagation path. The `SetChildInheritedBindingContext` override silently discards the inherited context, so child elements never receive the `BindingContext` from the templated parent. Note: `ContentConverter` does NOT handle binding context — it only forwards text/font properties from ancestor elements. ### Description of Change **`src/Controls/src/Core/ContentPresenter.cs`** Removed the no-op override in `SetChildInheritedBindingContext` and replaced it with an actual call to `SetInheritedBindingContext(child, context)`. This ensures that when binding context flows down the element tree to a `ContentPresenter`, its children receive the inherited context — matching the standard MAUI/WinUI behavior where `DataContext` always propagates through the template tree. This is consistent with the direction taken in PR #26072, which committed to always propagating `BindingContext` through `ControlTemplate` hierarchies. ### Key Technical Details - `SetChildInheritedBindingContext` is called by the element tree's inherited binding context propagation mechanism when a parent's `BindingContext` changes. - The `ContentPresenter` constructor sets up a default binding on `ContentProperty` using `ContentConverter` and `RelativeBindingSource.TemplatedParent`. This default path is NOT affected by this change. - `ContentConverter` only handles text/font property propagation — it does not participate in `BindingContext` inheritance. - The fix aligns `ContentPresenter` with standard `SetInheritedBindingContext` behavior used by all other layout types. ### Issues Fixed Fixes #23797 ### Platforms Tested - [x] Windows - [x] Android - [x] iOS - [x] Mac
…n disposed (#29964) <!-- 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 - In GraphicsView, the Resize method returns an image that has already been disposed. ### Root Cause - The Bitmap property returned the internal _bitmap instance directly, which would be disposed during the Dispose() call if disposeBitmap was set to true, potentially leading to access of a disposed object. ### Description of Change - Changed the disposeBitmap parameter to false in the PlatformImage.Resize method to prevent the returned image from being disposed on Android (PlatformImage.cs). ### Issues Fixed Fixes #29961 Fixes #31103 ### Validated 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/a2f1bb88-ab79-4d71-9911-4eec716ecc8c"> | <video src="https://github.com/user-attachments/assets/fe4e5aac-5179-4fd3-b781-61c900f804d0"> |
… control (#30505) <!-- 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 - When typing into Entry control on iOS, the CursorPosition property is not updated. ### Root Cause - OnEditingChanged was updating the text but not the cursor position, causing the virtual view's cursor position to become out of sync with the platform view during typing. ### Description of Change - Introduced a new method UpdateCursorPosition in the ITextInputExtensions class to update the cursor position if it differs from the current value. - Updated EntryHandler.iOS to call UpdateCursorPosition during the OnEditingChanged event, ensuring the cursor position stays in sync with text changes. ### Issues Fixed Fixes #20911 Fixes #32483 ### Validated 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/cedc652c-ba03-4c8c-9da1-1cd669edfb53"> | <video src="https://github.com/user-attachments/assets/0ab91254-e8b0-44d5-ac45-1e4c0ceaa1c9"> |
<!-- 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. !!!!!!! --> ### Root Cause: When the IndicatorSize changed, the layout wasn’t updated, so the new size didn’t appears ### Description of Change Changed the UpdateIndicatorSize method in UIPageControlExtensions.cs to call InvalidateMeasure(), ensuring that the indicator view is properly remeasured and updated when its size changes. <!-- 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 #31064 ### Tested the behaviour in the following platforms : - [x] Windows - [x] Android - [x] iOS - [x] mac ### Screenshot | Before Issue Fix | After Issue Fix | |----------|----------| | <video src="https://github.com/user-attachments/assets/891d33a7-6221-470f-9b9e-066512784296"> | <video src="https://github.com/user-attachments/assets/526f4058-85b9-4585-89ed-f665eba3b7d9"> | <!-- 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! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details On iOS, when a SwipeView is placed inside a CollectionView and its content is updated, the swipe items remain in the open state. ### Description of Change <!-- Enter description of the fix in this section --> When the BindingContext changes, manually close the open state of the SwipeView. ### 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 #19541 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | **iOS**<br> <video src="https://github.com/user-attachments/assets/75a1ec0f-faec-4f7e-9093-72298f1d63c4" width="300" height="600"> | **iOS**<br> <video src="https://github.com/user-attachments/assets/847b5c7e-9339-4749-aae7-a8e0fb73baed" width="300" height="600"> |
…visibility changes (#33359) <!-- 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 Android, the content area in a TabbedPage shows incorrect layout when tabs use mixed HasNavigationBar values (some true, some false). When switching to a tab where the NavigationBar is visible, the content area does not properly account for the toolbar height, resulting in content being obscured by the NavigationBar. **Regression PR:** #27294 ### Root Cause PR #27294 introduced a default OffscreenPageLimit value, which pre-creates tab fragments during initialization. When switching between tabs with different HasNavigationBar values, Android's insets system does not automatically recalculate layout measurements because they were cached during the pre-creation phase. While the toolbar height updates correctly via LayoutParameters, the content area continues using stale inset measurements. ### Description of Change Added a call to AndroidX.Core.View.ViewCompat.RequestApplyInsets(nativeToolbar) in ToolbarExtensions.UpdateIsVisible after updating LayoutParameters. This explicitly requests Android to re-dispatch window insets through the view hierarchy, triggering remeasurement of the content area when the toolbar visibility or height changes. **References:** [Android/ContentViewGroup.cs#L149](https://github.com/dotnet/maui/blob/main/src/Core/src/Platform/Android/ContentViewGroup.cs#L149) [Android/LayoutViewGroup.cs#L166](https://github.com/dotnet/maui/blob/main/src/Core/src/Platform/Android/LayoutViewGroup.cs#L166) [Android/MauiScrollView.cs#L303](https://github.com/dotnet/maui/blob/main/src/Core/src/Platform/Android/MauiScrollView.cs#L303) ### Tested the behavior in the following platforms - [x] Android - [x] Windows - [x] iOS - [x] Mac ### Issues Fixed Fixes #33340 ### Screenshots | Before Issue Fix | After Issue Fix | |----------|----------| | <video width="300" height="600" src="https://github.com/user-attachments/assets/e15fe58b-a609-442c-911f-0e0f04ee8545"> | <video width="300" height="600" src="https://github.com/user-attachments/assets/e5da01a3-c0b8-4fc1-a443-efff1409dd82">) | --------- Co-authored-by: Shane Neuville <shneuvil@microsoft.com> Co-authored-by: Jakub Florkowski <kubaflo123@gmail.com>
…iPadOS 26+ (#33088) <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Description: On iPadOS 26+, NavigationPage.TitleView does not resize when the window dimensions change during device rotation, causing the TitleView to remain at its original width instead of expanding to fill the navigation bar. ### Root Cause iOS 26+ changed UIKit's layout behavior so that NavigationItem.TitleView container frames are no longer automatically updated during ViewWillTransitionToSize transitions, causing the TitleView to retain its original dimensions even when the navigation bar resizes. ### Description of Change Added explicit frame updates for the TitleView Container during view controller transitions on iOS 26+ by leveraging AnimateAlongsideTransition to synchronize the Container's frame with the navigation bar's dimensions, ensuring smooth resizing during rotation and window size changes. ### Issues Fixed Fixes #[32722 ](#32722) ### Tested the behaviour on the following platforms - [ ] Android - [ ] Windows - [x] iOS - [ ] Mac ### Note: This PR extends the behavior introduced in #32815 by adding support for the iPad scenario. As the earlier PR already provided the necessary test coverage, no new testcases are included in this follow‑up. ### Output Screenshot Before Issue Fix | After Issue Fix | |----------|----------| |<video width="300" height="150" alt="Before Fix" src="https://github.com/user-attachments/assets/22f2318e-0cbf-40e4-bbe6-0fb89d22b49f">|<video width="300" height="150" alt="After Fix" src="https://github.com/user-attachments/assets/492bac5f-447a-4c1d-9262-e0877053c1f5">|
>[!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 introduces a new "Shell Feature Matrix" to the test application, providing a comprehensive set of test cases for Shell and Shell Tabbed scenarios in .NET MAUI. It adds new pages, XAML layouts, and view models to allow interactive testing of Shell features, including tab navigation, dynamic properties, and content updates. The tests validate the Shell Tabbed Page , including properties such as TabBarBackgroundColor, TabBarDisabledColor, TabBarForegroundColor, TabBarTitleColor, TabBarUnselectedColor, TabBarIsVisible, IsVisible, IsEnabled and FlowDirection **Shell Feature Matrix Integration:** - Added a new entry for "Shell Feature Matrix" to the list of available feature matrix pages in the test app, making Shell-related tests easily accessible. **Shell Feature Matrix Main Page:** - Introduced `ShellFeaturePage` and `ShellFeatureMainPage`, providing a landing page with a button to launch the Shell Tabbed feature matrix. [[1]](diffhunk://#diff-429088ce96d697ab4ebcb64f4f34eab95990318df0e699a206770e487cc5f99cR1-R16) [[2]](diffhunk://#diff-d9fe6832827db8c2b917b1667eb42de532a901608d7f118f002848d9a7fc5018R1-R24) **Shell Tabbed Feature Matrix Implementation:** - Added a detailed `ShellTabbedControlPage` with a XAML layout containing twelve tabs, each with unique content, navigation buttons, and data bindings for various Shell properties and tab states. This enables thorough testing of tabbed navigation, tab visibility, and property bindings. - Implemented code-behind for `ShellTabbedControlPage` to handle navigation, tab switching, and data binding through a `ShellViewModel`, supporting dynamic updates and interactions within the tabbed shell. #### Issues Identified - #32992 - #32993 - #32994 - #32995 - #32996 - #33158 https://github.com/user-attachments/assets/818e6319-0f9e-4d1e-84fd-649d724c63e1
…ge on Android when using NavigationPage. (#32311) <!-- 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 Description: On Android, when navigating from one page to another (Navigation.PushAsync(...)), the icons from the previous page may persist on the new page. This doesn’t happen all the time (in either debug or release mode); it occurs randomly. ### Root Cause: The issue occurs because of a race condition between asynchronous icon loading and navigation in MAUI's Android toolbar implementation. When navigating from a page with more toolbar items to a page with fewer items (e.g., 3 items → 2 items), the Android MenuItems get reused for performance optimization. However, the icon loading for FontImageSource uses async callbacks that can complete after navigation has already happened. The async callbacks from the previous page's toolbar items (like "Delete" and "Edit" icons) can fire after the new page has already set up its toolbar items (like "Cancel" and "Validate" icons), causing the old icons to overwrite the new ones. The race condition is timing-dependent and more likely to occur when there are more toolbar items being reused, which explains why the issue manifests primarily when navigating from pages with higher item counts to pages with lower item counts. ### Fix Description: The fix involves implementing a tracking mechanism that associates each MenuItem with its current ToolbarItem to prevent stale async callbacks from overwriting correct icons. A dictionary maps MenuItem IDs to weak references of their currently assigned ToolbarItem. When an async icon loading callback fires, the code validates that the MenuItem is still associated with the ToolbarItem that initiated the icon loading operation. If a different ToolbarItem is now associated with that MenuItem (indicating the MenuItem was reused for a different toolbar item after navigation), the callback is aborted and logged as a detected race condition. This prevents async callbacks from previous pages from contaminating the icons on the current page. The mapping is cleaned up when MenuItems are disposed to prevent memory leaks. This solution maintains the performance benefits of MenuItem reuse while eliminating the race condition that caused icon persistence across page navigation. **Note:** This issue occurs in a random manner, so it's not possible to add a test case for it. ### Issues Fixed Fixes #31727 ### Tested the behaviour in the following platforms - [x] Android - [x] Windows - [x] iOS - [x] Mac ### Output Screenshot Before Issue Fix | After Issue Fix | |----------|----------| |<video width="100" height="100" alt="Before Fix" src="https://github.com/user-attachments/assets/9238df6b-d6d5-4e18-8472-d569127c5959">|<video width="100" height="100" alt="After Fix" src="https://github.com/user-attachments/assets/ed359046-b420-4bf7-a3cd-8dc1a4a84e6c">| --------- Co-authored-by: Rui Marinho <me@ruimarinho.net> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: rmarinho <1235097+rmarinho@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: TamilarasanSF4853 <tamilarasan.velu@syncfusion.com>
…34110) <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> <!-- 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! ### RootCause : `Span` elements did not inherit font properties from a styled parent `Label`, causing inconsistent rendering across platforms. ### Description of Change * Updated `FormattedStringExtensions` on Android, iOS, and Windows to ensure `Span` elements inherit `FontFamily` and `FontSize` from the parent `Label`'s style if not explicitly set on the `Span` itself. * This is done by checking if the `Span` has these properties set, and if not, falling back to the parent/default values. <!-- 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 #21326 ### Tested the behavior in the following platforms - [x] Windows - [x] Android - [x] iOS - [x] Mac | Before Issue Android Fix | After Issue Android Fix | |----------|----------| | <img width="1080" height="1920" alt="BeforeFixAndroid21326" src="https://github.com/user-attachments/assets/f7f3f5f4-9f7a-43eb-bfa4-2cd7736949b3"> |<img width="1080" height="1920" alt="AfterFixAndroid21326" src="https://github.com/user-attachments/assets/1c08fcce-8dd8-4623-b886-55b6ead14cd4"> | Before Issue iOS Fix | After Issue iOS Fix | <img width="1125" height="2436" alt="BeforeFixiOS21326" src="https://github.com/user-attachments/assets/902ac55f-0e78-417e-ad68-908d7a6494ae" /> | <img width="1125" height="2436" alt="AfterFixiOS21326" src="https://github.com/user-attachments/assets/e116c6db-2977-44e7-a892-d2538aa29223" /> | <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> --------- Co-authored-by: Vignesh-SF3580 <102575140+Vignesh-SF3580@users.noreply.github.com>
…teractions (#31403) ### Root Cause **iOS** The underlying `UICollectionView` does not inherit from `UIControl`, so it has no native Enabled property. In `ViewExtensions.UpdateIsEnabled`, this caused an early return for non-UIControl views, leaving touch interactions active when `IsEnabled = false`. **Android** `RecyclerView` does not support a native enabled/disabled state. While `UpdateIsEnabled` is called when `IsEnabled = false`, there was no platform-specific handling, so touch interactions remained functional. ### Description of Change **iOS** Modified `ViewExtensions.UpdateIsEnabled` to branch between UIControl and non-UIControl views. For UIControl, the native Enabled property is applied to block interactions and provide visual feedback. For non-UIControl views such as `UICollectionView`, `UserInteractionEnabled` is set to disable touch input while preserving visual appearance. **Android** Enhanced `MauiRecyclerView` with touch event overrides to handle the disabled state. `OnInterceptTouchEvent` returns true when the CollectionView is disabled, blocking child interactions. `OnTouchEvent` returns false to prevent `RecyclerView` itself from processing gestures. Both methods check `ItemsView?.IsEnabled` to ensure correct state handling. ### Issues Fixed Fixes #19771 Tested the behaviour in the following platforms - [x] Android - [x] Windows - [x] iOS - [x] Mac ### Output Video Before Issue Fix | After Issue Fix | |----------|----------| |<video width="40" height="60" alt="Before Fix" src="https://github.com/user-attachments/assets/2bab10f4-f614-4457-a97b-193e1abab866">|<video width="50" height="40" alt="After Fix" src="https://github.com/user-attachments/assets/ed8e29f2-5bd6-4365-a928-cfca67a4ae6e">|
…form (#33647) <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Description On DeveloperBalance , unable to open task using keyboard navigation on windows platform ### RootCause On DeveloperBalance ,TaskList is displayed using VerticalStackLayout with BindableLayout, creates layout elements, which are not focusable. On Windows, keyboard navigation works automatically only for controls, so individual items cannot receive keyboard focus. ### Description of Change - Replaced VerticalStackLayout with CollectionView, with navigation now handled through the SelectionChanged event - The previous implementation used SfEffectsView, which was intercepting touch interactions on macOS and preventing item selection. Since the highlight effect on interaction is now managed through CollectionView selection highlight ### Issues Fixed Fixes #30787 ### Tested the behaviour on the following platforms - [x] Android - [x] Windows - [x] iOS - [x] Mac ### Output Screenshot Before Issue Fix | After Issue Fix | |----------|----------| |<video width="300" height="150" alt="Before Fix" src="https://github.com/user-attachments/assets/a248fc9a-5cbd-4360-9942-8d1824f60d1a">|<video width="300" height="150" alt="After Fix" src="https://github.com/user-attachments/assets/15328185-d877-44f0-8e1c-18840a9103d2">|
<!-- 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. !!!!!!! --> ### Description of Change <!-- Enter description of the fix in this section --> This pull request introduces a new Material3-based time picker for Android and updates the handler registration and platform-specific extensions to support it. The main goal is to enable the use of `TimePickerHandler2` and `MauiMaterialTimePicker` when Material3 is enabled, while maintaining compatibility with the existing time picker otherwise. ### Material3 Time Picker Integration * Added new `TimePickerHandler2` class for Android, implementing a Material3-style time picker dialog, with custom mapping and event handling for properties such as time, format, background, and open/close state. (`src/Core/src/Handlers/TimePicker/TimePickerHandler2.Android.cs`) * Introduced `MauiMaterialTimePicker` control for Android, which wraps the Material3 time picker UI and exposes methods for showing/hiding the picker and updating its appearance. (`src/Core/src/Platform/Android/MauiMaterialTimePicker.cs`) ### Handler Registration Updates * Modified `AddControlsHandlers` method to register `TimePickerHandler2` for Android when Material3 is enabled, and fall back to the original handler otherwise. (`src/Controls/src/Core/Hosting/AppHostBuilderExtensions.cs`) [[1]](diffhunk://#diff-66e353858f3298f672f1eb103758a50e379019a1d8efe1b845de3779e7323b8bR72-R83) [[2]](diffhunk://#diff-66e353858f3298f672f1eb103758a50e379019a1d8efe1b845de3779e7323b8bL90) ### Platform Extension Methods * Added extension methods for updating format, time, and text color for `MauiMaterialTimePicker`, mirroring existing methods for the legacy time picker, and ensuring correct formatting and appearance. (`src/Core/src/Platform/Android/TimePickerExtensions.cs`) Material Design Spec - [TimePicker](https://m3.material.io/components/time-pickers/specs) ### 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 #33645 ### Output | Material 2 |Material 3 | |----------|----------| | <img src="https://github.com/user-attachments/assets/13cf453c-93e4-4009-a465-9ed9975d9d18"> | <img src="https://github.com/user-attachments/assets/577cd1d1-79fe-4348-856e-8658ea969fd9"> | <!-- 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! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details After PR #29234 , the else part was removed to stop the Navigated event from triggering when the WebView had no source. However, this caused a new issue where rendering a WebView without a source exceeded the layout bounds. ### Root Cause When the WebView was rendered without a source, the layout logic was not properly handled — causing the WebView to exceed its layout bounds. ### Description of Change <!-- Enter description of the fix in this section --> * Reintroduced the else part. * Added a check to skip the Navigated event when the source is the default (empty). This fix resolves both the layout overflow and unwanted event trigger issues. ### 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 #32030 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> **Tested the behavior in the following platforms.** - [x] Android - [x] Windows - [x] iOS - [x] Mac | Before | After | |---------|--------| | **Android**<br> <img src="https://github.com/user-attachments/assets/a86dcf12-05e0-4cb7-8261-c00d93036cbe" width="300" height="600"> | **Android**<br> <img src="https://github.com/user-attachments/assets/b924c532-d514-495e-bd04-ed6720113c82" width="300" height="600"> |
…troller (#34250) ### Description of Change On iOS, `CompletedHandler` was being invoked **before** `DismissViewController` had finished animating. This means any code running in the handler — such as showing an alert, opening a modal, or triggering navigation — would fire while the picker view controller was still visible and attached to the view hierarchy. iOS UIKit requires the presenting view controller to be fully visible and attached before presenting any new UI (alerts, modals, sheets). If you attempt to present something while a dismiss animation is still in progress, UIKit silently drops the presentation or throws a warning, resulting in: - `DisplayAlert` / `DisplayActionSheet` not appearing after picking an image - Custom modal dialogs not showing up - Any `await`-based UI call after `PickPhotoAsync` / `PickVideoAsync` silently failing on iOS, while working fine on Android The root cause is that `DismissViewController(animated:completion:)` accepts a completion callback precisely for this purpose — to run logic **after** the animation finishes — but the original code passed `null` and called the handler immediately after, creating a race condition. **Fix:** Moved all `CompletedHandler` invocations into the `completion` callback of `DismissViewController` across three call sites: - `UIImagePickerControllerDelegate.FinishedPickingMedia` - `UIImagePickerControllerDelegate.Canceled` - `PHPickerViewControllerDelegate.DidFinishPicking` ### Issues Fixed Fixes #21996 ### Testing Tested on a physical iOS device. - Opened image picker via `MediaPicker.PickPhotoAsync()` - After selecting an image, called `DisplayAlert` in the continuation - **Before fix:** alert did not appear after dismissing the picker - **After fix:** alert appears correctly after the picker is fully dismissed
…ally (#33687) <!-- 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 - Android DatePicker minimum/maximum date constraints don't update properly when changed dynamically. In a dependent DatePicker scenario (LEFT picker's date sets RIGHT picker's minimum), the RIGHT picker fails to respect the updated minimum date constraint. **Behavior:** - **First time** setting `MinimumDate`/`MaximumDate` → Works correctly - **Second time (or subsequent times)** setting `MinimumDate`/`MaximumDate` → Fails to update ### Root Cause of the issue - Android's DatePicker internally caches MinDate/MaxDate values and ignores subsequent setMinDate()/setMaxDate() calls unless the values are first reset. ### Description of Change **Android DatePicker Constraint Fixes:** * Added logic in `DatePickerHandler.Android.cs` to force dialog recreation when `MinimumDate` or `MaximumDate` are updated, ensuring Android's internal cache is invalidated and constraints are reapplied. * Updated `ShowPickerDialog` in `DatePickerHandler.Android.cs` to always apply minimum and maximum date constraints to newly created dialogs. * Introduced a `ResetDialog` method to safely dismiss and recreate the dialog when constraint properties change. **UI Tests for Regression Verification:** * Added `Issue19256` UI test page and NUnit test to verify dynamic updates to minimum date constraints in dependent DatePickers. * Added `Issue33583` UI test page and NUnit test to verify updates to maximum date constraints after dialog is shown. These changes ensure that Android DatePicker controls now correctly honor updated minimum and maximum date values, with comprehensive tests confirming the fix. ### 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 #19256 Fixes #33583 ### Output | Before | After | |----------|----------| | <video src="https://github.com/user-attachments/assets/84c845ed-6825-4737-90c7-f3edd79adf6e"> | <video src="https://github.com/user-attachments/assets/93c023f5-931d-477b-a95c-852f1c9f0751"> | <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. -->
### Description of Change The crash in #32194 occurs because `WindowRootView.UpdateTitleBarContentSize()` is called after the title bar window is already detached, but the `AppWindowId` property is still set. the fix is to reset the `AppWindowId` when the root view is cleared. ### Issues Fixed Fixes #32194
<!-- 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. !!!!!!! --> ## Description of Change This pull request adds support for Material 3 styling for the Button control on Android in .NET MAUI. It introduces runtime feature toggling for Material 3, configures the necessary Android resources and theming infrastructure, and applies Material 3 styling to Button controls. ### Material 3 Button support and theming: - **Added `MauiMaterialButton` style**, which extends `Widget.Material3.Button` and applies Material 3 design to MAUI buttons. This style removes Android Material 3 default constraints (minWidth, minHeight, padding, insets) to allow full MAUI control over button sizing and layout, and sets `iconSize` to 0dp for proper icon sizing.[[1]](diffhunk://#diff-ad5ac218072f5fc910079c411a1cb0a014f67083b7bcbbfd3e8fd041f4a1588eR39-R55) - **Integrated `MauiMaterialButton` into Material 3 base theme** by setting `materialButtonStyle` attribute to reference the custom button style, ensuring all buttons automatically receive Material 3 styling when the feature is enabled. [[1]](diffhunk://#diff-ad5ac218072f5fc910079c411a1cb0a014f67083b7bcbbfd3e8fd041f4a1588eR8) Fixes #33172 ### Screenshots Material Design Spec - [Button](https://m3.material.io/components/buttons/specs) | Material 2 | Material 3 | |---------|--------| | <img height=600 width=300 src="https://github.com/user-attachments/assets/dd767cb0-2672-4514-bdb6-7b2cb8582e14"> | <img height=600 width=300 src="https://github.com/user-attachments/assets/92e69117-fc8b-4942-898b-aa129bead4dc"> |
### Description of Change This pull request introduces support for Material Design 3 radio buttons on Android, making the radio button UI consistent with the latest Material guidelines when the Material3 feature is enabled. The changes ensure that the appropriate handler is used depending on the runtime feature flag. **Android Material Design 3 support:** * Conditional registration of radio button handlers in `AppHostBuilderExtensions.cs`, using `MaterialRadioButtonHandler` when Material3 is enabled, and falling back to the default `RadioButtonHandler` otherwise. * Removal of the unconditional registration of the default `RadioButtonHandler` to prevent duplicate handler assignments. **Handler implementation:** * Addition of the new `MaterialRadioButtonHandler` class in `RadioButtonHandler.Android.cs`, which creates a `MaterialRadioButton` platform view with the correct theme wrapper and disables sound effects for consistency. Material Design Spec : [RadioButton](https://m3.material.io/components/radio-button/specs) ### Issues Fixed Fixes #33467 ### Output | Material2 | Material3 | |----------|----------| | <img src="https://github.com/user-attachments/assets/a8235fae-c86f-4637-ad9b-e3a802d2ddd1"> | <img src="https://github.com/user-attachments/assets/2b9352f5-bd27-423f-a320-40d0eefceb0d"> | --------- Co-authored-by: Gerald Versluis <gerald.versluis@microsoft.com>
### Description of Change - This pull request introduces a new Material 3-specific handler for the `Picker` control on Android, enabling improved theming and dialog behavior when Material 3 is enabled. The changes are structured to ensure backward compatibility and to keep the new implementation internal until .NET 11. **Key changes:** **Material 3 Picker Handler Implementation:** - Added a new internal class `PickerHandler2` for Android, which uses a custom `MauiMaterialPicker` control and provides Material 3 dialog styling and behavior for the `Picker` control. This handler manages dialog creation, item selection, and property mapping for Material 3 pickers. - Introduced MauiMaterialPicker and MauiMaterialPickerBase classes, which extend TextInputEditText and provide the Material 3 look and feel for the picker input field. These classes implement proper Material 3 theming through MauiMaterialContextThemeWrapper, disable text cursor movement and selection to maintain picker behavior, and ensure visual consistency with Material 3 design guidelines. **Handler Registration Logic:** - Updated `AppHostBuilderExtensions.cs` to register `PickerHandler2` instead of the default `PickerHandler` when Material 3 is enabled on Android. The registration logic ensures the correct handler is used based on the runtime feature flag. **Platform-Specific Extensions:** - Added new extension methods in `PickerExtensions.cs` for `MauiMaterialPicker`, including methods to update the title, title color, selected index, and picker items, as well as to propagate flow direction to dialogs. These are internal and marked for future public release with .NET 11. ### Issues Fixed Fixes #33665 ### Output | Material2 | Material3 | |----------|----------| | <img src="https://github.com/user-attachments/assets/98f1b6f2-6d3e-4780-8945-ee1989d33cf2"> | <img src="https://github.com/user-attachments/assets/e2e299cb-4c84-47c1-9208-7a08a4eb2d52"> | --------- Co-authored-by: Gerald Versluis <gerald.versluis@microsoft.com>
### Description of Change - This PR introduces Material Design 3 support for the Editor control on Android. ### New classes (internal, TODO: make public in .NET 11): - EditorHandler2 (EditorHandler2.Android.cs): A new handler extending ViewHandler<IEditor, MauiMaterialEditText> that wraps MauiMaterialEditText (a TextInputEditText-based view) instead of the standard AppCompatEditText. - Implements full property/command mapper parity with EditorHandler, including DataFlowDirection tracking to distinguish platform-initiated vs MAUI-initiated text updates. Subscribes to TextChanged, FocusChange, and SelectionChanged events; calls VirtualView.Completed() on focus loss; syncs CursorPosition/SelectionLength on selection changes. Overrides PlatformArrange with PrepareForTextViewArrange. - MauiMaterialEditText (MauiMaterialEditText.cs): Extends TextInputEditText (from the Material library) to expose a SelectionChanged event via override of OnSelectionChanged, enabling cursor/selection position tracking by the handler. Wraps the context with MauiMaterialContextThemeWrapper to apply the Material 3 theme. ### Handler registration (AppHostBuilderExtensions.cs): - On Android, when RuntimeFeature.IsMaterial3Enabled is true, EditorHandler2 is registered for Editor; otherwise the standard EditorHandler is used. - On all other platforms, the standard EditorHandler is used (unchanged). ### Mapper setup (Editor.Mapper.cs, Editor.Android.cs): - When Material 3 is enabled on Android, additional mappings are registered on EditorHandler2.Mapper and EditorHandler2.CommandMapper: - ReplaceMapping for Text and TextTransform → platform-overloaded MapText (handles DataFlowDirection) - AppendToMapping for IsFocused → InputView.MapIsFocused - PrependToMapping for Focus → InputView.MapFocus ### Issues Fixed Fixes #33476 ### Output | Material2 | Material3 | |----------|----------| | <img src="https://github.com/user-attachments/assets/7d97f447-4228-4df8-b63d-8a8b96823734"> | <img src="https://github.com/user-attachments/assets/1798d8bb-2f5a-40bd-97c8-cf9396d34d59"> | --------- Co-authored-by: Gerald Versluis <gerald.versluis@microsoft.com>
### Description of Change - This pull request introduces support for Material3 styling for `Label` controls on Android by conditionally using a new handler and platform view. The changes ensure that when Material3 is enabled, a new `LabelHandler2` and `MauiMaterialTextView` are used, which properly handle formatted text and layout events. The update also improves event management in the `Label` control. **Material3 support for Label on Android:** * Added conditional logic in `AppHostBuilderExtensions.cs` to use `LabelHandler2` with `MauiMaterialTextView` when Material3 is enabled on Android; otherwise, the default handler is used. * Introduced the internal `LabelHandler2` class, which overrides `CreatePlatformView` to return a `MauiMaterialTextView`. * Added the new internal `MauiMaterialTextView` class, which extends `MaterialTextView` and optimizes layout event handling for formatted text. **Label control event management improvements:** * Updated `Label.Android.cs` to properly attach and detach `LayoutChanged` event handlers for both `MauiTextView` and `MauiMaterialTextView`, preventing memory leaks and ensuring correct event handling. * Improved null-checking and early returns in the `OnLayoutChanged` method for robustness. **Preparatory/cleanup changes:** * Removed the `[ElementHandler<LabelHandler>]` attribute from the Label class and replaced it with conditional dependency injection registration. This change was necessary because the static attribute approach cannot support runtime handler selection based on feature flags. ### Issues Fixed Fixes #33598 ### Output | Material2 | Material3 | |----------|----------| | <img src="https://github.com/user-attachments/assets/0a5ee29f-ab99-4ea2-b035-351d9a6c409a"> | <img src="https://github.com/user-attachments/assets/40a6a2a8-3ad1-42a2-913d-17aef86bd624"> | --------- Co-authored-by: Gerald Versluis <gerald.versluis@microsoft.com> Co-authored-by: Gerald Versluis <gerald@verslu.is>
### Description of Change Backgrounds are everywhere in our apps, so we must be fast when drawing android views, and `Java -> C#` is not. This PR tries to do its best to completely move the logic into a java `PlatformDrawable` class. ### Benchmarks (~50% improvements in mapping, ~60% improvement in rendering time) I used #24414 as main page wrapped into a `Shell` component given it has a `drawChild` method which shows the cumulative draw time. The results are impressive and will for sure make an impact! [24414-net10.json](https://github.com/user-attachments/files/22296183/24414-net10.json) <img width="754" height="144" alt="image" src="https://github.com/user-attachments/assets/834b59e0-77f9-457c-9867-179b91f116d0" /> <img width="749" height="46" alt="image" src="https://github.com/user-attachments/assets/5ecf5252-10c8-42e8-85f0-b94dfd60746b" /> <img width="752" height="124" alt="image" src="https://github.com/user-attachments/assets/04d78a16-f22d-4ff1-ab5f-b34316c7240a" /> [24414-pr-final2.json](https://github.com/user-attachments/files/22403331/24414-pr-final2.json) <img width="1106" height="122" alt="image" src="https://github.com/user-attachments/assets/bc59bef4-9e2f-4626-b399-7ab0b3b44cd0" /> <img width="918" height="104" alt="image" src="https://github.com/user-attachments/assets/caca6cba-69c4-4949-b7df-cac5ceccb6d9" /> <img width="903" height="123" alt="image" src="https://github.com/user-attachments/assets/2b6e9b52-c347-43d8-abec-061263739724" /> --------- Co-authored-by: Shane Neuville <shneuvil@microsoft.com> Co-authored-by: Gerald Versluis <gerald.versluis@microsoft.com>
…urce While Scrolled (#34153) > [!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 The offsets (VerticalOffset and HorizontalOffset) were being calculated incrementally and did not reset properly when the ItemsSource changed, leading to incorrect offset values. ### Description of Change <!-- Enter description of the fix in this section --> The change resets the VerticalOffset and HorizontalOffset to 0 when the ItemsSource is updated. This ensures correct offset values after adding or removing items, fixing the issue of incorrect offsets while scrolling. ### Regarding test case The test case was added in PR #26782 , so this PR includes only the iOS fix. ### 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 #26798 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> --------- Co-authored-by: Jakub Florkowski <kubaflo123@gmail.com>
… - 1 (#34334) This PR addresses the UI test image failures that occurred in the inflight/candidate branch #34294 and includes updates to improve rendering and test stability across platforms. ### Controls Handler Registration * Simplified the logic for registering handlers for controls like `Label`, `Editor`, `Picker`, `RadioButton`, and `TimePicker` in `AppHostBuilderExtensions.cs`. The new approach registers all fallback handlers together, reducing duplicated code and improving maintainability. ### * In the NavigationRootManager class, the line _rootView.SetTitleBar(null, null); was added in this PR #34032 by a contributor due to an AI minor suggestion, but this line causes an issue when swapping pages, so the TitlebarWorksWhenSwitchingPage test fails. Setting SetTitleBar to null is already implemented in the WindowHandler class in the [DisconnectHandler](https://github.com/dotnet/maui/blob/main/src/Core/src/Handlers/Window/WindowHandler.Windows.cs#L55) method, so I have removed this line _rootView.SetTitleBar(null, null); from the PR [34032](#34032). ### Image Resave: * Resaved images: DownSizeImageAppearProperly, Material3CheckBoxFeatureTests, Material3CheckBox_DefaultAppearance, DownSizeImageAppearProperly, VerifyLinearGradientBrushWithStrokeAndOpacity, VerifyRadialGradientBrushWithOpacity, VerifyRadialGradientBrushWithShadowAndOpacity, VerifyLinearGradientBrushWithOpacity, VerifyLinearGradientBrushWithShadowAndOpacity, DarkTheme_VerifyVisualState. These PR fixes address the issues: #33173, #31567, #33590, #34036 * Added the base images for iOS 26, Mac, and Windows. ### Test Stability and Platform-Specific Handling * Added a platform-specific ignore for a Shell flyout test on iOS 26 due to a known bug, improving test reliability and clarity about platform limitations. * Updated a CollectionView scroll test to wait for specific elements on Windows, ensuring the test works correctly across platforms. ### DatePicker Handler Tests * Introduced a helper method `EnsureDialogCreated` in `DatePickerHandlerTests.Android.cs` to reliably create the native dialog before reading min/max values, addressing issues caused by lazy dialog creation after a recent PR. This helper is now used in relevant tests to improve robustness. [[1]](diffhunk://#diff-de28fdea458f311cfcc7e767c7e9e2a4c7c36e4d065ae2ebf2a25b420f183c29R26) [[2]](diffhunk://#diff-de28fdea458f311cfcc7e767c7e9e2a4c7c36e4d065ae2ebf2a25b420f183c29R54) [[3]](diffhunk://#diff-de28fdea458f311cfcc7e767c7e9e2a4c7c36e4d065ae2ebf2a25b420f183c29R131-R146) * Clarified the DatePicker test logic in `DatePickerTests.cs` to ensure the `DateSelected` event fires correctly regardless of dialog state, improving test reliability on Android. ### Test Case Organization * Removed the obsolete `VerifyFlyoutPage_IsEnabled` test and renumbered the remaining FlyoutPage tests in `FlyoutPageFeatureTests.cs` to maintain sequential order and consistency. [[1]](diffhunk://#diff-a20c8165e92130c8ebbda3af607c3dd309cf1c1b6c85942abd6ed81132510fb3L176-R177) [[2]](diffhunk://#diff-a20c8165e92130c8ebbda3af607c3dd309cf1c1b6c85942abd6ed81132510fb3L204-R191) [[3]](diffhunk://#diff-a20c8165e92130c8ebbda3af607c3dd309cf1c1b6c85942abd6ed81132510fb3L222-R209) [[4]](diffhunk://#diff-a20c8165e92130c8ebbda3af607c3dd309cf1c1b6c85942abd6ed81132510fb3L240-R227) [[5]](diffhunk://#diff-a20c8165e92130c8ebbda3af607c3dd309cf1c1b6c85942abd6ed81132510fb3L254-R241) [[6]](diffhunk://#diff-a20c8165e92130c8ebbda3af607c3dd309cf1c1b6c85942abd6ed81132510fb3L268-R255) [[7]](diffhunk://#diff-a20c8165e92130c8ebbda3af607c3dd309cf1c1b6c85942abd6ed81132510fb3L284-R271) [[8]](diffhunk://#diff-a20c8165e92130c8ebbda3af607c3dd309cf1c1b6c85942abd6ed81132510fb3L299-R286) [[9]](diffhunk://#diff-a20c8165e92130c8ebbda3af607c3dd309cf1c1b6c85942abd6ed81132510fb3L310-R297) [[10]](diffhunk://#diff-a20c8165e92130c8ebbda3af607c3dd309cf1c1b6c85942abd6ed81132510fb3L327-R314) [[11]](diffhunk://#diff-a20c8165e92130c8ebbda3af607c3dd309cf1c1b6c85942abd6ed81132510fb3L340-R327) [[12]](diffhunk://#diff-a20c8165e92130c8ebbda3af607c3dd309cf1c1b6c85942abd6ed81132510fb3L357-R344) [[13]](diffhunk://#diff-a20c8165e92130c8ebbda3af607c3dd309cf1c1b6c85942abd6ed81132510fb3L376-R363) [[14]](diffhunk://#diff-a20c8165e92130c8ebbda3af607c3dd309cf1c1b6c85942abd6ed81132510fb3L387-R374) [[15]](diffhunk://#diff-a20c8165e92130c8ebbda3af607c3dd309cf1c1b6c85942abd6ed81132510fb3L400-R387)
3d28b2d to
2c73f63
Compare
|
/azp run maui-pr-uitests , maui-pr-devicetests |
|
Azure Pipelines successfully started running 2 pipeline(s). |
What's Coming
.NET MAUI inflight/candidate introduces significant improvements across all platforms with focus on quality, performance, and developer experience. This release includes 46 commits with various improvements, bug fixes, and enhancements.
Button
[Android] Implemented material3 support for Button by @Dhivya-SF4094 in [Android] Implemented material3 support for Button #33173
🔧 Fixes
CollectionView
[Android] Fix RemainingItemsThresholdReachedCommand not firing when CollectionView has Header and Footer both defined by @SuthiYuvaraj in [Android] Fix RemainingItemsThresholdReachedCommand not firing when CollectionView has Header and Footer both defined #29618
🔧 Fixes
[iOS/MacCatalyst] Fix CollectionView ScrollTo for horizontal layouts by @Shalini-Ashokan in [iOS/MacCatalyst] Fix CollectionView ScrollTo for horizontal layouts #33853
🔧 Fixes
[iOS & Mac] Fixed IndicatorView Size doesnt update dynamically by @SubhikshaSf4851 in [iOS & Mac] Fixed IndicatorView Size doesnt update dynamically #31129
🔧 Fixes
[Android] Fix for CollectionView Scrolled event is triggered on the initial app load. by @BagavathiPerumal in [Android] Fix for CollectionView Scrolled event is triggered on the initial app load. #33558
🔧 Fixes
[iOS, Android] Fix for CollectionView IsEnabled=false allows touch interactions by @praveenkumarkarunanithi in [iOS, Android] Fix for CollectionView IsEnabled=false allows touch interactions #31403
🔧 Fixes
[iOS] Fix VerticalOffset Update When Modifying CollectionView.ItemsSource While Scrolled by @devanathan-vaithiyanathan in [iOS] Fix VerticalOffset Update When Modifying CollectionView.ItemsSource While Scrolled #34153
🔧 Fixes
DateTimePicker
[Android] Fix DatePicker MinimumDate/MaximumDate not updating dynamically by @HarishwaranVijayakumar in [Android] Fix DatePicker MinimumDate/MaximumDate not updating dynamically #33687
🔧 Fixes
Drawing
Editor
[Android] Implemented material3 support for Editor by @SyedAbdulAzeemSF4852 in [Android] Implemented material3 support for Editor #33478
🔧 Fixes
Entry
[iOS, Mac] Fix for CursorPosition not updating when typing into Entry control by @SyedAbdulAzeemSF4852 in [iOS, Mac] Fix for CursorPosition not updating when typing into Entry control #30505
🔧 Fixes
Flyoutpage
[Android, Windows] Fix for FlyoutPage toolbar button not updating on orientation change by @praveenkumarkarunanithi in [Android, Windows] Fix for FlyoutPage toolbar button not updating on orientation change #31962
🔧 Fixes
Fix for First Item in CollectionView Overlaps in FlyoutPage.Flyout on iOS by @praveenkumarkarunanithi in Fix for First Item in CollectionView Overlaps in FlyoutPage.Flyout on iOS #29265
🔧 Fixes
Image
[Android] Fix excessive memory usage for stream and resource-based image loading by @Shalini-Ashokan in [Android] Fix excessive memory usage for stream and resource-based image loading #33590
🔧 Fixes
[Android] Fix for Resize method returns an image that has already been disposed by @SyedAbdulAzeemSF4852 in [Android] Fix for Resize method returns an image that has already been disposed #29964
🔧 Fixes
Label
🔧 Fixes
Spandoes not inherit text styling fromLabelif that styling is applied usingStyle[Android] Implemented material3 support for Label by @SyedAbdulAzeemSF4852 in [Android] Implemented material3 support for Label #33599
🔧 Fixes
Map
[Android] Fix Circle Stroke color is incorrectly updated as Fill color. by @NirmalKumarYuvaraj in [Android] Fix Circle Stroke color is incorrectly updated as Fill color. #33643
🔧 Fixes
Mediapicker
[iOS] Fix: invoke MediaPicker completion handler after DismissViewController by @yuriikyry4enko in [iOS] Fix: invoke MediaPicker completion handler after DismissViewController #34250
🔧 Fixes
Navigation
Fix ContentPage memory leak on Android when using NavigationPage modally (fixes [Android] Modal TabbedPage whose tabs are NavigationPage(ContentPage) is retained after PopModalAsync() #33918) by @brunck in Fix ContentPage memory leak on Android when using NavigationPage modally (fixes #33918) #34117
🔧 Fixes
Picker
[Android] Implement material3 support for TimePicker by @HarishwaranVijayakumar in [Android] Implement material3 support for TimePicker #33646
🔧 Fixes
[Android] Implemented Material3 support for Picker by @SyedAbdulAzeemSF4852 in [Android] Implemented Material3 support for Picker #33668
🔧 Fixes
RadioButton
[Android] Implemented material3 support for RadioButton by @SyedAbdulAzeemSF4852 in [Android] Implemented material3 support for RadioButton #33468
🔧 Fixes
Setup
Clarify MA003 error message by @jeremy-visionaid in Clarify MA003 error message #34067
🔧 Fixes
Shell
[Android] Fix TabBar FlowDirection not updating dynamically by @SubhikshaSf4851 in [Android] Fix TabBar FlowDirection not updating dynamically #33091
🔧 Fixes
[Android] Fix page not disposed on Shell replace navigation by @Vignesh-SF3580 in [Android] Fix page not disposed on Shell replace navigation #33426
🔧 Fixes
[Android] Fixed Shell flyout does not disable scrolling when FlyoutVerticalScrollMode is set to Disabled by @NanthiniMahalingam in [Android] Fixed Shell flyout does not disable scrolling when FlyoutVerticalScrollMode is set to Disabled #32734
🔧 Fixes
Single Project
Fix: Throw a clear error when an SVG lacks dimensions instead of a NullReferenceException by @Shalini-Ashokan in Fix: Throw a clear error when an SVG lacks dimensions instead of a NullReferenceException #33194
🔧 Fixes
SwipeView
[iOS] Fix SwipeView stays open on iOS after updating content by @devanathan-vaithiyanathan in [iOS] Fix SwipeView stays open on iOS after updating content #31248
🔧 Fixes
TabbedPage
[Windows] Fixed IsEnabled Property not works on Tabs by @NirmalKumarYuvaraj in [Windows] Fixed IsEnabled Property not works on Tabs #26728
🔧 Fixes
[Android] Fix NavigationBar overlapping StatusBar when NavigationBar visibility changes by @Vignesh-SF3580 in [Android] Fix NavigationBar overlapping StatusBar when NavigationBar visibility changes #33359
🔧 Fixes
Templates
Fix for unable to open task using keyboard navigation on windows platform by @SuthiYuvaraj in Fix for unable to open task using keyboard navigation on windows platform #33647
🔧 Fixes
TitleView
Toolbar
[iOS] Fix toolbar items ignoring BarTextColor on iOS/MacCatalyst 26+ by @Shalini-Ashokan in [iOS] Fix toolbar items ignoring BarTextColor on iOS/MacCatalyst 26+ #34036
🔧 Fixes
[Android] Fix for ToolbarItem retaining the icon from the previous page on Android when using NavigationPage. by @BagavathiPerumal in [Android] Fix for ToolbarItem retaining the icon from the previous page on Android when using NavigationPage. #32311
🔧 Fixes
WebView
[Android] Fix WebView in a grid expands beyond it's cell by @devanathan-vaithiyanathan in [Android] Fix WebView in a grid expands beyond it's cell #32145
🔧 Fixes
Xaml
ContentPresenter: Propagate binding context to children with explicit TemplateBinding by @HarishwaranVijayakumar in ContentPresenter: Propagate binding context to children with explicit TemplateBinding #30880
🔧 Fixes
🔧 Infrastructure (1)
🧪 Testing (6)
[Testing] Feature Matrix UITest Cases for Shell Flyout Page by @NafeelaNazhir in [Testing] Feature Matrix UITest Cases for Shell Flyout Page #32525
[Testing] Feature Matrix UITest Cases for Brushes by @LogishaSelvarajSF4525 in [Testing] Feature Matrix UITest Cases for Brushes #31833
[Testing] Feature Matrix UITest Cases for BindableLayout by @LogishaSelvarajSF4525 in [Testing] Feature Matrix UITest Cases for BindableLayout #33108
[Android] Add UI tests for Material 3 CheckBox by @HarishwaranVijayakumar in [Android] Add UI tests for Material 3 CheckBox #34126
🔧 Fixes
[Testing] Feature Matrix UITest Cases for Shell Tabbed Page by @NafeelaNazhir in [Testing] Feature Matrix UITest Cases for Shell Tabbed Page #33159
[Testing] Fixed Test case failure in PR 34294 - [03/2/2026] Candidate - 1 by @TamilarasanSF4853 in [Testing] Fixed Test case failure in PR 34294 - [03/2/2026] Candidate - 1 #34334
📦 Other (2)
Bumps Syncfusion.Maui.Toolkit dependency to version 1.0.9 by @PaulAndersonS in Bumps Syncfusion.Maui.Toolkit dependency to version 1.0.9 #34178
Fix crash when closing Windows based app when using TitleBar by @MFinkBK in Fix crash when closing Windows based app when using TitleBar #34032
🔧 Fixes