Skip to content

March 30th, Inflight Candidate#34617

Open
PureWeen wants to merge 193 commits intomainfrom
inflight/candidate
Open

March 30th, Inflight Candidate#34617
PureWeen wants to merge 193 commits intomainfrom
inflight/candidate

Conversation

@PureWeen
Copy link
Copy Markdown
Member

@PureWeen PureWeen commented Mar 24, 2026

What's Coming

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

Blazor

Border

Button

CollectionView

🔧 Fixes

DateTimePicker

Dialogalert

Drawing

Entry

Essentials

Flyout

Flyoutpage

Fonts

Gestures

Image

Label

Layout

Map

Mediapicker

Navigation

Picker

Progressbar

RadioButton

ScrollView

Searchbar

SearchBar

Shell

🔧 Fixes

Slider

Stepper

SwipeView

Switch

TabbedPage

Theming

Titlebar

Toolbar

Window

Xaml

🔧 Infrastructure (1)
🧪 Testing (19)
🏠 Housekeeping (1)
📦 Other (7)
📝 Issue References

Fixes #6972, Fixes #8422, Fixes #10107, Fixes #10509, Fixes #11113, Fixes #11677, Fixes #11808, Fixes #11812, Fixes #12131, Fixes #12324, Fixes #14566, Fixes #15057, Fixes #15280, Fixes #15559, Fixes #16522, Fixes #17127, Fixes #17323, Fixes #17550, Fixes #17664, Fixes #17864, Fixes #18367, Fixes #18481, Fixes #18669, Fixes #18679, Fixes #18843, Fixes #18933, Fixes #19074, Fixes #19219, Fixes #19331, Fixes #19642, Fixes #20383, Fixes #20392, Fixes #20596, Fixes #20682, Fixes #20855, Fixes #20922, Fixes #21037, Fixes #21240, Fixes #21646, Fixes #21700, Fixes #21791, Fixes #21828, Fixes #22060, Fixes #22565, Fixes #22887, Fixes #23030, Fixes #23832, Fixes #23903, Fixes #24241, Fixes #24252, Fixes #24511, Fixes #24603, Fixes #24866, Fixes #25010, Fixes #25081, Fixes #25093, Fixes #25728, Fixes #25920, Fixes #25921, Fixes #26158, Fixes #26633, Fixes #26864, Fixes #26975, Fixes #27143, Fixes #27250, Fixes #27302, Fixes #27427, Fixes #27646, Fixes #27846, Fixes #28078, Fixes #28101, Fixes #28147, Fixes #28421, Fixes #28722, Fixes #28824, Fixes #28901, Fixes #28961, Fixes #29191, Fixes #29192, Fixes #29415, Fixes #29428, Fixes #29484, Fixes #29547, Fixes #29645, Fixes #29704, Fixes #29729, Fixes #29764, Fixes #29812, Fixes #29930, Fixes #30004, Fixes #30066, Fixes #30097, Fixes #30181, Fixes #30273, Fixes #30290, Fixes #30605, Fixes #30782, Fixes #30888, Fixes #30979, Fixes #31109, Fixes #31121, Fixes #31140, Fixes #31145, Fixes #31387, Fixes #31551, Fixes #31966, Fixes #32017, Fixes #32243, Fixes #32266, Fixes #32316, Fixes #32406, Fixes #32416, Fixes #32578, Fixes #32791, Fixes #32807, Fixes #32983, Fixes #32989, Fixes #32995, Fixes #33119, Fixes #33131, Fixes #33258, Fixes #33291, Fixes #33293, Fixes #33304, Fixes #33375, Fixes #33415, Fixes #33417, Fixes #33420, Fixes #33424, Fixes #33493, Fixes #33547, Fixes #33577, Fixes #33601, Fixes #33604, Fixes #33614, Fixes #33635, Fixes #33648, Fixes #33650, Fixes #33672, Fixes #33706, Fixes #33769, Fixes #33772, Fixes #33904, Fixes #33909, Fixes #33947, Fixes #33954, Fixes #33964, Fixes #33969, Fixes #33972, Fixes #34021, Fixes #34073, Fixes #34114, Fixes #34119, Fixes #34122, Fixes #34165, Fixes #34210, Fixes #34211, Fixes #34246, Fixes #34257, Fixes #34336, Fixes #34343, Fixes #34419, Fixes #34464, Fixes #34480, Fixes #34591, Fixes #34635, Fixes #34636, Fixes #34661

Full Changelog: main...inflight/candidate

Copilot AI review requested due to automatic review settings March 24, 2026 15:50
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 24, 2026

🚀 Dogfood this PR with:

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

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

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 34617"

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR appears to be an “inflight” collection of fixes/regressions across Controls, XAML parsing/source-gen, Shell navigation/appearance, item handlers (Android/iOS/Windows), Maps, and BlazorWebView packaging/platform attributes, plus associated unit/device tests.

Changes:

  • Tighten/adjust runtime behaviors (e.g., StaticResource exceptions, Shell navigation/query behavior, swipe/pan gesture handling, various handler/layout edge cases).
  • Add/extend tests (Core unit tests + device tests) to cover multiple regressions (Maps, SwipeView, Shell, FlexLayout, etc.).
  • Update platform-specific implementations (Android/iOS/Windows) for visuals, selection/click listeners, measurement invalidation, and platform quirks; plus BlazorWebView single-file bundling + SupportedOSPlatform metadata.

Reviewed changes

Copilot reviewed 124 out of 1440 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
src/Controls/tests/DeviceTests/Xaml/StaticResourceTests.cs Adds device test asserting missing StaticResource throws even with handler present.
src/Controls/tests/DeviceTests/TestCategory.cs Adds Map test category constant.
src/Controls/tests/DeviceTests/Elements/SearchBar/SearchBarTests.cs Adds iOS/MacCatalyst rendering tests for SearchBar Width/HeightRequest.
src/Controls/tests/DeviceTests/Elements/Map/MapTests.cs Adds iOS/MacCatalyst device tests for MapElementId reset behavior.
src/Controls/tests/DeviceTests/Elements/Entry/EntryTests.Android.cs Uses platform helper for selection length + adds RTL selection length regression test.
src/Controls/tests/DeviceTests/Elements/Editor/EditorTests.Android.cs Uses platform helper for selection length + adds RTL selection length regression test.
src/Controls/tests/DeviceTests/Elements/CollectionView/CollectionViewTests.Android.cs Adds tests asserting click listeners follow SelectionMode; adds layout helper.
src/Controls/tests/DeviceTests/ControlsDeviceTestExtensions.cs Registers Maps handlers for device tests (Android/iOS/MacCatalyst).
src/Controls/tests/DeviceTests/Controls.DeviceTests.csproj Adds Maps project references to device tests.
src/Controls/tests/Core.UnitTests/SwipeViewTests.cs Adds unit tests for SwipeView scroll parent discovery behavior.
src/Controls/tests/Core.UnitTests/ShellTests.cs Adds unit test for back navigation default animation behavior.
src/Controls/tests/Core.UnitTests/ShellElementCollectionTests.cs Adds regression tests for flyout observer notifications after dynamic item replacement.
src/Controls/tests/Core.UnitTests/Layouts/FlexLayoutTests.cs Adds multiple FlexLayout regression tests (arrange-only + flex-grow behavior).
src/Controls/tests/Core.UnitTests/Gestures/SwipeGestureRecognizerTests.cs Adds tests for swipe direction rotation transform + invalid rotations.
src/Controls/src/Xaml/XmlTypeXamlExtensions.cs Avoids static *Extension shadowing exact type resolution (#34021).
src/Controls/src/Xaml/MarkupExtensions/StaticResourceExtension.cs Always throws when static resource key missing (even with handler present).
src/Controls/src/Xaml/MarkupExtensions/BindingExtension.cs Avoids DataType assignment for non-relative explicit Source to prevent source-null-out.
src/Controls/src/Xaml/ApplyPropertiesVisitor.cs Ensures StaticResource exceptions are rethrown even when exception handler exists.
src/Controls/src/SourceGen/XmlTypeExtensions.cs Mirrors static *Extension shadowing guard in source-gen type resolution.
src/Controls/src/SourceGen/KnownMarkups.cs Fixes x:DataType resolution logic + reports a more specific diagnostic.
src/Controls/src/Core/Window/Window.cs Triggers SizeChanged when Width/Height bindable properties change (guarded by batch updates).
src/Controls/src/Core/VisualStateManager.cs Adds helper to detect Selected visual state.
src/Controls/src/Core/VisualElement/VisualElement.cs Preserves Selected state when computing visual state (vs forcing Normal/PointerOver).
src/Controls/src/Core/Toolbar/Toolbar.Android.cs Adjusts Android toolbar content insets when TitleView has margins/options set.
src/Controls/src/Core/SwipeView/SwipeView.cs Improves scroll parent discovery for templated scenarios; uses absolute deltas for close-on-scroll.
src/Controls/src/Core/Shell/ShellSection.cs Defaults back navigation animation to true when not specified.
src/Controls/src/Core/Shell/ShellNavigationManager.cs Adjusts query attribute application when popping and merged query is empty.
src/Controls/src/Core/Shell/ShellElementCollection.cs Tracks clear/add cycles to notify flyout observers when count reaches 2 after clear.
src/Controls/src/Core/Shell/ShellContent.cs Moves delayed query param propagation earlier; improves nullable conversion handling.
src/Controls/src/Core/Shell/Shell.cs Propagates NavBarIsVisible changes; adjusts navigating/navigated event timing and defers NavigatedTo until Loaded.
src/Controls/src/Core/Shell/SearchHandler.cs Avoids double query confirmation on WinUI when selecting item.
src/Controls/src/Core/Shell/BaseShellItem.cs Special-cases NavBarIsVisible propagation to read from Shell when appropriate.
src/Controls/src/Core/Shell/BackButtonBehavior.cs Prevents IsEnabledCore from re-enabling when IsEnabled is false.
src/Controls/src/Core/SearchBar/SearchBar.iOS.cs Adds mapping to update native UserInteractionEnabled based on IsEnabled/IsReadOnly/InputTransparent.
src/Controls/src/Core/SearchBar/SearchBar.Mapper.cs Refines SearchBar mapper behavior (iOS user interaction mapping; Android Material3 handler mapping selection).
src/Controls/src/Core/SearchBar/SearchBar.Android.cs Adds Material3 SearchBarHandler2 text mapping overload.
src/Controls/src/Core/RadioButton/RadioButton.Windows.cs Applies TextTransform to RadioButton content on Windows (Lowercase/Uppercase).
src/Controls/src/Core/RadioButton/RadioButton.Mapper.cs Maps TextTransform -> content update for Android/Windows.
src/Controls/src/Core/RadioButton/RadioButton.Android.cs Applies TextTransform to RadioButton text on Android (Lowercase/Uppercase).
src/Controls/src/Core/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt Tracks newly exposed iOS/MacCatalyst API surface changes.
src/Controls/src/Core/PublicAPI/net-ios/PublicAPI.Unshipped.txt Tracks newly exposed iOS API surface changes.
src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt Tracks Android public API changes, incl. ShellRenderer color members update.
src/Controls/src/Core/Platform/iOS/Extensions/FormattedStringExtensions.cs Adds line break + character spacing propagation to spans; validates character spacing.
src/Controls/src/Core/Platform/Windows/Extensions/ToolbarExtensions.cs Disconnects TitleView handler before reusing in Windows toolbar TitleView updates.
src/Controls/src/Core/Platform/Windows/Extensions/FormattedStringExtensions.cs Adds character spacing inheritance/validation into formatted string spans on Windows.
src/Controls/src/Core/Platform/Windows/CollectionView/TemplatedItemSourceFactory.cs Returns empty items when itemsSource is null (Windows CollectionView).
src/Controls/src/Core/Platform/Windows/CollectionView/ObservableItemTemplateCollection.cs Skips group footer contexts when syncing underlying items source.
src/Controls/src/Core/Platform/Windows/CollectionView/ItemContentControl.cs Coalesces measure invalidations on item dimension changes via DispatcherQueue.
src/Controls/src/Core/Platform/Windows/CollectionView/GroupTemplateContext.cs Fixes footer insertion order/logic for group templates.
src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.iOS.cs Transforms swipe direction based on view rotation; changes simultaneous recognition against UIScrollView.
src/Controls/src/Core/Platform/GestureManager/GesturePlatformManager.Windows.cs Uses cumulative translation + marks manipulation events handled; avoids clearing pointer on active gestures.
src/Controls/src/Core/Platform/Android/TabbedPageManager.cs Prevents removing tabs on disappearing; adjusts bottom nav elevation w/ gradient background.
src/Controls/src/Core/Platform/Android/Extensions/ToolbarExtensions.cs Adjusts back button icon behavior and menu item title setting for tooltip color.
src/Controls/src/Core/Platform/Android/Extensions/FormattedStringExtensions.cs Adds character spacing inheritance/validation for Android formatted strings.
src/Controls/src/Core/Platform/Android/Extensions/EditTextExtensions.cs Replaces SetTextKeepState with Editable.Replace for safer programmatic updates + selection clamping.
src/Controls/src/Core/Platform/AlertManager/AlertManager.iOS.cs Avoids using a presented VC that is being dismissed when finding top VC.
src/Controls/src/Core/NavigationPage/NavigationPageToolbar.cs Keeps flyout hamburger accessible when back button is hidden.
src/Controls/src/Core/Layout/FlexLayout.cs Ensures arranged size respects updated Width/HeightRequest during arrange-only passes.
src/Controls/src/Core/Internals/SwipeGestureExtensions.cs Adds helpers to normalize rotation and transform swipe directions.
src/Controls/src/Core/IndicatorView/IndicatorStackLayout.cs Filters indicator items based on MaximumVisible.
src/Controls/src/Core/Hosting/AppHostBuilderExtensions.cs Expands handler registration set; includes Material3 alternatives when enabled.
src/Controls/src/Core/Handlers/Shell/ShellHandler.cs Adds FlyoutVerticalScrollMode mapping (Windows).
src/Controls/src/Core/Handlers/Shell/ShellHandler.Windows.cs Updates FlyoutVerticalScrollMode on loaded (Windows).
src/Controls/src/Core/Handlers/Items2/iOS/ItemsViewDelegator2.cs Corrects visible item ordering for grouped sources and improves first visible index resolution.
src/Controls/src/Core/Handlers/Items2/ItemsViewHandler2.iOS.cs Forces compositional layout pre-mount to compute content size; fixes horizontal auto-height circular sizing.
src/Controls/src/Core/Handlers/Items2/CollectionViewHandler2.iOS.cs Fixes ItemsLayout property change subscription lifecycle + disconnect cleanup.
src/Controls/src/Core/Handlers/Items2/CarouselViewHandler2.iOS.cs Adds IsEnabled mapping to update CollectionView enabled state.
src/Controls/src/Core/Handlers/Items/iOS/ItemsViewDelegator.cs Same visible item ordering/first visible index update for legacy iOS handler path.
src/Controls/src/Core/Handlers/Items/iOS/ItemsViewController.cs Resets contentSize.Height for horizontal layouts when width is 0 to avoid circular sizing.
src/Controls/src/Core/Handlers/Items/StructuredItemsViewHandler.Windows.cs Sets ItemContainerStyle based on orientation for FormsListView.
src/Controls/src/Core/Handlers/Items/StructuredItemsViewHandler.Android.cs Updates adapter/scrolling mode/layout manager when ItemsLayout changes.
src/Controls/src/Core/Handlers/Items/SelectableItemsViewHandler.Android.cs Ensures adapter updates click listeners on selection mode changes.
src/Controls/src/Core/Handlers/Items/ItemsViewHandler.Windows.cs Enqueues vector change handling; disconnects handlers during cleanup.
src/Controls/src/Core/Handlers/Items/CarouselViewHandler.iOS.cs Adds IsEnabled mapping for CarouselView iOS handler path.
src/Controls/src/Core/Handlers/Items/CarouselViewHandler.cs Maps IsEnabled for iOS/MacCatalyst; keeps ItemsLayout mapping for Tizen/Android.
src/Controls/src/Core/Handlers/Items/CarouselViewHandler.Windows.cs Removes explicit ListViewBase.InvalidateMeasure during item size invalidation.
src/Controls/src/Core/Handlers/Items/Android/TemplatedItemViewHolder.cs Recycles and clears disconnected view/template state to force handler recreation on rebind.
src/Controls/src/Core/Handlers/Items/Android/SpacingItemDecoration.cs Removes outer-edge spacing for grid/linear layouts based on span/orientation.
src/Controls/src/Core/Handlers/Items/Android/SelectableViewHolder.cs Adds ability to attach/detach click listeners dynamically based on selection mode.
src/Controls/src/Core/Handlers/Items/Android/RecyclerViewScrollListener.cs Defers RemainingItemsThresholdReached until RecyclerView is idle to avoid scroll-callback modification crash.
src/Controls/src/Core/Handlers/Items/Android/MauiRecyclerView.cs Guards invalid scroll positions; improves empty view recycling; updates spacing/padding behavior for grids.
src/Controls/src/Core/Handlers/Items/Android/MauiCarouselRecyclerView.cs Fixes swipe disabled handling; scrolls to position after items source updates.
src/Controls/src/Core/Handlers/Items/Android/ItemsSources/ObservableGroupedSource.cs Adds bounds check for group index retrieval (returns null + debug log).
src/Controls/src/Core/Handlers/Items/Android/ItemContentView.cs Disconnects handlers during recycle before clearing content; cleans pixel size reset logic.
src/Controls/src/Core/Handlers/Items/Android/Adapters/StructuredItemsViewAdapter.cs Avoids MeasureFirstItem sizing logic on header/footer view types.
src/Controls/src/Core/Handlers/Items/Android/Adapters/SelectableItemsViewAdapter.cs Updates selection mode click listeners; disables selection/clickability for SelectionMode.None (accessibility).
src/Controls/src/Core/Handlers/Items/Android/Adapters/EmptyViewAdapter.cs Ensures template content has handler before measuring header/footer.
src/Controls/src/Core/Handlers/Items/Android/Adapters/CarouselViewAdapter.cs Disables selection on CarouselView adapter.
src/Controls/src/Core/Entry/Entry.Mapper.cs Adds Android Material3 EntryHandler2 mappings.
src/Controls/src/Core/Entry/Entry.Android.cs Adds EntryHandler2 mapping overloads for Material3 (ImeOptions/Text).
src/Controls/src/Core/Compatibility/Handlers/TabbedPage/iOS/TabbedRenderer.cs Updates flow direction handling and listens for FlowDirection changes.
src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellSectionRootRenderer.cs Invalidates header layout on MacCatalyst when header frame changes.
src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellSectionRenderer.cs Adds guards for iOS 26 pop dispatch; respects back button enabled; applies appearance to More controller; new override.
src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellPageRendererTracker.cs Adds keyboard hide observer to fix view mispositioning; adjusts hamburger behavior; disposes observer.
src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellNavBarAppearanceTracker.cs Resets tint to default when user clears ForegroundColor.
src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/ShellItemRenderer.cs Applies disabled state for tabs; sets per-item disabled appearance; updates “More” tab membership after removals.
src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/SearchHandlerAppearanceTracker.cs Fixes background reset/customization logic; removes forced cancel button behavior.
src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/SafeShellTabBarAppearanceTracker.cs Uses foreground/disabled colors for tab appearance; sets disabled title attributes.
src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellToolbarTracker.cs Updates left button when FlyoutIcon/ForegroundColor changes; refines icon visibility cases; clears tint when none set.
src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellToolbarAppearanceTracker.cs Stops forcing tracker TintColor from shell foreground color.
src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellSectionRenderer.cs Stores shell toolbar instance; refreshes TitleView mapping when fragment becomes visible.
src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellRenderer.cs Updates default colors based on Material3 and adjusts theme detection.
src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellPageContainer.cs Uses Material3 surface color as background; refactors resource background selection.
src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellItemRenderer.cs Updates bottom nav background color from appearance; avoids early return during menu setup.
src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellFlyoutTemplatedContentRenderer.cs Renames inset listener to Shell-specific name and updates references.
src/Controls/src/Core/Compatibility/Handlers/Shell/Android/ShellBottomNavViewAppearanceTracker.cs Tweaks default ColorStateList primary color for Material3.
src/Controls/src/Core/Compatibility/Handlers/NavigationPage/iOS/NavigationRenderer.cs Adds iOS gesture delegate, flyout menu button updates, safety checks for rapid nav, iOS 26 disposal guard, tracker target changes.
src/Controls/src/Core/Button/Button.iOS.cs Preserves AlwaysTemplate rendering mode if explicitly set when resizing images.
src/Controls/src/Core/BindingExpressionHelper.cs Adjusts conversion logic around “0” and “-0” canonicalization for decimal types.
src/Controls/src/Core/BindingExpression.cs Skips type mismatch checks for explicit non-relative Source bindings.
src/Controls/src/Build.Tasks/XmlTypeExtensions.cs Mirrors static *Extension shadowing guard in build task type resolution.
src/Controls/samples/Controls.Sample/ViewModels/OthersViewModel.cs Removes legacy “Large Titles - iOS” entry from Others section.
src/Controls/samples/Controls.Sample/Pages/PlatformSpecifics/iOS/iOSLargeTitlePage.xaml.cs Removes XAML code-behind for Large Title demo page.
src/Controls/samples/Controls.Sample/Pages/PlatformSpecifics/iOS/iOSLargeTitlePage.xaml Removes XAML for Large Title demo page.
src/Controls/samples/Controls.Sample/Pages/PlatformSpecifics/iOS/iOSLargeTitlePage.cs Reintroduces Large Title demo as pure C# UI + expanded scenarios.
src/Controls/samples/Controls.Sample/Pages/Others/LargeTitlesPageiOS.cs Removes older Large Titles demo page implementation.
src/Compatibility/Maps/src/iOS/MapRenderer.cs Tracks added MapElements to clear MapElementId on Reset/clear cycles.
src/Compatibility/Maps/src/Android/MapRenderer.cs Tracks added MapElements to clear MapElementId on Reset/clear cycles.
src/BlazorWebView/src/SharedSource/BlazorWebViewServiceCollectionExtensions.cs Uses BlazorWebView constants for SupportedOSPlatform attributes; adds MacCatalyst attribute.
src/BlazorWebView/src/Maui/build/Microsoft.AspNetCore.Components.WebView.Maui.targets Includes computed static web assets in single-file bundle.
src/BlazorWebView/src/Maui/Microsoft.AspNetCore.Components.WebView.Maui.csproj Sets SupportedOSPlatformVersion metadata (keep in sync with BlazorWebView constants).
src/BlazorWebView/src/Maui/BlazorWebViewHandler.cs Uses constants for platform support attributes across Android/iOS/MacCatalyst.
src/BlazorWebView/src/Maui/BlazorWebView.cs Adds platform support constants + applies them to attributes consistently.
eng/pipelines/common/ui-tests.yml Adds Essentials category to UI tests split categories list.

// even when an exception handler is present (for debug/hot reload scenarios).
// This prevents the app from crashing when relaunching.

Controls.Internals.ResourceLoader.ExceptionHandler2 = (ex) => { };
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

This test mutates a global static (ResourceLoader.ExceptionHandler2) but doesn’t restore the previous handler value. Please capture the original value before overwriting it and restore it in Dispose() (or via try/finally) to avoid cross-test coupling when other tests set the handler.

Copilot uses AI. Check for mistakes.
Comment on lines +46 to +49
public void Dispose()
{
Controls.Internals.ResourceLoader.ExceptionHandler2 = null;
}
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

This test mutates a global static (ResourceLoader.ExceptionHandler2) but doesn’t restore the previous handler value. Please capture the original value before overwriting it and restore it in Dispose() (or via try/finally) to avoid cross-test coupling when other tests set the handler.

Copilot uses AI. Check for mistakes.
Comment on lines +33 to +43
bool exceptionThrown = false;
try
{
page.LoadFromXaml(xaml);
}
catch (Exception)
{
exceptionThrown = true;
}

Assert.True(exceptionThrown, "Expected an exception to be thrown for missing ControlTemplate");
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

Prefer asserting exceptions directly (e.g., Assert.Throws<...>(() => ...)) instead of a boolean flag. This produces clearer failure output and avoids masking unintended exception types.

Suggested change
bool exceptionThrown = false;
try
{
page.LoadFromXaml(xaml);
}
catch (Exception)
{
exceptionThrown = true;
}
Assert.True(exceptionThrown, "Expected an exception to be thrown for missing ControlTemplate");
Assert.ThrowsAny<Exception>(() => page.LoadFromXaml(xaml));

Copilot uses AI. Check for mistakes.
Comment on lines +150 to +151
var handler = CreateHandler<SearchBarHandler>(searchBar);
var platformControl = GetPlatformControl(handler);
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

These iOS/MacCatalyst tests read UISearchBar.Frame immediately after handler creation without ensuring the control has been measured/arranged. Frame.Width/Height can legitimately be 0 (or differ due to layout rounding), making the test flaky. Consider placing the SearchBar into a parent, forcing a layout pass (measure/arrange + LayoutIfNeeded), and using a tolerance-based assertion.

Copilot uses AI. Check for mistakes.
Comment on lines +155 to +160
if (platformControl is UIKit.UISearchBar uiSearchBar)
{
actualWidth = uiSearchBar.Frame.Width;
}

Assert.Equal(requestedWidth, actualWidth);
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

These iOS/MacCatalyst tests read UISearchBar.Frame immediately after handler creation without ensuring the control has been measured/arranged. Frame.Width/Height can legitimately be 0 (or differ due to layout rounding), making the test flaky. Consider placing the SearchBar into a parent, forcing a layout pass (measure/arrange + LayoutIfNeeded), and using a tolerance-based assertion.

Copilot uses AI. Check for mistakes.

// do not canonicalize "-0"; user will likely enter a period after "-0"
if (stringValue == "-0" && DecimalTypes.Contains(convertTo))
if ((stringValue.StartsWith("0") || stringValue.StartsWith("-0")) && DecimalTypes.Contains(convertTo))
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

This broadens the previous special-case from exactly \"-0\" to any value starting with \"0\" (e.g., \"012\", \"0.5\", \"0\"). That can prevent conversion for valid numeric inputs with leading zeros and may regress numeric Entry typing behavior. Consider narrowing the condition to only the incremental-typing cases you want to preserve (e.g., \"-0\", \"0\", \"-0.\", \"0.\").

Copilot uses AI. Check for mistakes.
Comment on lines +168 to +170
// Get the filtered items source based on MaximumVisible
var itemsSource = GetFilteredItemsSource();
BindableLayout.SetItemsSource(this, itemsSource);
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

Returning a snapshot List<object> as the BindableLayout ItemsSource breaks change notifications when the original ItemsSource is observable (e.g., ObservableCollection): subsequent adds/removes won’t update the indicators. If the intent is to cap visible items while preserving live updates, consider using a wrapper collection which implements INotifyCollectionChanged and stays in sync with the source, or keeping the original ItemsSource and handling MaximumVisible at the template/layout level.

Copilot uses AI. Check for mistakes.
Comment on lines +192 to +201
var filteredItems = new List<object>(_indicatorView.MaximumVisible);
foreach (var item in itemsSource)
{
if (filteredItems.Count >= _indicatorView.MaximumVisible)
{
break;
}

filteredItems.Add(item);
}
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

Returning a snapshot List<object> as the BindableLayout ItemsSource breaks change notifications when the original ItemsSource is observable (e.g., ObservableCollection): subsequent adds/removes won’t update the indicators. If the intent is to cap visible items while preserving live updates, consider using a wrapper collection which implements INotifyCollectionChanged and stays in sync with the source, or keeping the original ItemsSource and handling MaximumVisible at the template/layout level.

Copilot uses AI. Check for mistakes.
Comment on lines +183 to +191
int totalCount = itemsSource is ICollection col
? col.Count
: itemsSource.Cast<object>().Count();

if (totalCount <= _indicatorView.MaximumVisible)
{
return itemsSource;
}

Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

For non-ICollection sources, Count() forces full enumeration, and the method then enumerates again to build the filtered list. This can be O(N) twice and can trigger side effects for streaming enumerables. Consider a single-pass approach which iterates until MaximumVisible + 1 (to detect overflow) without calling Count().

Suggested change
int totalCount = itemsSource is ICollection col
? col.Count
: itemsSource.Cast<object>().Count();
if (totalCount <= _indicatorView.MaximumVisible)
{
return itemsSource;
}
// If the source is a collection, we can use Count to determine whether filtering is necessary
if (itemsSource is ICollection col)
{
if (col.Count <= _indicatorView.MaximumVisible)
{
return itemsSource;
}
var filteredFromCollection = new List<object>(_indicatorView.MaximumVisible);
foreach (var item in itemsSource)
{
if (filteredFromCollection.Count >= _indicatorView.MaximumVisible)
{
break;
}
filteredFromCollection.Add(item);
}
return filteredFromCollection;
}
// For non-ICollection sources, avoid double enumeration by building the filtered list in a single pass

Copilot uses AI. Check for mistakes.
Comment on lines +2 to +5
*REMOVED*~static readonly Microsoft.Maui.Controls.Handlers.Compatibility.ShellRenderer.DefaultForegroundColor -> Microsoft.Maui.Graphics.Color
*REMOVED*~static readonly Microsoft.Maui.Controls.Handlers.Compatibility.ShellRenderer.DefaultTitleColor -> Microsoft.Maui.Graphics.Color
~static Microsoft.Maui.Controls.Handlers.Compatibility.ShellRenderer.DefaultForegroundColor.get -> Microsoft.Maui.Graphics.Color
~static Microsoft.Maui.Controls.Handlers.Compatibility.ShellRenderer.DefaultTitleColor.get -> Microsoft.Maui.Graphics.Color
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

This changes public API shape on Android from static readonly fields to properties. That’s a breaking change for consumers referencing the fields. If this is shipping in a minor/service release, it should be avoided (keep the fields and add new properties, or keep binary compatibility via obsolete forwarders if possible).

Copilot uses AI. Check for mistakes.
kubaflo pushed a commit that referenced this pull request Mar 30, 2026
…idate - 1 (#34670)

I have addressed the UI test image failures in this PR
(#34617) by adding base images and
re-saving the necessary UI test images.

- Re-saved the Material3FeatureTests, BoxViewFeatureTests,
BorderFeatureTests, and CollectionView_ScrollingFeatureTests images.
- Added the Mac, iOS, and Windows base images.
@sheiksyedm
Copy link
Copy Markdown
Contributor

/rebase

kubaflo pushed a commit that referenced this pull request Mar 31, 2026
…ed when ItemSpacing changes at runtime and candidate tests failures (#34664)

<!-- 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 with LinearItemsLayout, the first and last items become
truncated/clipped after changing the ItemSpacing value at runtime. This
affects both vertical and horizontal list orientations on Android.

**Note:** This is inflight/candate branch changes where exsiting PR
#27093 causes the regression on this branch. So added this new fix to
overcome the regression.

**Also, this fix resolves following tests failures on candidate PR
#34617:**

CollectionViewSelectionModeOnDarkTheme
CollectionViewSelectionModeOnLightTheme
VerifyCVBackgroundAndBackgroundColorWithVSM
Issue23377ItemSpacing
CVHorizontalLinearItemsLayoutItemSpacing 
CollectionViewPreSelectionShouldUpdate

### Root Cause
PR #27093 changed SpacingItemDecoration.GetItemOffsets to zero out the
outer edge offsets (outRect.Top = 0 for item 0, outRect.Bottom = 0 for
last item) for all layout types including LinearItemsLayout. However,
MauiRecyclerView.UpdateItemSpacing still applied negative padding
(SetPadding(-offset, ...)) on the RecyclerView for linear layouts. This
conflict caused the first and last items to be pulled outside the
visible area and clipped, since the positive offset that was supposed to
cancel the negative padding was removed.

### Description of Change
Added a _removeOuterEdgeSpacing boolean flag to SpacingItemDecoration,
set to true only for GridItemsLayout. In GetItemOffsets, an early return
is added when _removeOuterEdgeSpacing is false, skipping the
edge-zeroing logic for LinearItemsLayout. This restores the correct
balanced behavior for linear lists: the positive outRect offset (+N) and
the negative RecyclerView padding (-N) cancel each other out at the
edges, keeping the first and last items correctly positioned at the
screen boundary.

Validated the behavior in the following platforms
 
- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac
 
### Issues Fixed
  
Fixes #34636 

### Output  ScreenShot

| Before  | After  |
|---------|--------|
| <img width="361" height="746" alt="BeforeFix"
src="https://github.com/user-attachments/assets/6a8a08d5-ad1d-4578-9a37-4319eda88fce"
/> | <img width="361" height="746" alt="AfterFix"
src="https://github.com/user-attachments/assets/356d2d41-c953-4711-a165-1d31fbcd281b"
/> |
kubaflo pushed a commit that referenced this pull request Apr 3, 2026
…4760)

This pull request primarily introduces platform-specific test handling
and improvements to test reliability and maintainability in the MAUI
test suite. The main changes include adding conditional compilation to
skip or modify tests for specific platforms where features are
unsupported or behave differently, refactoring test code for clarity,
and adjusting data setup for scrolling feature tests.

**Platform-specific test handling:**

* Added `#if TEST_FAILS_ON_WINDOWS` and similar directives to multiple
test files (such as `Issue12131.cs`, `Issue21240.cs`, `Issue31109.cs`,
`Issue32995.cs`, and `TabbedPageFeatureTests.cs`) to skip or adjust
tests on Windows and other platforms where certain features are
unsupported or have known issues. Explanatory comments and links to
relevant GitHub issues are included for context.
[[1]](diffhunk://#diff-4967cd1d24b2578402405e12108feb36d6dbb4cec8fb530dd04da61e6a342abbR1-R3)
[[2]](diffhunk://#diff-6e55c1524ac32eaeddbb0a8804fffb7a6d5ef5127753f194d76c10e77595064cR1-R3)
[[3]](diffhunk://#diff-792c457903e89a20bbebff9ac8872d63fae0b25ba8ce42c16a5339c3d20a7970R1-R2)
[[4]](diffhunk://#diff-60deaf8f74a387042becb5819cac24e499abcca8242abe7f1efb507ddfaa5607R1)
[[5]](diffhunk://#diff-0c14bbbf93a322dc932f523b25c7fcb1e3fb98e6309edc283ec06b074464ca47R322-R323)

* Updated test methods in `Issue13537.cs` to explicitly verify the
triggering of `ApplyQueryAttributes` and simplified navigation
assertions, improving test clarity and reliability.
[[1]](diffhunk://#diff-8a0b88fd536529b3cd914be70ca2a1445f3fb833feaee2c0cba13c2cae76028eL26-R30)
[[2]](diffhunk://#diff-8a0b88fd536529b3cd914be70ca2a1445f3fb833feaee2c0cba13c2cae76028eL40-R49)

**Test reliability and maintainability:**

* Refactored navigation logic in `Issue28722.cs` to use a new
`NavigateBack()` helper method, which handles platform-specific
navigation differences and improves test robustness.

* Adjusted the test for the scrolling feature in
`CollectionView_ScrollingFeatureTests.cs` to include an extra scroll
gesture for Mac Catalyst, addressing platform-specific UI behavior.

**Test data setup improvements:**

* Modified the `CollectionViewViewModel` and related test pages to
accept a new `isScrollingFeatureTest` parameter, allowing for dynamic
adjustment of test data size depending on the test scenario (e.g., more
items for scrolling tests).
[[1]](diffhunk://#diff-df6d5b58c124d80e1fee4d941cdb6e46d17a052ca91274dd76ff2f5b0c495ff3L126-R128)
[[2]](diffhunk://#diff-df6d5b58c124d80e1fee4d941cdb6e46d17a052ca91274dd76ff2f5b0c495ff3L643-R643)
[[3]](diffhunk://#diff-df6d5b58c124d80e1fee4d941cdb6e46d17a052ca91274dd76ff2f5b0c495ff3L679-R680)
[[4]](diffhunk://#diff-df6d5b58c124d80e1fee4d941cdb6e46d17a052ca91274dd76ff2f5b0c495ff3L692-R693)
[[5]](diffhunk://#diff-9bdc032101814c121101794f70453396c96ad8b935758b14b5ee45bebd66b41dL11-R18)

**Test organization:**

* Added or updated conditional compilation blocks to ensure tests are
only compiled and run on supported platforms, reducing noise from known
failures and improving the accuracy of test results.
[[1]](diffhunk://#diff-5cd9b0108cf3bb480e3acc7d1a670c9b55e32c0b5c1fe89de1092e01d34311feR16-R24)
[[2]](diffhunk://#diff-0c14bbbf93a322dc932f523b25c7fcb1e3fb98e6309edc283ec06b074464ca47R350)
[[3]](diffhunk://#diff-4967cd1d24b2578402405e12108feb36d6dbb4cec8fb530dd04da61e6a342abbR36)
[[4]](diffhunk://#diff-6e55c1524ac32eaeddbb0a8804fffb7a6d5ef5127753f194d76c10e77595064cR33)
[[5]](diffhunk://#diff-792c457903e89a20bbebff9ac8872d63fae0b25ba8ce42c16a5339c3d20a7970R76)
[[6]](diffhunk://#diff-60deaf8f74a387042becb5819cac24e499abcca8242abe7f1efb507ddfaa5607R26)

**Test image resaving:**
* Resaved the valid images on the Android, iOS, macOS, and Windows
platforms

These changes collectively improve the reliability, maintainability, and
clarity of the MAUI test suite across different platforms.

Reverted this PR ##34750 changes that
is added for one test failures, but its not need.

Fixes: #34617

---------

Co-authored-by: NafeelaNazhir <nafeela.nazhirhussain@syncfusion.com>
Co-authored-by: HarishKumarSF4517 <harish.kumar@syncfusion.com>
Co-authored-by: devanathan-vaithiyanathan <114395405+devanathan-vaithiyanathan@users.noreply.github.com>
Co-authored-by: LogishaSelvarajSF4525 <logisha.selvaraj@syncfusion.com>
Co-authored-by: Ahamed-Ali <102580874+Ahamed-Ali@users.noreply.github.com>
@sheiksyedm
Copy link
Copy Markdown
Contributor

/rebase

NirmalKumarYuvaraj and others added 13 commits April 4, 2026 14:27
… a footer template is present or crashes when removing data. (#24867)

### Root Cause

- **Add** - When a CollectionView contains grouping and a footer
template, we create a new List<object> and add the footer to the list if
the footer's item template type is not an IList. This prevents events
such as CollectionChanged or INotifyCollectionChanged from being
triggered on the original collection. As a result, when a new item is
added to the collection, it is not reflected in the view.

- **Clear** - When clearing the collection and adding items at runtime,
a COM exception occurs when items are grouped. This happens because the
OnItemsVectorChanged event is triggered whenever there is a change in
the item collection, causing ListViewBase.ScrollIntoView to be called
from a background thread, which leads to the COM exception.
 
### Description of Change
 
#### Windows 

- **Add** - Reverting the changes made in PR #24205 caused the exception
. This exception occurred due to the triggering of the
TemplateCollectionChanged event, which was introduced during the
implementation of drag-and-drop functionality for the CollectionView in
PR #3768. Adding the footer to the items triggers the
TemplateCollectionChanged event, which incorrectly adds the footer as a
new item in the collection. Since the footer template is not the same
type as the items in the original collection, this results in the
exception. To resolve this, we can ignore the addition of the footer
template to the ItemsSource.
 
- **Clear** - Calling ListViewBase.ScrollIntoView in the DispatcherQueue
helps avoid exceptions and ensures synchronized updates.
Reference -
https://github.com/dotnet/maui/blob/5ceff42f4713a18516a0bffa209b0ed272e915b7/src/Controls/src/Core/Compatibility/Handlers/ListView/Windows/ListViewRenderer.cs#L628
 
Validated the behaviour in the following platforms
 
- [x] Android
- [x] Windows
- [ ] iOS
- [ ] Mac
 
iOS and Mac has issues - #17969 
 
### Issues Fixed
  
Fixes #24866 
Fixes #27302
Fixes #18481
Fixes #21791 

### Output 

#### Windows
|**Before**|**After**|
|--|--|
|<video
src="https://github.com/user-attachments/assets/2813d618-2c9d-4700-af20-8402b0779597">
| <video
src="https://github.com/user-attachments/assets/bb96519e-5a70-47a8-a872-d61ac2cf8f4f">
|
… value on iOS16+ - fix (#30733)

<!-- 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. !!!!!!!
-->

### Issues Fixed

Fixes #18669

|Before|After|
|--|--|
|<video
src="https://github.com/user-attachments/assets/1c43b0dc-a432-4107-81b5-d418e0a70a7b"
width="300px"></video>|<video
src="https://github.com/user-attachments/assets/fff7b26c-e703-4761-baa1-bf3e60f01005"
width="300px"></video>|
… fix (#29339)

<!-- 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!

### Issues Fixed

Fixes #20596

|Before|After|
|--|--|
|<video
src="https://github.com/user-attachments/assets/dd0ce289-bbff-453c-81ff-5306c891b14e"
width="300px"/>|<video
src="https://github.com/user-attachments/assets/8b07e943-4d38-4575-a216-e1252d12785c"
width="300px"/>|
…ft Text Selection on Editor and Entry (#30906)

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

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

### Issue Details
When selecting text from right to left, the SelectionLength property in
Entry and Editor is incorrectly reported as 0 on Android.
 
### Root Cause
On Android, when selecting text from right to left,
GetSelectedTextLength returned 0 due to incorrect handling of reverse
selection. In GetSelectionEnd, the selection length was also calculated
as 0, resulting in the selection length remaining zero even though text
was selected.
 
### Description of Change
 
Updated GetSelectedTextLength() to return the absolute difference
between SelectionStart and SelectionEnd using Math.Abs. Modified
GetSelectionEnd() to handle right-to-left selection by adjusting the end
position and correctly updating SelectionLength. This ensures consistent
behavior across selection directions and platforms.
 
### Validated the behaviour in the following platforms
 
- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac
 
### Issues Fixed:
Fixes #30782 
 
### Screenshots
| Before  | After |
|---------|--------|
|  <video
src="https://github.com/user-attachments/assets/9e6aff76-aa74-41f5-9047-e8449262b313">
|   <video
src="https://github.com/user-attachments/assets/e744b5fd-0b98-40d1-8875-e36e64021ccc"> 
|
…PopToRootAsync (#29779)

### Issue Detail
When the user inserts a page before the root and then pops the current
page using PopAsync (or pops to root using PopToRootAsync), the flyout
hamburger icon is not visible on iOS after the navigation completes.

### Root Cause
UpdateLeftBarButtonItem (which sets the flyout hamburger icon on the
ParentingViewController) was only called in the RemovePage method. The
programmatic pop paths — OnPopViewAsync, OnPopToRoot, and the
native-swipe-back path via UpdateFormsInnerNavigation — did not call it.
After a pop that results in a new root page, the flyout button was never
refreshed.

### Description of Change
Extracted the flyout-button-refresh logic from RemovePage into a new
private helper:

```
void UpdateFlyoutMenuButton(Page pageBeingRemoved = null)
{
    var parentingViewController = GetParentingViewController();
    parentingViewController?.UpdateLeftBarButtonItem(pageBeingRemoved);
}
```
Then called UpdateFlyoutMenuButton() at the end of:

- OnPopViewAsync — programmatic PopAsync()
- OnPopToRoot — programmatic PopToRootAsync()
- UpdateFormsInnerNavigation — native back-button (swipe) pop

RemovePage was refactored to use the same helper (no behavior change).

**File changed:**
src/Controls/src/Core/Compatibility/Handlers/NavigationPage/iOS/NavigationRenderer.cs

**Reference:**
https://github.com/dotnet/maui/blob/main/src/Controls/src/Core/Compatibility/Handlers/NavigationPage/iOS/NavigationRenderer.cs#L693

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

### Issues Fixed
 
Fixes #21828

### Screenshots

| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video width="300" height="600"
src="https://github.com/user-attachments/assets/7afc9d80-3d98-4f73-a124-dcc06c5e6d1c">
| <video width="300" height="600"
src="https://github.com/user-attachments/assets/7d59f508-9760-44bb-9889-4bd4fcca9353">)
|
…ource loads with delay (#34424)

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

### Root Cause

The bug is a **circular sizing dependency** specific to iOS horizontal
`CollectionView` with delayed data loading:

1. **UIKit assigns a large initial frame** (~812–1013px) to the
`CollectionView` before items load.
2. **`LayoutFactory2.CreateHorizontalList`** configures item and group
heights as `NSCollectionLayoutDimension.CreateFractionalHeight(1f)` —
items always fill 100% of the container height. This is intentional for
horizontal scroll UX.
3. Before items are realized, `CollectionViewContentSize.Width == 0` but
**`CollectionViewContentSize.Height` equals the current (large) frame
height** — a side effect of `FractionalHeight(1f)`.
4. In **`EnsureContentSizeForScrollDirection`** (CV2 /
`ItemsViewHandler2.iOS.cs`), the `Width == 0` branch correctly fetches a
desired width from `base.GetDesiredSize()` — but previously did NOT
reset `Height`, letting the large frame-derived height pass through.
5. MAUI reports this large height as the desired size → sets the frame
to that height → when items finally load, `FractionalHeight(1f)` × large
frame = items are large → height is never corrected. **The lock is
permanent.**

The same bug exists in the legacy CV1 handler (`ItemsViewController.cs`)
where `GetSize()` returned the raw `CollectionViewContentSize` without
resetting height for an empty horizontal layout.

### Description of Change
In both the CV2 (`Items2/`) and CV1 (`Items/`) iOS handler pipelines,
when a **horizontal CollectionView has `Width == 0`** (meaning no items
have been realized yet), also reset `Height = 0`. This breaks the
circular dependency by letting `MinimumHeightRequest` / `HeightRequest`
govern the initial size rather than an arbitrary frame-derived value.

**The condition `Width == 0`** is a reliable proxy for "no items
realized" because:
- A horizontal CV with any visible items will always have non-zero
content width.
- `Width == 0` uniquely occurs in the pre-items-loaded state that causes
the bug.

### Issues Fixed

Fixes #34336

### Technical Details

- **CV2 (`ItemsViewHandler2.iOS.cs`)** — When a horizontal
`CollectionView` has no items loaded yet (`Width == 0`),
`contentSize.Height` was incorrectly carrying the large UIKit-assigned
frame height. The fix also resets `Height` to zero in that case, so
`MinimumHeightRequest` / `HeightRequest` governs the initial size.

- **CV1 (`ItemsViewController.cs`)** — Same issue in the legacy handler.
A guard was added: if the layout is horizontal and `Width == 0`,
`Height` is reset to zero before the size is returned.

### Files Changed

| File | Change | Purpose |
|------|--------|---------|
| `src/Controls/src/Core/Handlers/Items2/ItemsViewHandler2.iOS.cs` | +8
lines | Fix CV2 (new iOS handler) circular height lock |
| `src/Controls/src/Core/Handlers/Items/iOS/ItemsViewController.cs` |
+15/-1 lines | Fix CV1 (legacy iOS handler) circular height lock |
| `src/Controls/tests/TestCases.HostApp/Issues/Issue34336.cs` | New file
(104 lines) | HostApp repro page: horizontal CV with 1s delayed
`ObservableCollection` load |
| `src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34336.cs`
| New file (31 lines) | NUnit UI test using `VerifyScreenshot(tolerance:
0.5)` to verify correct layout after delayed load |

### Screenshots

| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video width="300" height="600"
src="https://github.com/user-attachments/assets/ce13c0b9-cd35-40fe-a341-bb3c634cd441">
| <video width="300" height="600"
src="https://github.com/user-attachments/assets/49f720d6-b8ca-4520-bbe7-d579a9b43d18">)
|
<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

### Description of Change
This pull request introduces a new Material 3-based `SearchBarHandler2`
for Android, and conditionally uses it when Material 3 is enabled. The
new handler and its supporting platform classes provide improved
integration with Material 3 design, including custom appearance, clear
button, and color handling. Several internal extension methods and
mappings are updated to support this new handler, while maintaining
compatibility with the existing handler for non-Material 3 scenarios.

**Material 3 SearchBar support for Android:**

* Added a new internal `SearchBarHandler2` class for Material 3, with a
complete set of property and command mappers, event handlers, and
platform view integration. This handler is used only when Material 3 is
enabled.
* **SearchView limitation:** Android’s SearchView is designed to open as
an expanded overlay when tapped, covering other content. It's meant to
work in combination with a collapsed search bar trigger.
* The overlay’s height and behavior cannot be customized to behave like
a persistent inline search field. This limitation is inherent to the
SearchView design.
* **Solution**: So Introduced `MauiMaterialTextInputLayout` and
`MauiMaterialTextInputEditText` platform classes to provide Material 3
styling, clear button, and selection change support for the new
SearchBar handler.
* Updated `AppHostBuilderExtensions.cs` to register `SearchBarHandler2`
conditionally for Android when Material 3 is enabled, otherwise falling
back to the original handler.

**Mapping and platform extension updates:**

* Modified SearchBar mapping logic in `SearchBar.Mapper.cs` to use the
correct handler and mapping methods based on whether Material 3 is
enabled on Android.
* Added new extension methods in `SearchViewExtensions.cs` for Material
3 SearchBar support, including updating text, background, icon colors,
and return type for the new handler.
* Added a Material 3-specific overload for `MapText` in
`SearchBar.Android.cs` for use with `SearchBarHandler2`.

**Internal API and behavior improvements:**

* Made `UpdateIsTextPredictionEnabled` and `UpdateIsSpellCheckEnabled`
extension methods internal to allow usage by the new handler.
* Improved `UpdateCursorSelection` in `EditTextExtensions.cs` to post
selection changes when the EditText is focused, preventing potential
issues with selection updates.

### Issues Fixed

Fixes #33947 

### Screenshot
| Material 2  | Material 3 |
|---------|--------|
| <img height=600 width=300
src="https://github.com/user-attachments/assets/75269b67-1b8c-4e31-a880-c86d4102c76c">
|  <img height=600 width=300
src="https://github.com/user-attachments/assets/ba76f61d-587f-4421-b782-24bfb7a74155"> 
|

---------

Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
<!-- 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
The sizing of the RefreshView no longer works when the content is
wrapped inside a RefreshView. As a result, the RefreshView height is
calculated as 0.

### Root Cause
MauiSwipeRefreshLayout.OnMeasure called CrossPlatformMeasure() but
discarded the return value, never calling SetMeasuredDimension with the
correct size. Android kept height=0 from base.OnMeasure().

### Description of Change
Updated MauiSwipeRefreshLayout.OnMeasure() to correctly use the result
from CrossPlatformMeasure()
and call SetMeasuredDimension() with the resolved size. Previously, the
return value was discarded
and Android retained height=0 from base.OnMeasure().

The implementation respects MeasureSpecMode as follows:

- EXACTLY — uses the size from the measure spec (parent dictates size).
- AT_MOST — uses the full spec constraint (not the cross-platform
measure), matching Android's View.getDefaultSize() semantics. This is
intentional: SwipeRefreshLayout internally centers its spinner indicator
using getMeasuredWidth() / 2, so clamping to content size would
misposition the spinner.
- UNSPECIFIED — uses the size returned from CrossPlatformMeasure()
(content wraps naturally).

### Validated the behaviour in the following platforms
- [x] Android
- [ ] Windows
- [ ] iOS
- [ ] Mac


### Issues Fixed:
Fixes #12131

### Screenshots
| Before  | After |
|---------|--------|
| <img height=600 width=300
src="https://github.com/user-attachments/assets/6ffdfc04-fdc0-4c1a-b0fd-3f67c4744571">
|  <img height=600 width=300
src="https://github.com/user-attachments/assets/7143297a-94f2-48a8-9eca-3516ddf70491"> 
|
<!-- 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 : 
`SendNavigatingFrom()` was called too early in `SendNavigating()`—before
the navigation stack updated. At that point, `CurrentPage` still pointed
to the source page, so the event incorrectly reported the source page as
the destination.
### Description of Change
Bug fix for navigation event:

* Updated `IShellController.UpdateCurrentState` in `Shell.cs` to fire
`SendNavigatingFrom` after the shell state is updated, ensuring
`CurrentPage` correctly reflects the destination page in the
`NavigatingFromEventArgs`. The navigation type is determined based on
the navigation source.
* Modified `SendNavigating` in `Shell.cs` to capture the current page
for later use, rather than immediately firing `SendNavigatingFrom`, so
the destination is correct when the event is triggered.

Test coverage for the fix:

* Added a new test case in `Issue34073.cs` under `TestCases.HostApp` to
demonstrate and validate the correct behavior of `OnNavigatingFrom`,
showing the destination page is now accurate.
* Added a UI test in `TestCases.Shared.Tests/Tests/Issues/Issue34073.cs`
that navigates between pages and asserts that the destination page
reported by `OnNavigatingFrom` is correct.


<!-- 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 #34073 
### Tested the behavior in the following platforms

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

| Before Issue Fix | After Issue Fix |
|----------|----------|
| <img width="1080" height="1920" alt="BeforeFix34073"
src="https://github.com/user-attachments/assets/763e1c20-9f41-4fc2-b7d6-21261280b42a"
/> | <img width="1080" height="1920" alt="AfterFix34073"
src="https://github.com/user-attachments/assets/bc4f998e-52b7-492f-8fc5-61e2f56881a4">
|
| <img width="1125" height="2436" alt="BeforeFixiOS34073"
src="https://github.com/user-attachments/assets/fadc8294-77a8-4db2-b48f-787eb49e0f8b"
/> | <img width="1125" height="2436" alt="AfterFixiOS34073"
src="https://github.com/user-attachments/assets/237f1fbf-649a-48d2-9930-a182695cf9e9"
/> |
<!--
Are you targeting main? All PRs should target the main branch unless
otherwise noted.
-->
…anges (#34416)

### Root Cause
On Android, MAUI declares `configChanges="density"` in the manifest. As
a result, when the user changes the system display size (display
density), the `Activity` is not recreated. Instead, the existing view
hierarchy remains active and `OnSizeChanged` is triggered to update the
view’s pixel dimensions.

However, `PlatformGraphicsView` initializes its internal `_scale` field
only once during construction, and the field is marked as `readonly`.
Because the `Activity` is not recreated, this value is never refreshed
after a density change.

This leads to a mismatch between two density sources:

* `GraphicsView.Width` and `GraphicsView.Height`, which rely on MAUI’s
cached display density (`s_displayDensity`) set at application startup.
* The `dirtyRect` passed into `IDrawable.Draw()`, which is calculated
using the stale `_scale` value from `PlatformGraphicsView`.

After a system display size change, these two values diverge. As a
result, the drawable’s coordinate space no longer aligns with the view’s
logical dimensions, causing rendering inconsistencies and incorrect
drawing behavior.

### Description of Change
Removed the `readonly` modifier from the `_scale` field in
`PlatformGraphicsView` and introduced an internal virtual
`GetDisplayDensity()` method. The `_scale` value is now refreshed on
every `OnSizeChanged` call using the value returned by this method,
ensuring it reflects the current display density.

`PlatformTouchGraphicsView` (the MAUI-integrated subclass in the Core
project) overrides `GetDisplayDensity()` to return MAUI’s cached display
density — the same value used by `GraphicsView.Width` and
`GraphicsView.Height`.

This ensures that both logical sizing and `dirtyRect` calculations rely
on a consistent density source, keeping them fully synchronized even
after a system display density change.

### Issues Fixed
Fixes #34211 
 
Tested the behaviour in the following platforms
- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Note
display density can be forced on Android using `adb shell wm density`.
Other platforms do not provide a comparable runtime command or
automation method to override display density, so this scenario cannot
be triggered or validated the same way outside Android.

### Output Video
Before Issue Fix | After Issue Fix |
|----------|----------|
|<video width="40" height="60" alt="Before Fix"
src="https://github.com/user-attachments/assets/6c6af647-c758-40b3-802c-000d5021a936">|<video
width="50" height="40" alt="After Fix"
src="https://github.com/user-attachments/assets/85f7b299-2349-4fef-a2c1-b68b485dbd34">|
…WebView and HybridWebView (#30653)

<!-- 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
FlowDirection was only applied to the WebView and HybridWebview, not its
internal ScrollView, which handles the actual content layout and
scrolling.

### Description of Change

<!-- Enter description of the fix in this section -->
FlowDirection is now applied to the internal ScrollView of WKWebView to
ensure correct layout direction.

### 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 #30605 

### Regarding Test case
For this case, it's not possible to write a test because the scrollbar
does not appear during initial loading. It only becomes visible when a
scroll action is performed, and even then, it remains visible only for a
few seconds.

<!--
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/eaf6620b-5f00-402c-b191-2ba881cacac2"
width="300" height="600"> | **iOS**<br> <video
src="https://github.com/user-attachments/assets/b038125e-5dbf-483b-aa7d-640f2c72555e"
width="300" height="600"> |
#33439)

<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->
### Issue Details
MediaPicker on Android was appending _rotated and _processed suffixes to
filenames when rotating or compressing images, causing the original
filename to be lost.

### Description of Change

<!-- Enter description of the fix in this section -->
The updated implementation closes the input stream before performing any
file operations, deletes the original file, and writes the processed
(rotated) image back to the same file path. This ensures that the
original filename is preserved, avoiding the addition of any _rotated or
_processed suffixes.

### 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 #33258 

### Regarding test case
Picking an image is not possible in a test.

<!--
Are you targeting main? All PRs should target the main branch unless
otherwise noted.
-->

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

| Before  | After  |
|---------|--------|
| **Android**<br> <video
src="https://github.com/user-attachments/assets/35cb8242-9d10-4926-81b8-d28e291a56fe"
width="300" height="600"> | **Android**<br> <video
src="https://github.com/user-attachments/assets/92249ba3-76af-4d05-a789-8f63d02de86b"
width="300" height="600"> |
devanathan-vaithiyanathan and others added 27 commits April 4, 2026 14:27
…: RightToLeft) device tests (#34645)

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

### Issue Details
This PR #30653 causes [WebView] FlowDirection is set
correctly(flowDirection: RightToLeft) device tests was failed.


### Description of Change

<!-- Enter description of the fix in this section -->
The root cause is that MapFlowDirection only updated the internal
UIScrollView of WKWebView, but not the WKWebView itself. Since the test
reads SemanticContentAttribute directly from the WKWebView platform
view, it always returned LeftToRight regardless of the set value. So
updated the WebView FlowDirection as well.

### Test fixed
* [WebView] FlowDirection is set correctly(flowDirection: RightToLeft)
### Issue Details:
This PR  #30339 caused the NavBarIsVisibleUpdates unit test to fail.

### Description of Changes:
In the test case, the NavBarIsVisible property value was cleared, but
that scenario was not handled in the PR #30339 . I have updated the fix
to address this case. With the current changes, both the test failure
and the original issue are resolved.

### Test fixed 
* NavBarIsVisibleUpdates
Reverts 7ddc0a1, 49e9512, 117fd00, ca29f7a, 492769c which were
accidentally cherry-picked onto inflight/candidate. These fix commits
belong on the fix-34635 feature branch only.
…ute changes (#34668)

<!-- 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
This PR #28734 causes the unit test below

1. BackButtonUpdatesWhenSetToNewCommand
2. BackButtonDisabledWhenCommandDisabled

### Description of Change

The root cause is [IsEnabledCore { set => SetValue(IsEnabledProperty,
value && IsEnabled);
}](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html)
— a circular read: once
[IsEnabledProperty](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html)
is false, reading
[IsEnabled](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html)
always returns false, so the property is permanently stuck.

The fix introduces two backing fields to track the concerns
independently:

-
[_userDefinedIsEnabled](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html)
— written only by the developer via
[IsEnabled](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html)
-
[_commandEnabled](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html)
— written only by
[CanExecute](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html)
via
[IsEnabledCore](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html)
-
[IsEnabledProperty](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html)
is always [_userDefinedIsEnabled &&
_commandEnabled](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html),
eliminating the circular read.

- BackButtonDisabledWhenCommandDisabled — When
[CanExecute](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html)
flips to true and
[ChangeCanExecute()](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html)
is called,
[_commandEnabled](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html)
updates correctly and the back button re-enables.

- BackButtonUpdatesWhenSetToNewCommand — Setting [Command =
null](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html)
resets [_commandEnabled =
true](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html),
so the back button re-enables as expected.


### Test fixed
Unit tests:
BackButtonUpdatesWhenSetToNewCommand
BackButtonDisabledWhenCommandDisabled
…ice tests (#34674)

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

### Issue Details
This PR #32878 caused the NavigatingAwayFromTabbedPageResizesContentPage
device tests to failed in Candidate branch.


### Description of Change

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

In the device test NavigatingAwayFromTabbedPageResizesContentPage, the
height of the new ContentPage is validated. Due to the changes in PR
#32878, an incorrect page height was returned, causing the test to fail.

In TabbedPageManager, reintroduced RemoveTabs(). For modal navigation,
an early return is applied (similar to PR #32878).

With these changes, both issue
CommunityToolkit/Maui#2708 and the candidate
test failures are resolved.
…sample on candidate (#34697)

### Details

PR #30538 fixes the Windows Switch control width issue, where it
previously reserved unnecessary space inherited from WinUI’s
ToggleSwitch default style.
Due to this change, we need to re-save the existing switch images.
Also the reduced Switch width, the grid columns in AppThemePage are
rebalanced, causing the RadioButton (which has Grid.ColumnSpan="2") to
overlap the Editor control on the right side.

### Description of Change:

- Before: RadioButton had Grid.ColumnSpan="2", causing it to span both
columns and overlap the Editor in Column 1 of the same row.

- After: RadioButton is constrained to Grid.Column="0" only, so the
Editor in Column 1 remains in its own cell without overlap.

### Failures caused by these PRs: 
#30538 - The Switch previously
occupied the full width; now it takes only the required space.
#30089 - The Slider previously
appeared without a background color, now the background color is applied
correctly.

### Screenshots

| Before Issue Fix | After Issue Fix |
|----------|----------|
| <img width="300" height="600"
src="https://github.com/user-attachments/assets/ac70ad29-f055-4870-b9b2-5a381f601254">
| <img width="300" height="600"
src="https://github.com/user-attachments/assets/a06482bf-c0de-4c27-87be-d9d00a503723">
|
<!-- 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. !!!!!!!
-->

### Issues Details
PR #34276 caused the BackgroundGradientsShouldRenderCorrectly and
GradientAndShadowShouldWork UI tests to fail on iOS and Mac. Label text
is not visible when a gradient background is applied.


### Description of Change
In
[MapBackground](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html),
added a condition to route
[GradientPaint](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html)
backgrounds to
[handler.ToPlatform()](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html)
(WrapperView) where the gradient layer sits behind the label text. Other
backgrounds continue to use
[handler.PlatformView](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html)
(MauiLabel) to preserve the #34114 clip fix.

With these changes, both the gradient background test failures and the
original #34114 clip issue are resolved.


### Test Fixed 
UI Test
1. BackgroundGradientsShouldRenderCorrectly
2. GradientAndShadowShouldWork
…idate - 1 (#34670)

I have addressed the UI test image failures in this PR
(#34617) by adding base images and
re-saving the necessary UI test images.

- Re-saved the Material3FeatureTests, BoxViewFeatureTests,
BorderFeatureTests, and CollectionView_ScrollingFeatureTests images.
- Added the Mac, iOS, and Windows base images.
… device test (#34734)

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

The failure of `LifeCycleEvents` during top tab navigation on Android is
due to a race condition introduced by PR #30757, which deferred `MapsTo`
until after the `Loaded` event (`Loaded → MapsTo`). On Android, `Loaded`
is triggered via `ViewExtensions.OnLoaded`, where `SendLoaded` is
scheduled using `view.Post()` on `ViewAttachedToWindow`.

During programmatic tab switches (e.g., `ViewPager2.CurrentItem`), the
view rapidly detached and re-attached. In this window, the scheduled
callback can run after detachment, causing it to skip execution because
the view is no longer attached. However, the tracking reference is still
consumed, preventing the callback from being retried on the next attach.
As a result, `Loaded` never fires, `MapsTo` is not dispatched, and the
device test times out.

### Description of Change

The fix introduces a recovery mechanism within the `OnLoaded` method’s
`view.Post()` callback in `ViewExtensions.cs`. When the callback runs
while the view is detached, the tracking reference is now preserved
instead of being discarded. This ensures that when the view is
re-attached and the attach event is triggered again, the callback can be
retried successfully and `SendLoaded` executes once the view reaches a
stable attached state. The change is implemented as an additional
conditional branch and is limited to Android, specifically addressing
the detach and re-attach race condition without affecting normal
lifecycle behavior.

### Issues Fixed
`LifeCycleEventsFireWhenNavigatingTopTabs` - Android device test case.
 
Tested the behaviour in the following platforms
- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Screenshots
| Before Fix | After Fix |
|------------|-----------|
| <video width="350" alt="withoutfix"
src="https://github.com/user-attachments/assets/7807c6e9-0f91-42a5-b963-b99a5ca04116"
/> | <video width="350" alt="withfix"
src="https://github.com/user-attachments/assets/ebee1016-ca27-4a9e-a9dd-1caa82b65e77"
/> |
…#34739)

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

### Root Cause of the issue



- The problem is on `MauiCarouselRecyclerView`.cs:302. PR #30106 added
ScrollToPosition(carouselPosition) unconditionally — outside the
_scrollToCounter guard. So even when the Issue22417 explicitly calls
ScrollTo(5) (which increments _scrollToCounter), the dispatched callback
still forces the carousel back to carouselPosition (position 0 for a new
item added, since ItemsUpdatingScrollMode defaults to KeepScrollOffset).



### Description of Change



- Moved ScrollToPosition(carouselPosition) inside the _scrollToCounter
== savedScrollToCounter guard so it's also skipped when an explicit
ScrollTo was called between dispatch and delivery.

This preserves the #29415 fix because when no explicit ScrollTo is
called (the normal ItemsUpdatingScrollMode scenario), _scrollToCounter
won't change and the ScrollToPosition will still execute as intended.



### Issues Fixed



Fixes #29415 

### Test details fails on Candidate

- AddItemsToCarouselViewWorks (22417)

After fix, ensured AddItemsToCarouselViewWorks test and original issue
ItemsUpdatingScrollModeShouldWork (29415)

### Regression PR

- #30106

### Tested the behaviour in the following platforms



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



### Screenshot

| Before Issue Fix | After Issue Fix |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/d3d394be-8716-406f-8635-95035acee88a">
| <video
src="https://github.com/user-attachments/assets/2d1fb0f7-4caf-4956-b625-56e04412bdec">
|
…candidate branch (#34667)

<!-- 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!
  
**Reverts the iOS-specific `Window.SafeAreaInsets` changes that caused
CollectionView cell misalignment on the candidate branch from #33908 ,
and re-implements safe area handling via per-cell geometric overlap
computation that works correctly across all platforms.**
 
### Root Cause
**Cause of regression:**
PR #33908 introduced the issue by using `Window.SafeAreaInsets` for
`CollectionView` cells; on macOS this includes a 41px title bar. Due to
a timing race (`IsParentHandlingSafeArea()` returning false), all cells
incorrectly applied this inset, causing misalignment.
Reverted the iOS changes from PR #33908 in MauiView.cs, restoring the
previous behavior. Android changes were retained as they function
correctly.

**Actual root cause of Issue33604:**
PR #33908 modified `MauiView.GetAdjustedSafeAreaInsets()` to use
`Window.SafeAreaInsets` as the base safe area for CollectionView cell
descendants. On macOS, `Window.SafeAreaInsets.Top` is 41px (title bar).
Combined with `IsParentHandlingSafeArea()` returning false due to a
timing race (parent not yet validated), every CollectionView cell
received `_appliesSafeAreaAdjustments = true` with a 41px top inset,
causing all items to be misaligned on MacCatalyst.
Fix: Fully reverted all iOS changes from PR #33908 in MauiView.cs,
restoring it to the pre-#33908 state. The Android changes from PR #33908
are retained as they work correctly (WindowInsetsCompat propagates to
all views regardless of `RecyclerView` containment).
 
### Description of Change
The fix introduces a shared helper in `MauiView`
(`ApplyCellSafeAreaOverride` / `ComputeCellSafeAreaInsets`) used by both
`TemplatedCell` (CV1) and `TemplatedCell2` (CV2) during
`LayoutSubviews`.

Before arranging, per-cell safe area insets are computed based on the
cell's geometric position relative to the window's unsafe regions and
passed via a new `CellSafeAreaOverride` property. The cell frame remains
full-width so backgrounds extend edge-to-edge, while content is inset
internally.

Uniform configurations (`Container×4`, `None×4`, `All×4`) are skipped as
they are handled by the parent layout. Insets are applied only for edges
explicitly set to `Container` or `All`, and ignored for `SoftInput`-only
edges. A tolerance filter (`ToSafeAreaInsets`) avoids sub-pixel layout
noise.

`MauiView` applies this override during `CrossPlatformMeasure` and
`CrossPlatformArrange` when `_appliesSafeAreaAdjustments` is false,
treating it as internal padding consistent with existing
`AdjustForSafeArea` behavior. Stale overrides are cleared during cell
reuse when the template no longer implements `ISafeAreaView2`.

Additionally, `ContentInsetsReference` is set to
`UIContentInsetsReference.None` at all three section creation sites in
`LayoutFactory2` (Linear, Grid, Carousel). On iOS 26.1+, the default
(`.automatic` → `.safeArea`) started actively insetting cells at the
section level in `UICollectionViewCompositionalLayout`, conflicting with
MAUI's internal safe area handling. Setting `.None` restores pre-26.1
behavior. CV1 is unaffected as it uses `UICollectionViewFlowLayout`,
which does not have this property.

### Issues Fixed
Fixes #33604 
Fixes #34635 

### Additional Fixes
Also resolves the following Failed iOS test cases:
`VerifyGroupFooterTemplate_WithFooterString`
`VerifyGroupHeaderTemplate_WithFooterString`
`VerifyIsGroupedFalse_WithHeaderAndFooterString`
`SelectedItemVisualIsCleared`
`CollectionViewItemsShouldRespectSafeAreaEdges`
 
Tested the behaviour in the following platforms
- [x] Android
- [ ] Windows
- [x] iOS
- [x] Mac

### Screenshots
**Issue33604**
| Before Fix | After Fix |
|------------|-----------|
| <video width="350" alt="withoutfix"
src="https://github.com/user-attachments/assets/466ca15c-db77-45ff-8cfb-2d2042ca3b2d"
/> | <video width="350" alt="withfix"
src="https://github.com/user-attachments/assets/33f9ea89-a8bd-40c8-b4d8-cb0e7d93348c"
/> |

**Issue34635**
| Before Fix | After Fix |
|------------|-----------|
| <video width="350" alt="withoutfix"
src="https://github.com/user-attachments/assets/783cc1ba-f18d-4aa2-8102-2e217f32ccc9"
/> | <video width="350" alt="withfix"
src="https://github.com/user-attachments/assets/9b6e8107-20d0-4a71-b2b5-3030a2db317c"
/> |
)

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

### Root Cause
PR #34493 correctly reduced UpdateLayout() from N calls to a single call
per layout-property change, but it exposed a UIKit behavior where
SetCollectionViewLayout(layout, animated: false) can shift the
contentOffset on a UICollectionViewCompositionalLayout with estimated
item sizes. This causes the scroll position to jump after an ItemSpacing
change.

**Test name:** Issue23377ItemSpacing
 
### Description of change
This PR resolves the `Issue23377ItemSpacing` test failure on the
candidate branch. In ItemsViewController2.UpdateLayout(), the
contentOffset is saved before calling SetCollectionViewLayout and
explicitly restored afterward, ensuring the scroll position is preserved
across layout updates on both iOS and MacCatalyst.

**Cause PR:** #34493

### Test result
| Before Issue Fix | After Issue Fix |
|----------|----------|
| <img width="300" height="600"
src="https://github.com/user-attachments/assets/d3e7d730-07ec-4987-bb4e-bd5b7c39897b">
| <img width="300" height="600"
src="https://github.com/user-attachments/assets/115e8518-3ae2-40f8-ae3b-e82f8079a5da">
|
…26213)" (#34753)

This reverts commit d686a51.

Reverts kubaflo's fix from PR #26213 which addressed issue #26158
(SelectionLength property update when entry is focused).

SelectionLength does not work properly on iOS. When the Entry is focused
for the first time, the SelectionLength is not updated. After closing
the keyboard and focusing the Entry again, it works correctly. Due to
this inconsistency, I reverted the changes

### Changes Reverted
- Removed `Issue26158.cs` HostApp test page
- Removed `Issue26158.cs` shared tests
- Removed snapshot images for
`SelectionLengthShouldUpdateWhenEntryIsFocused`
- Reverted `TextFieldExtensions.cs` iOS changes (removed `DispatchAsync`
logic for focused entry selection update)
- Reverted `EditTextExtensions.cs` Android changes (removed
`Post()`/`IsAlive()` async dispatch for focused entry selection update)

---------
…or fix disabled More button when tabs > 5 (#34745)

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

PR #[33955](#33955) added
`ApplyInitialDisabledState` to apply disabled tab styling on iOS. When a
Shell has more than 5 tabs, iOS displays 4 visible tabs plus a system
"More" button.
The loop iterated by index and mapped the 5th shell section to the
"More" button, disabling it and blocking access to all overflow tabs.

### Description of Change

Calculate the number of visible tab items excluding the system "More"
button before iterating. When a "More" tab exists, the loop now stops
one item before the last TabBar entry, ensuring only actual shell
section tabs are processed.

### Issues Fixed
`GitHubIssue6184` - iOS UI test case.
 
Tested the behaviour in the following platforms
- [x] Android
- [ ] Windows
- [x] iOS
- [ ] Mac

### Screenshots
| Before Fix | After Fix |
|------------|-----------|
| <video width="350" alt="withoutfix"
src="https://github.com/user-attachments/assets/500ed712-09b3-46dc-8e6e-f79522508c58"
/> | <video width="350" alt="withfix"
src="https://github.com/user-attachments/assets/11d823d7-48dc-474a-be50-03daeaced23f"
/> |
…ch (#34756)

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

### Root Cause
PR #24867 deferred the OnItemsVectorChanged logic into an async
DispatcherQueue.TryEnqueue lambda. Later, PR #34534 introduced
DisconnectHandlers() in CleanUpCollectionViewSource, which sets
base.VirtualView to null before the queued lambda executes.

**Test name:** FlexLayoutCycleException

### Description of Change
This PR resolves the `FlexLayoutCycleException` test failure on the
candidate branch. In ItemsViewHandler.Windows.cs, the guards inside the
OnItemsVectorChanged lambda were updated from: if (VirtualView is null)
return; to: if (((IViewHandler)this).VirtualView is null) return; No
other changes were made.

**Cause PR:** #34534

### Test result
| Before Issue Fix | After Issue Fix |
|----------|----------|
| <img width="300" height="600"
src="https://github.com/user-attachments/assets/ac0d8e92-8c20-4647-8334-b3dcbaa96a64">
| <img width="300" height="600"
src="https://github.com/user-attachments/assets/77010f17-8db3-4ffe-9a51-ba19e4b5079c">
|
…ed when ItemSpacing changes at runtime and candidate tests failures (#34664)

<!-- 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 with LinearItemsLayout, the first and last items become
truncated/clipped after changing the ItemSpacing value at runtime. This
affects both vertical and horizontal list orientations on Android.

**Note:** This is inflight/candate branch changes where exsiting PR
#27093 causes the regression on this branch. So added this new fix to
overcome the regression.

**Also, this fix resolves following tests failures on candidate PR
#34617:**

CollectionViewSelectionModeOnDarkTheme
CollectionViewSelectionModeOnLightTheme
VerifyCVBackgroundAndBackgroundColorWithVSM
Issue23377ItemSpacing
CVHorizontalLinearItemsLayoutItemSpacing 
CollectionViewPreSelectionShouldUpdate

### Root Cause
PR #27093 changed SpacingItemDecoration.GetItemOffsets to zero out the
outer edge offsets (outRect.Top = 0 for item 0, outRect.Bottom = 0 for
last item) for all layout types including LinearItemsLayout. However,
MauiRecyclerView.UpdateItemSpacing still applied negative padding
(SetPadding(-offset, ...)) on the RecyclerView for linear layouts. This
conflict caused the first and last items to be pulled outside the
visible area and clipped, since the positive offset that was supposed to
cancel the negative padding was removed.

### Description of Change
Added a _removeOuterEdgeSpacing boolean flag to SpacingItemDecoration,
set to true only for GridItemsLayout. In GetItemOffsets, an early return
is added when _removeOuterEdgeSpacing is false, skipping the
edge-zeroing logic for LinearItemsLayout. This restores the correct
balanced behavior for linear lists: the positive outRect offset (+N) and
the negative RecyclerView padding (-N) cancel each other out at the
edges, keeping the first and last items correctly positioned at the
screen boundary.

Validated the behavior in the following platforms
 
- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac
 
### Issues Fixed
  
Fixes #34636 

### Output  ScreenShot

| Before  | After  |
|---------|--------|
| <img width="361" height="746" alt="BeforeFix"
src="https://github.com/user-attachments/assets/6a8a08d5-ad1d-4578-9a37-4319eda88fce"
/> | <img width="361" height="746" alt="AfterFix"
src="https://github.com/user-attachments/assets/356d2d41-c953-4711-a165-1d31fbcd281b"
/> |
…34773)

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

### Root Cause
- PR #34081 correctly reduced stepValue to spaceToMin when near the
minimum boundary so iOS 26 keeps the decrement button enabled — for
example, with value=2 and interval=10, spaceToMin=2 is less than the
interval so stepValue is set to 2 instead of 10. But this same reduced
stepValue is also used by the increment button — causing it to step by 2
instead of the full interval 10, producing wrong values like 4 instead
of the expected 12. This is why Issue20706.ChangeIncrementValue failed —
the test changes the increment to 10 and taps the increment button
expecting 12, but gets 4.

### Description of Change
- In OnValueChanged, after UIStepper applies a reduced stepValue, a
check is performed to determine whether the step was partial (smaller
than the defined interval). If the full step (oldValue + interval) falls
within the valid range [min, max], the value is overridden to the
expected result (e.g., ensuring “+” results in 12 instead of 4). If the
full step exceeds the bounds (e.g., decrementing from value = 2 would
result in -8), the value is left unchanged, preserving the intended
boundary behavior.

### Issues Fixed

- Regression introduced by PR #34081
- **Resolved test case:** Issue20706.ChangeIncrementValue UI Test

### Output
| Before | After |
|----------|----------|
| <img
src="https://github.com/user-attachments/assets/52cd25f9-1d9e-4280-86c5-c731e551acb2">
| <img
src="https://github.com/user-attachments/assets/83c130b9-d12b-426a-8558-f1987762b454">
|
…nch (#34777)

<!-- 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 of the issue:

- On Windows SearchBar, the read-only behavior is applied through an
attached property on AutoSuggestBox, but the internal TextBox is created
only after template/load.
- Initial IsReadOnly values could be set before the internal TextBox
existed, so the value was not reliably reflected in the actual input
control during first render.
- MaxLength == 0 is intended to force read-only (to block all typing),
but IsReadOnly updates could later override that state if the mapper
logic did not consistently re-apply the MaxLength rule.
- **Result**: behavior was inconsistent across initialization and
subsequent property changes, and the SearchBar clear/deletion scenario
in issue 29547 was not reliable on Windows.

### Description of Change
- Updated the Windows SearchBar read-only pipeline to reliably apply the
attached IsReadOnly value both:
- Immediately when the platform control is already loaded.
- Deferred via OnLoaded when the internal TextBox is not yet available.
- Kept the attached property value as the source of truth so deferred
application can read and apply the latest state.
- Updated SearchBar UpdateIsReadOnly mapping to enforce the intended
rule in one expression:
- MaxLength == 0 || IsReadOnly.
- This guarantees MaxLength == 0 always has priority, while still
honoring normal IsReadOnly behavior when max length is not zero.
…uldBeCorrect UI test failure on iOS 26.1+ (#34782)

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

PR #30757 defers the `NavigatedTo` event until the page’s `Loaded` event
fires, using `CurrentPage.IsLoaded` to decide whether to defer. On iOS,
`IsLoaded` checks if `UIView.Window` is set.

With iOS 26.1+, UIKit changed `AddSubview` to set `UIView.Window`
synchronously instead of during the layout pass. As a result, `IsLoaded`
returns true earlier—before the MAUI `Loaded` event is actually
dispatched—causing `NavigatedTo` to fire immediately and before
`Loaded`, reintroducing the original event-ordering issue only on iOS
26.1+.

### Description of Change

Replaced the `IsLoaded` check with `IsLoadedFired` in
`PropagateSendNavigatedTo` and `SendNavigating`. `IsLoaded` relies on
platform-level view attachment (`UIView.Window != null` on iOS), which
became unreliable due to UIKit’s synchronous behavior change in iOS
26.1+. `IsLoadedFired`, on the other hand, tracks whether the MAUI
`Loaded` event has actually been dispatched (`_isLoadedFired` set via
`SendLoaded()`), ensuring correct lifecycle ordering independent of
platform timing differences.

This change ensures consistent behavior across platforms — on Windows,
`IsLoadedFired` is already true synchronously (no change), and on iOS
18.5/26.0 and Android, both values remain false at this stage, so
existing behavior is preserved while fixing the regression on iOS 26.1+.

### Issues Fixed
`ShellFlyoutNavigationEventOrderShouldBeCorrect` - UI test case.
 
Tested the behaviour in the following platforms
- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac
…empty text transition (#34698)

<!-- 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 a Label is initialized with LineBreakMode="TailTruncation" and
its Text is null or empty during the first
render, later updates to the Text property do not render any visible
text on iOS. The label remains visually
empty even though the Text value changes successfully.

### Root Cause
- **Regression**: Introduced by PR #28931
- PR #28931 introduced ComputeConstraintForView on several layouts,
which causes a Label with default HorizontalOptions = Fill (e.g., inside
a VerticalStackLayout) to be marked as HorizontallyFixed. This activates
an existing optimization in TextChangedShouldInvalidateMeasure that
skips InvalidateMeasureInternal for labels that are both single-line and
horizontally fixed.
- This optimization is valid for typical text changes (e.g., "Hello" →
"World") where the height remains unchanged. However, it fails for the
empty → non-empty transition. When a label initially has null/empty
text, iOS measures it with a height of 0, and MAUI caches this value.
When text is later assigned, the optimization prevents re-measurement,
leaving the stale 0-height intact—resulting in the label being invisible
despite having text.

### Description of Change
- Updated OnTextPropertyChanged in Label.cs to always invalidate measure
when the label's text transitions between empty and non-empty, ensuring
the label is properly rendered and sized in scenarios like
TailTruncation.


### Issues Fixed
Fixes #34591

### Validated the behaviour in the following platforms

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

### Output
| Before | After |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/7d46bf6a-50f5-45ee-bc34-58071e4f17de">
| <video
src="https://github.com/user-attachments/assets/7d600c48-2c94-4efe-ba98-81adf4976925">
|
…4760)

This pull request primarily introduces platform-specific test handling
and improvements to test reliability and maintainability in the MAUI
test suite. The main changes include adding conditional compilation to
skip or modify tests for specific platforms where features are
unsupported or behave differently, refactoring test code for clarity,
and adjusting data setup for scrolling feature tests.

**Platform-specific test handling:**

* Added `#if TEST_FAILS_ON_WINDOWS` and similar directives to multiple
test files (such as `Issue12131.cs`, `Issue21240.cs`, `Issue31109.cs`,
`Issue32995.cs`, and `TabbedPageFeatureTests.cs`) to skip or adjust
tests on Windows and other platforms where certain features are
unsupported or have known issues. Explanatory comments and links to
relevant GitHub issues are included for context.
[[1]](diffhunk://#diff-4967cd1d24b2578402405e12108feb36d6dbb4cec8fb530dd04da61e6a342abbR1-R3)
[[2]](diffhunk://#diff-6e55c1524ac32eaeddbb0a8804fffb7a6d5ef5127753f194d76c10e77595064cR1-R3)
[[3]](diffhunk://#diff-792c457903e89a20bbebff9ac8872d63fae0b25ba8ce42c16a5339c3d20a7970R1-R2)
[[4]](diffhunk://#diff-60deaf8f74a387042becb5819cac24e499abcca8242abe7f1efb507ddfaa5607R1)
[[5]](diffhunk://#diff-0c14bbbf93a322dc932f523b25c7fcb1e3fb98e6309edc283ec06b074464ca47R322-R323)

* Updated test methods in `Issue13537.cs` to explicitly verify the
triggering of `ApplyQueryAttributes` and simplified navigation
assertions, improving test clarity and reliability.
[[1]](diffhunk://#diff-8a0b88fd536529b3cd914be70ca2a1445f3fb833feaee2c0cba13c2cae76028eL26-R30)
[[2]](diffhunk://#diff-8a0b88fd536529b3cd914be70ca2a1445f3fb833feaee2c0cba13c2cae76028eL40-R49)

**Test reliability and maintainability:**

* Refactored navigation logic in `Issue28722.cs` to use a new
`NavigateBack()` helper method, which handles platform-specific
navigation differences and improves test robustness.

* Adjusted the test for the scrolling feature in
`CollectionView_ScrollingFeatureTests.cs` to include an extra scroll
gesture for Mac Catalyst, addressing platform-specific UI behavior.

**Test data setup improvements:**

* Modified the `CollectionViewViewModel` and related test pages to
accept a new `isScrollingFeatureTest` parameter, allowing for dynamic
adjustment of test data size depending on the test scenario (e.g., more
items for scrolling tests).
[[1]](diffhunk://#diff-df6d5b58c124d80e1fee4d941cdb6e46d17a052ca91274dd76ff2f5b0c495ff3L126-R128)
[[2]](diffhunk://#diff-df6d5b58c124d80e1fee4d941cdb6e46d17a052ca91274dd76ff2f5b0c495ff3L643-R643)
[[3]](diffhunk://#diff-df6d5b58c124d80e1fee4d941cdb6e46d17a052ca91274dd76ff2f5b0c495ff3L679-R680)
[[4]](diffhunk://#diff-df6d5b58c124d80e1fee4d941cdb6e46d17a052ca91274dd76ff2f5b0c495ff3L692-R693)
[[5]](diffhunk://#diff-9bdc032101814c121101794f70453396c96ad8b935758b14b5ee45bebd66b41dL11-R18)

**Test organization:**

* Added or updated conditional compilation blocks to ensure tests are
only compiled and run on supported platforms, reducing noise from known
failures and improving the accuracy of test results.
[[1]](diffhunk://#diff-5cd9b0108cf3bb480e3acc7d1a670c9b55e32c0b5c1fe89de1092e01d34311feR16-R24)
[[2]](diffhunk://#diff-0c14bbbf93a322dc932f523b25c7fcb1e3fb98e6309edc283ec06b074464ca47R350)
[[3]](diffhunk://#diff-4967cd1d24b2578402405e12108feb36d6dbb4cec8fb530dd04da61e6a342abbR36)
[[4]](diffhunk://#diff-6e55c1524ac32eaeddbb0a8804fffb7a6d5ef5127753f194d76c10e77595064cR33)
[[5]](diffhunk://#diff-792c457903e89a20bbebff9ac8872d63fae0b25ba8ce42c16a5339c3d20a7970R76)
[[6]](diffhunk://#diff-60deaf8f74a387042becb5819cac24e499abcca8242abe7f1efb507ddfaa5607R26)

**Test image resaving:**
* Resaved the valid images on the Android, iOS, macOS, and Windows
platforms

These changes collectively improve the reliability, maintainability, and
clarity of the MAUI test suite across different platforms.

Reverted this PR ##34750 changes that
is added for one test failures, but its not need.

Fixes: #34617

---------

Co-authored-by: NafeelaNazhir <nafeela.nazhirhussain@syncfusion.com>
Co-authored-by: HarishKumarSF4517 <harish.kumar@syncfusion.com>
Co-authored-by: devanathan-vaithiyanathan <114395405+devanathan-vaithiyanathan@users.noreply.github.com>
Co-authored-by: LogishaSelvarajSF4525 <logisha.selvaraj@syncfusion.com>
Co-authored-by: Ahamed-Ali <102580874+Ahamed-Ali@users.noreply.github.com>
@sheiksyedm sheiksyedm force-pushed the inflight/candidate branch from 5b1a4e0 to ba59eaf Compare April 4, 2026 08:57
@sheiksyedm
Copy link
Copy Markdown
Contributor

/azp run maui-pr-uitests , maui-pr-devicetests

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 2 pipeline(s).

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