Skip to content

[.NET 11] [Android] Implemented material3 support for CarouselView - #35640

Draft
Dhivya-SF4094 wants to merge 13 commits into
dotnet:net11.0from
Dhivya-SF4094:material3_Carousel
Draft

[.NET 11] [Android] Implemented material3 support for CarouselView#35640
Dhivya-SF4094 wants to merge 13 commits into
dotnet:net11.0from
Dhivya-SF4094:material3_Carousel

Conversation

@Dhivya-SF4094

@Dhivya-SF4094 Dhivya-SF4094 commented May 27, 2026

Copy link
Copy Markdown
Contributor

Description of Change

This pull request introduces a new implementation for Material Design Carousel support in the Android handler code, focusing on compatibility with Material's CarouselLayoutManager and its unique requirements. The most significant changes include the addition of new adapter and view holder classes that wrap carousel items in a MaskableFrameLayout, a new scroll listener tailored for Material's carousel, and several extensibility points in the base classes to support these requirements. There are also targeted refactors to enable more flexible handling of looping and empty views.

Material Carousel Support and Adapter Enhancements:

  • Added CarouselViewAdapter2, a new adapter for MauiCarouselRecyclerView2, which wraps each item in a MaskableFrameLayout to satisfy Material's CarouselLayoutManager requirements. This adapter also disables virtual looping, exposing the real item count to avoid performance issues and infinite layout loops with the Material carousel. (src/Controls/src/Core/Handlers/Items2/Android/Adapters/CarouselViewAdapter2.cs)
  • Introduced MaskableCarouselItemViewHolder, a view holder that manages MAUI content inside a MaskableFrameLayout, ensuring the correct handling of item templates and data binding for the Material carousel. (src/Controls/src/Core/Handlers/Items2/Android/MaskableCarouselItemViewHolder.cs)
  • Added CarouselViewOnScrollListener2, a scroll listener tailored for MauiCarouselRecyclerView2 that works directly with CarouselLayoutManager and does not depend on the legacy loop manager. It accurately tracks visible items and snap positions.(src/Controls/src/Core/Handlers/Items2/Android/CarouselViewOnScrollListener2.cs)
  • Raw string items (a CarouselView bound to plain strings with no ItemTemplate) are also wrapped in a MaskableFrameLayout via MaskableTextItemViewHolder, since CarouselLayoutManager rejects any direct RecyclerView child that is not a MaskableFrameLayout.
  • The Material handler renders the EmptyView using a plain LinearLayoutManager instead of Material's CarouselLayoutManager. MauiCarouselRecyclerView2.SelectLayoutManager returns a LinearLayoutManager whenever the active adapter is the EmptyViewAdapter, because Material's keyline mask (sized for full-viewport carousel items) would collapse a normally-sized EmptyView.

Loop Logic Improvements:

  • Refactored loop logic in MauiCarouselRecyclerView by introducing the IsLoopEnabled property, allowing subclasses to override loop behavior (for example, to disable looping when using a layout manager that does not support virtual looping), and replaced direct checks of Carousel.Loop with IsLoopEnabled throughout the code.

Important

The Material3 path is locked to FullScreenCarouselStrategy (one item masked to the full viewport, snapping one page at a time). The following CarouselView behaviors are intentionally not supported under this strategy and are documented in code:

  • Loop is not supported. Material's CarouselLayoutManager has no virtual-range model, so the legacy LoopScale (≈16384) trick used by the LinearLayoutManager path causes infinite measure/GC loops. Handler2 forces non-loop behavior (IsLoopEnabled => false) and exposes the real item count. Keep CarouselView.Loop="False".
  • PeekAreaInsets is not supported. FullScreenCarouselStrategy masks every item to fill the viewport, so there is no peek of adjacent items. The mapper is a documented no-op and item sizing deliberately ignores the insets.
  • LinearItemsLayout.ItemSpacing is not honoured. Material's CarouselLayoutManager has no spacing API, and it builds its KeylineState from the decorated measured size of the first child — so injecting spacing offsets (decoration/margins) would distort the keyline geometry. With full-viewport single-snap pages there is also no inter-item gutter for spacing to occupy. It is a documented no-op.
  • Per-item visual states are not surfaced. CurrentItem/PreviousItem/NextItem/DefaultItem are only observable when adjacent items peek into view (the docs example uses PeekAreaInsets="100"). Because Handler2 has no peek and shows only the current item at a time, these states are not driven. This is documented as an explicit limitation to revisit if a non-full-screen strategy with peek support is added.

Each limitation is scoped to FullScreenCarouselStrategy and can be revisited if strategy-aware sizing (MultiBrowse/Hero/Uncontained) is wired up via CreateCarouselStrategy.

Fixed

Fixes #35637

Screenshots

Before  After
 
35637_BeforeChanges.mov
  
35637_AfterChanges.mov

UI Test results

Material2  Material3 
      

@github-actions

github-actions Bot commented May 27, 2026

Copy link
Copy Markdown
Contributor

🚀 Dogfood this PR with:

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

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

Or

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

@dotnet-policy-service dotnet-policy-service Bot added the partner/syncfusion Issues / PR's with Syncfusion collaboration label May 27, 2026
@github-actions github-actions Bot added area-controls-collectionview CollectionView, CarouselView, IndicatorView platform/android labels May 27, 2026
@kubaflo

kubaflo commented May 27, 2026

Copy link
Copy Markdown
Contributor

/review -b feature/refactor-copilot-yml

1 similar comment
@kubaflo

kubaflo commented May 28, 2026

Copy link
Copy Markdown
Contributor

/review -b feature/refactor-copilot-yml

@MauiBot MauiBot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Expert Review — 6 findings

See inline comments for details.

Comment thread src/Controls/src/Core/Hosting/AppHostBuilderExtensions.cs Outdated
Comment thread src/Controls/src/Core/Handlers/Items2/Android/Adapters/CarouselViewAdapter2.cs Outdated
Comment thread src/Controls/src/Core/Handlers/Items2/Android/IMauiCarouselRecyclerView2.cs Outdated
@MauiBot MauiBot added s/agent-fix-win AI found a better alternative fix than the PR s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) labels May 28, 2026
@MauiBot

This comment has been minimized.

@kubaflo kubaflo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could you check the ai's suggestions?

@Dhivya-SF4094
Dhivya-SF4094 force-pushed the material3_Carousel branch 2 times, most recently from 4b948d7 to 90d2165 Compare June 4, 2026 12:13
@kubaflo

kubaflo commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

/review -b feature/enhanced-reviewer -p android

@MauiBot

This comment has been minimized.

@kubaflo

kubaflo commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

/review rerun

@github-actions github-actions Bot added the s/agent-ready-for-rerun AI review has a new PR-author comment or commit and is ready for rerun label Jun 10, 2026
@kubaflo

kubaflo commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

/review -b feature/enhanced-reviewer -p android

@github-actions github-actions Bot added s/agent-review-in-progress AI review is currently running for this PR and removed s/agent-ready-for-rerun AI review has a new PR-author comment or commit and is ready for rerun labels Jun 10, 2026

@MauiBot MauiBot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Expert Review — 6 findings

See inline comments for details.

Comment thread src/Controls/src/Core/Hosting/AppHostBuilderExtensions.cs
Comment thread src/Controls/src/Core/Handlers/Items2/Android/Adapters/CarouselViewAdapter2.cs Outdated
Comment thread src/Controls/src/Core/Handlers/Items2/Android/IMauiCarouselRecyclerView2.cs Outdated
MauiBot

This comment was marked as outdated.

@kubaflo

kubaflo commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

/review -b feature/enhanced-reviewer -p android

@github-actions github-actions Bot added the s/agent-review-in-progress AI review is currently running for this PR label Jun 11, 2026
MauiBot

This comment was marked as outdated.

@MauiBot MauiBot removed the s/agent-review-in-progress AI review is currently running for this PR label Jun 11, 2026
Copilot AI review requested due to automatic review settings July 30, 2026 05:18

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

src/Controls/src/Core/Handlers/Items2/Android/MauiCarouselRecyclerView2.cs:120

  • UpdateSnapBehavior attaches CarouselSnapHelper for all non-None snap settings, but Material's CarouselSnapHelper always center-snaps and doesn't support MAUI's SnapPointsAlignment (Start/End) or the full set of SnapPointsType behaviors. Since this is a behavioral difference when Material3 is enabled, it should be explicitly documented here to avoid confusion when those properties appear to be ignored.
        // Honor SnapPointsType.None: when the user disables snapping, leave the carousel
        // free-scrolling instead of forcing Material's page snap. This mirrors the legacy
        // SnapManager behavior (see Items/Android/SnapHelpers/SnapManager.cs).
        if (ItemsLayout is Microsoft.Maui.Controls.ItemsLayout { SnapPointsType: SnapPointsType.None })
        {

@vishnumenon2684

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

@kubaflo

This comment has been minimized.

@github-actions

This comment has been minimized.

@kubaflo kubaflo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could you please check if test failures are related?

@kubaflo

This comment has been minimized.

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Tests Failure Analysis

@Dhivya-SF4094 — test-failure review results are available based on commit 9f78b11.

Maintainers can request a fresh review after new comments, commits, or CI runs by commenting /review tests.

Overall Not ready Failures 40 Regressed vs base 3 Baseline 3 on base

Test Failure Review: Not ready - click to expand

Overall verdict: Not ready. Of 40 distinct failures, 3 legs are deterministic regressions vs the base net11.0 branch (red on the PR, green across all 5 recently sampled base builds per definition), while only 3 also fail on base and are dismissable; the remaining ~34 are unattributed (flaky-on-base, infra, or unverified device-test legs) and require human classification.

  • ✗ PR-related — Deterministic regressions vs base (~3 legs): a Windows device-test build leg, a drag-drop UI test, and the iOS CV1 test-result publish all pass on every sampled base build but fail here; representative DragEvents.
  • i Uncertain — New Material3 CarouselView/Button UI tests (~5 tests): timeouts and possible-crash tear-downs on the feature this PR adds, but the legs are also red on base so attribution is indeterminate; representative Material3VerifyCarouselViewWithPosition.
  • i Uncertain — HybridWebView InvokeJavaScript* assertion failures (~10 tests, iOS/Windows): InvokeJavaScript vs InvokeJavaScriptAsync message mismatch, unrelated to CarouselView; representative InvokeJavaScriptMethodThatThrowsString.
  • i Uncertain — Unexplained build legs, aborted/canceled checks, and unverified device-test legs (~22 legs + 2 aborted + 3 device-test-unverified): logs yield no extractable failure or XHarness green could not be confirmed; representative 🛠️ Build Microsoft.Maui.sln.
  • i Uncertain — Infra/provisioning flakiness (~several): Android SDK platform-tools;35.0.2 provisioning and emulator/instrumentation crashes; representative DialogsRenderWithM3Styling.
  • ● Unrelated — Pre-existing-on-base Shell visual/timeout flakes (~3 tests): the only failures also observed on the base branch; representative TopTabUnselectedTextVisibleWhenSwitchingTabs.

Coverage: 141 checks · 123 passing · 18 failing · 0 pending · 0 inaccessible · 1 unmapped · 22 unexplained build legs · 0 unaccounted failing checks · 2 aborted failing checks · 0 canceled-build checks · 3 device-test unverified · 37 unattributed · 3 regressed-vs-base. Deterministic ceiling: Not ready — 3 legs regressed vs base, plus unexplained/aborted/unverified legs forbid a green verdict.

Builds (this PR): maui-pr 1532716, maui-pr-devicetests 1532751, maui-pr-uitests 1532750. Base sampling (net11.0, 5 recent builds per definition): maui-pr 1535343, maui-pr-devicetests 1535345, maui-pr-uitests 1535443.

Recommended action

A human should investigate the 3 regressed-vs-base legs (DragEvents, the Windows device-test build, and the iOS CV1 publish) and confirm the unverified device-test/aborted legs before merging.

Visual failure comparisons

Full-resolution CI baseline, actual, and diff images are embedded below. They supplement the failure classification and do not change the deterministic verdict ceiling.
Relationship labels use deterministic exact test-and-platform baseline evidence plus exact changed snapshot/test scope; missing or mixed evidence remains Needs human investigation.

VerifyShell_IsVisible - macos - Needs human investigation - visual comparison

CI reported size differs - baseline is 789x563 pixels, actual is 1920x1051 pixels in build 1532750.

Relationship to PR: Needs human investigation - No decisive exact test-and-platform baseline attribution was available.

CI baselineFresh PR actualCI diff
VerifyShell_IsVisible baseline VerifyShell_IsVisible actual VerifyShell_IsVisible diff
ShellPages_PresentationModeModalNotAnimated - macos - Needs human investigation - visual comparison

CI reported size differs - baseline is 789x563 pixels, actual is 1920x1051 pixels in build 1532750.

Relationship to PR: Needs human investigation - No decisive exact test-and-platform baseline attribution was available.

CI baselineFresh PR actualCI diff
ShellPages_PresentationModeModalNotAnimated baseline ShellPages_PresentationModeModalNotAnimated actual ShellPages_PresentationModeModalNotAnimated diff
ShellPages_PresentationModeModalAnimated - macos - Needs human investigation - visual comparison

CI reported size differs - baseline is 789x563 pixels, actual is 1920x1051 pixels in build 1532750.

Relationship to PR: Needs human investigation - No decisive exact test-and-platform baseline attribution was available.

CI baselineFresh PR actualCI diff
ShellPages_PresentationModeModalAnimated baseline ShellPages_PresentationModeModalAnimated actual ShellPages_PresentationModeModalAnimated diff
ShellPages_PresentationModeModal - macos - Needs human investigation - visual comparison

CI reported size differs - baseline is 789x563 pixels, actual is 1920x1051 pixels in build 1532750.

Relationship to PR: Needs human investigation - No decisive exact test-and-platform baseline attribution was available.

CI baselineFresh PR actualCI diff
ShellPages_PresentationModeModal baseline ShellPages_PresentationModeModal actual ShellPages_PresentationModeModal diff
ShellPages_PresentationModeAnimated - macos - Needs human investigation - visual comparison

CI reported size differs - baseline is 789x563 pixels, actual is 1920x1051 pixels in build 1532750.

Relationship to PR: Needs human investigation - No decisive exact test-and-platform baseline attribution was available.

CI baselineFresh PR actualCI diff
ShellPages_PresentationModeAnimated baseline ShellPages_PresentationModeAnimated actual ShellPages_PresentationModeAnimated diff
ShellPages_PresentationModeNotAnimated - macos - Needs human investigation - visual comparison

CI reported size differs - baseline is 789x563 pixels, actual is 1920x1051 pixels in build 1532750.

Relationship to PR: Needs human investigation - No decisive exact test-and-platform baseline attribution was available.

CI baselineFresh PR actualCI diff
ShellPages_PresentationModeNotAnimated baseline ShellPages_PresentationModeNotAnimated actual ShellPages_PresentationModeNotAnimated diff
ShellPages_IsVisibleTrue - macos - Needs human investigation - visual comparison

CI reported size differs - baseline is 789x563 pixels, actual is 1920x1051 pixels in build 1532750.

Relationship to PR: Needs human investigation - No decisive exact test-and-platform baseline attribution was available.

CI baselineFresh PR actualCI diff
ShellPages_IsVisibleTrue baseline ShellPages_IsVisibleTrue actual ShellPages_IsVisibleTrue diff
ShellPages_IsVisibleFalse - macos - Needs human investigation - visual comparison

CI reported size differs - baseline is 789x563 pixels, actual is 1920x1051 pixels in build 1532750.

Relationship to PR: Needs human investigation - No decisive exact test-and-platform baseline attribution was available.

CI baselineFresh PR actualCI diff
ShellPages_IsVisibleFalse baseline ShellPages_IsVisibleFalse actual ShellPages_IsVisibleFalse diff
ShellPages_ShowTitleViewHidden - macos - Needs human investigation - visual comparison

CI reported size differs - baseline is 789x563 pixels, actual is 1920x1051 pixels in build 1532750.

Relationship to PR: Needs human investigation - No decisive exact test-and-platform baseline attribution was available.

CI baselineFresh PR actualCI diff
ShellPages_ShowTitleViewHidden baseline ShellPages_ShowTitleViewHidden actual ShellPages_ShowTitleViewHidden diff
ShellPages_ShowTitleView - macos - Needs human investigation - visual comparison

CI reported size differs - baseline is 789x563 pixels, actual is 1920x1051 pixels in build 1532750.

Relationship to PR: Needs human investigation - No decisive exact test-and-platform baseline attribution was available.

CI baselineFresh PR actualCI diff
ShellPages_ShowTitleView baseline ShellPages_ShowTitleView actual ShellPages_ShowTitleView diff
EnsureFlyoutIconWithForegroundColor - macos - Needs human investigation - visual comparison

CI reported size differs - baseline is 789x563 pixels, actual is 1920x1051 pixels in build 1532750.

Relationship to PR: Needs human investigation - No decisive exact test-and-platform baseline attribution was available.

CI baselineFresh PR actualCI diff
EnsureFlyoutIconWithForegroundColor baseline EnsureFlyoutIconWithForegroundColor actual EnsureFlyoutIconWithForegroundColor diff
Visual output was bounded for comment safety; 13 additional comparison(s) were omitted. 26 additional visual comparison(s) were omitted by publisher bounds (deduplication, the comparison cap, the discovery/publish time budget, or assets that failed validation).

@kubaflo

This comment has been minimized.

@kubaflo

kubaflo commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated no new comments.

Suppressed comments (2)

src/Controls/src/Core/Handlers/Items/Android/MauiCarouselRecyclerView.cs:52

  • IsLoopEnabled was introduced so subclasses (e.g., the Material3 carousel) can force the non-loop code paths, but UpdateLoop() later in this file still branches on Carousel.Loop directly (e.g., var loopValue = Carousel.Loop; and if (Carousel.Loop)). That means a subclass overriding IsLoopEnabled => false can still hit loop-specific logic when CarouselView.Loop changes, which can reintroduce the virtual-loop behavior this abstraction is meant to prevent.
		// Subclasses backed by a layout manager that has no virtual-range concept
		// (e.g. Material's CarouselLayoutManager) can override this to force the
		// non-loop code paths regardless of the public Carousel.Loop value.
		protected virtual bool IsLoopEnabled => Carousel?.Loop == true;

src/Controls/tests/TestCases.Shared.Tests/Tests/FeatureMatrix/Material3CarouselViewFeatureTests.cs:50

  • These tests currently depend on state set up only in the first test (tapping CarouselViewButton to enter the carousel scenario). Since most tests start directly with Options, they will fail if run individually or if the app resets between tests. To make the suite robust, add per-test setup that navigates into the CarouselView scenario and enable ResetAfterEachTest for a clean start each test; then remove the redundant CarouselViewButton steps from the first test.
    public Material3CarouselViewFeatureTests(TestDevice device) : base(device)
    {
    }

    [Test, Order(1)]
    [Category(UITestCategories.Material3)]
    public void Material3VerifyCarouselViewLoadsItems()
    {
        // Regression guard for #35637: the Material CarouselLayoutManager must lay out the
        // real item count and render the first item instead of getting stuck on splash.
        App.WaitForElement("CarouselViewButton");
        App.Tap("CarouselViewButton");
        App.WaitForElement(Options);
        App.Tap(Options);
        App.WaitForElement(Apply);
        App.Tap(Apply);
        App.WaitForElement("Item 1");
    }

@MauiBot

This comment has been minimized.

@kubaflo

This comment has been minimized.

1 similar comment
@kubaflo

This comment has been minimized.

@MauiBot

This comment has been minimized.

@kubaflo

This comment has been minimized.

@kubaflo kubaflo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could you please check if test failures are related?

@MauiBot MauiBot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

AI Review Summary

@Dhivya-SF4094 — new AI review results are available based on this last commit: c7a66fe.

Gate Partial Confidence Low Platform Android


🗂️ Review Sessions — click to expand
🚦 Gate — Test Before & After Fix

Gate Result: ❌ FAILED

Platform: ANDROID · Base: net11.0 · Merge base: 5d366053

🩺 Test does not reproduce the bug — ran the same in both states (PASS without fix, PASS with fix). The repro test is not exercising the issue. Strengthen the test before reviewing the fix.

Test Without Fix (expect FAIL) With Fix (expect PASS)
🖥️ Material3CarouselViewFeatureTests Material3CarouselViewFeatureTests ❌ PASS — 3093s ✅ PASS — 583s
🔴 Without fix — 🖥️ Material3CarouselViewFeatureTests: PASS ❌ · 3093s

Error-relevant lines (filtered from the build log):

/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/37.0.0-ci.main.2160/tools/Xamarin.Android.Common.Debugging.targets(378,5): error ADB0010: Xamarin.Android.Tasks.FastDeployInstallException: Serving... [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net11.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/37.0.0-ci.main.2160/tools/Xamarin.Android.Common.Debugging.targets(378,5): error ADB0010: Performing Incremental Install [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net11.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/37.0.0-ci.main.2160/tools/Xamarin.Android.Common.Debugging.targets(378,5): error ADB0010:  [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net11.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/37.0.0-ci.main.2160/tools/Xamarin.Android.Common.Debugging.targets(378,5): error ADB0010: Performing Streamed Install [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net11.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/37.0.0-ci.main.2160/tools/Xamarin.Android.Common.Debugging.targets(378,5): error ADB0010: All files should be loaded. Notifying the device. [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net11.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/37.0.0-ci.main.2160/tools/Xamarin.Android.Common.Debugging.targets(378,5): error ADB0010: Timed out waiting for data from device. [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net11.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/37.0.0-ci.main.2160/tools/Xamarin.Android.Common.Debugging.targets(378,5): error ADB0010: adb: failed to install /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net11.0-android/com.microsoft.maui.uitests-Signed.apk: cmd: Failure calling service package: Broken pipe (32) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net11.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/37.0.0-ci.main.2160/tools/Xamarin.Android.Common.Debugging.targets(378,5): error ADB0010:    at Xamarin.Android.Tasks.FastDeploy2.InstallApkWithRetry(String apkFile, Boolean reinstall, Boolean testOnly, String user) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net11.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/37.0.0-ci.main.2160/tools/Xamarin.Android.Common.Debugging.targets(378,5): error ADB0010:    at Xamarin.Android.Tasks.FastDeploy2.InstallPackage() [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net11.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/37.0.0-ci.main.2160/tools/Xamarin.Android.Common.Debugging.targets(378,5): error ADB0010:    at Xamarin.Android.Tasks.FastDeploy2.RunInstall() [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net11.0-android]
Build FAILED.
🟢 With fix — 🖥️ Material3CarouselViewFeatureTests: PASS ✅ · 583s

(no coded error found; showing last 1200 chars)

 08/02/2026 20:17:54 Material3VerifyCarouselViewWithScrollTo Stop
  Passed Material3VerifyCarouselViewWithScrollTo [5 s]
>>>>> 08/02/2026 20:17:54 Material3VerifyCarouselViewWithScrollToAndCurrentItem Start
>>>>> 08/02/2026 20:18:00 Material3VerifyCarouselViewWithScrollToAndCurrentItem Stop
  Passed Material3VerifyCarouselViewWithScrollToAndCurrentItem [5 s]
>>>>> 08/02/2026 20:18:00 Material3VerifyCarouselViewWithVerticalLayout Start
>>>>> 08/02/2026 20:18:06 Material3VerifyCarouselViewWithVerticalLayout Stop
  Passed Material3VerifyCarouselViewWithVerticalLayout [6 s]
>>>>> 08/02/2026 20:18:06 Material3VerifyCarouselViewWithVerticalLayoutAndKeepItemInView Start
>>>>> 08/02/2026 20:18:12 Material3VerifyCarouselViewWithVerticalLayoutAndKeepItemInView Stop
  Passed Material3VerifyCarouselViewWithVerticalLayoutAndKeepItemInView [6 s]
NUnit Adapter 4.5.0.0: Test execution complete
Results File: /home/vsts/work/1/s/CustomAgentLogsTmp/UITests/TestResults/Material3CarouselViewFeatureTests.trx
Test Run Successful.
Total tests: 17
     Passed: 17
 Total time: 2.0595 Minutes
>>> TRX_RESULT_FILE: /home/vsts/work/1/s/CustomAgentLogsTmp/UITests/TestResults/Material3CarouselViewFeatureTests.trx

⚠️ Failure Details

  • Material3CarouselViewFeatureTests PASSED without fix (should fail) — tests don't catch the bug
📁 Fix files reverted (4 files)
  • src/Controls/src/Core/Handlers/Items/Android/MauiCarouselRecyclerView.cs
  • src/Controls/src/Core/Handlers/Items/Android/MauiRecyclerView.cs
  • src/Controls/src/Core/Hosting/AppHostBuilderExtensions.cs
  • src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt

New files (not reverted):

  • src/Controls/src/Core/Handlers/Items2/Android/Adapters/CarouselViewAdapter2.cs
  • src/Controls/src/Core/Handlers/Items2/Android/CarouselViewOnScrollListener2.cs
  • src/Controls/src/Core/Handlers/Items2/Android/MaskableCarouselItemViewHolder.cs
  • src/Controls/src/Core/Handlers/Items2/Android/MaskableTextItemViewHolder.cs
  • src/Controls/src/Core/Handlers/Items2/Android/MauiCarouselRecyclerView2.cs
  • src/Controls/src/Core/Handlers/Items2/CarouselViewHandler2.Android.cs

📱 UI Tests — CarouselView,CollectionView,Material3

Detected UI test categories: CarouselView,CollectionView,Material3

Deep UI tests — 726 passed, 19 failed across 3 categories on platform-pool agent (replaces in-process counts above). 318 new snapshot tests need a baseline PNG (added separately by a maintainer — not a regression).

🧪 UI Test Execution Results (deep, platform pool)

Category Tests Snapshot diffs
CarouselView 90/91 (1 ❌) 2 diff PNGs
CollectionView 612/630 (18 ❌)
Material3 24/342 (318 ⚠ new baseline)
🔍 AI analysis of failures — PR-related vs unrelated

🔍 AI-generated triage (GitHub Copilot CLI) — a heuristic judgement of whether each deep UI test failure is connected to this PR's changes. Verify before relying on it.

Mixed / uncertain: see the grouped assessment below.

  • ✗ PR-related — Android CarouselView / Material3 carousel handler visual behavior (~1 test): the PR directly changes Android CarouselView handler code, loop handling, snap/listener behavior, and Material3 carousel adapter/layout plumbing, so the VerticalCarouselMandatorySingleSnapAdvancesOneCard snapshot difference is plausibly connected.
  • ℹ Uncertain — Android CollectionView scroll-to timeouts (~16 tests): the PR touches shared Android MauiCarouselRecyclerView base code but not Android CollectionView itself, while these failures are the common “timed out waiting for element” scroll/flakiness pattern, so the evidence is weak and indirect.
  • ● Unrelated — Android CollectionView stale element (~1 test): StaleElementReferenceException on CollectionViewHeaderShouldNotScroll is a known nondeterministic Appium/DOM-refresh pattern and the PR does not change CollectionView header behavior.
  • ● Unrelated — Material3 non-carousel missing snapshot baselines (310+ tests): these fail with “Baseline snapshot not yet created” across DatePicker, Button, Slider, ImageButton, SearchBar, Label, and other Material3 controls outside the PR’s changed handler/test area, indicating missing Android snapshot baselines rather than a functional regression from this PR.

Strongest signal: only the CarouselView snapshot failure overlaps the PR’s Android CarouselView/Material3 handler changes; the large Material3 set is baseline creation noise and the CollectionView rows mostly match flaky timeout/stale-element patterns.

CarouselView — 1 failed test
VerticalCarouselMandatorySingleSnapAdvancesOneCard
VisualTestUtils.VisualTestFailedException : 
Snapshot different than baseline: VerticalCarouselMandatorySingleSnapAdvancesOneCard.png (4.87% difference)
If the correct baseline has changed (this isn't a a bug), then update the baseline image.
See test attachment or download the build artifacts to get the new snapshot file.

More info: https://aka.ms/visual-test-workflow
at Microsoft.Maui.TestCases.Tests.UITest.VerifyScreenshot(String name, Nullable`1 retryDelay, Nullable`1 retryTimeout, Int32 cropLeft, Int32 cropRight, Int32 cropTop, Int32 cropBottom, Double tolerance) in /_/src/Controls/tests/TestCases.Shared.Tests/UITest.cs:line 296
   at Microsoft.Maui.TestCases.Tests.Issues.Issue33308.VerticalCarouselMandatorySingleSnapAdvancesOneCard() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue33308.cs:line 26
   at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
   at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, Bi
...
CollectionView — 18 failed tests
VerifyGroupIndexScrollToByIndexWithEndPositionAndHorizontalGrid_Potato
System.TimeoutException : Timed out waiting for element...
at UITest.Appium.HelperExtensions.Wait(Func`1 query, Func`2 satisfactory, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2761
   at UITest.Appium.HelperExtensions.WaitForAtLeastOne(Func`1 query, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2788
   at UITest.Appium.HelperExtensions.WaitForElement(IApp app, String marked, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency, Nullable`1 postTimeout) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 797
   at Microsoft.Maui.TestCases.Tests.CollectionView_ScrollingFeatureTests.VerifyGroupIndexScrollToByIndexWithEndPositionAndHorizontalGrid_Potato() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/FeatureMatrix/CollectionView_ScrollingFeatureTests.cs:line 3170
   at System.Reflec
...
VerifyGroupItemScrollToByIndexWithEndPositionAndHorizontalList_Kiwi
System.TimeoutException : Timed out waiting for element...
at UITest.Appium.HelperExtensions.Wait(Func`1 query, Func`2 satisfactory, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2761
   at UITest.Appium.HelperExtensions.WaitForAtLeastOne(Func`1 query, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2788
   at UITest.Appium.HelperExtensions.WaitForElement(IApp app, String marked, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency, Nullable`1 postTimeout) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 797
   at Microsoft.Maui.TestCases.Tests.CollectionView_ScrollingFeatureTests.VerifyGroupItemScrollToByIndexWithEndPositionAndHorizontalList_Kiwi() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/FeatureMatrix/CollectionView_ScrollingFeatureTests.cs:line 3561
   at System.RuntimeMe
...
VerifyScrollToByIndexWithEndPositionAndHorizontalList_Kiwi
System.TimeoutException : Timed out waiting for element...
at UITest.Appium.HelperExtensions.Wait(Func`1 query, Func`2 satisfactory, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2761
   at UITest.Appium.HelperExtensions.WaitForAtLeastOne(Func`1 query, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2788
   at UITest.Appium.HelperExtensions.WaitForElement(IApp app, String marked, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency, Nullable`1 postTimeout) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 797
   at Microsoft.Maui.TestCases.Tests.CollectionView_ScrollingFeatureTests.VerifyScrollToByIndexWithEndPositionAndHorizontalList_Kiwi() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/FeatureMatrix/CollectionView_ScrollingFeatureTests.cs:line 2376
   at System.RuntimeMethodHandl
...
VerifyScrollToByIndexWithMakeVisiblePositionAndHorizontalList_Kiwi
System.TimeoutException : Timed out waiting for element...
at UITest.Appium.HelperExtensions.Wait(Func`1 query, Func`2 satisfactory, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2761
   at UITest.Appium.HelperExtensions.WaitForAtLeastOne(Func`1 query, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2788
   at UITest.Appium.HelperExtensions.WaitForElement(IApp app, String marked, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency, Nullable`1 postTimeout) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 797
   at Microsoft.Maui.TestCases.Tests.CollectionView_ScrollingFeatureTests.VerifyScrollToByIndexWithMakeVisiblePositionAndHorizontalList_Kiwi() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/FeatureMatrix/CollectionView_ScrollingFeatureTests.cs:line 2137
   at System.RuntimeMet
...
VerifyScrollToByItemWithStartPositionAndHorizontalList_Kiwi
System.TimeoutException : Timed out waiting for element...
at UITest.Appium.HelperExtensions.Wait(Func`1 query, Func`2 satisfactory, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2761
   at UITest.Appium.HelperExtensions.WaitForAtLeastOne(Func`1 query, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2788
   at UITest.Appium.HelperExtensions.WaitForElement(IApp app, String marked, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency, Nullable`1 postTimeout) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 797
   at Microsoft.Maui.TestCases.Tests.CollectionView_ScrollingFeatureTests.VerifyScrollToByItemWithStartPositionAndHorizontalList_Kiwi() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/FeatureMatrix/CollectionView_ScrollingFeatureTests.cs:line 2541
   at System.RuntimeMethodHand
...
VerifyGroupIndexScrollToByIndexWithStartPositionAndHorizontalList_Kiwi
System.TimeoutException : Timed out waiting for element...
at UITest.Appium.HelperExtensions.Wait(Func`1 query, Func`2 satisfactory, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2761
   at UITest.Appium.HelperExtensions.WaitForAtLeastOne(Func`1 query, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2788
   at UITest.Appium.HelperExtensions.WaitForElement(IApp app, String marked, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency, Nullable`1 postTimeout) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 797
   at Microsoft.Maui.TestCases.Tests.CollectionView_ScrollingFeatureTests.VerifyGroupIndexScrollToByIndexWithStartPositionAndHorizontalList_Kiwi() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/FeatureMatrix/CollectionView_ScrollingFeatureTests.cs:line 2918
   at System.Reflec
...
CollectionViewHeaderShouldNotScroll
OpenQA.Selenium.StaleElementReferenceException : Cached elements 'By.id: com.microsoft.maui.uitests:id/HeaderEntry' do not exist in DOM anymore; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#stale-element-reference-exception
at OpenQA.Selenium.WebDriver.UnpackAndThrowOnError(Response errorResponse, String commandToExecute)
   at OpenQA.Selenium.WebDriver.ExecuteAsync(String driverCommandToExecute, Dictionary`2 parameters)
   at OpenQA.Selenium.WebDriver.InternalExecute(String driverCommandToExecute, Dictionary`2 parameters)
   at OpenQA.Selenium.WebElement.Execute(String commandToExecute, Dictionary`2 parameters)
   at OpenQA.Selenium.WebElement.get_Location()
   at OpenQA.Selenium.Appium.AppiumElement.get_Rect()
   at UITest.Appium.AppiumGeneralActions.GetRect(IDictionary`2 parameters) in /_/src/TestUtils/src/UITest.Appium/Actions/AppiumGeneralActions.cs:line 51
   at UITest.Appium.AppiumGeneralActions.Execute(St
...
VerifyGroupIndexScrollToByIndexWithCenterPositionAndVerticalList_Potato
System.TimeoutException : Timed out waiting for element...
at UITest.Appium.HelperExtensions.Wait(Func`1 query, Func`2 satisfactory, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2761
   at UITest.Appium.HelperExtensions.WaitForAtLeastOne(Func`1 query, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2788
   at UITest.Appium.HelperExtensions.WaitForElement(IApp app, String marked, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency, Nullable`1 postTimeout) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 797
   at Microsoft.Maui.TestCases.Tests.CollectionView_ScrollingFeatureTests.VerifyGroupIndexScrollToByIndexWithCenterPositionAndVerticalList_Potato() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/FeatureMatrix/CollectionView_ScrollingFeatureTests.cs:line 1874
   at System.Refle
...
VerifyGroupIndexScrollToByIndexWithStartPositionAndVerticalList_Carrot
System.TimeoutException : Timed out waiting for element...
at UITest.Appium.HelperExtensions.Wait(Func`1 query, Func`2 satisfactory, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2761
   at UITest.Appium.HelperExtensions.WaitForAtLeastOne(Func`1 query, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2788
   at UITest.Appium.HelperExtensions.WaitForElement(IApp app, String marked, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency, Nullable`1 postTimeout) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 797
   at Microsoft.Maui.TestCases.Tests.CollectionView_ScrollingFeatureTests.VerifyGroupIndexScrollToByIndexWithStartPositionAndVerticalList_Carrot() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/FeatureMatrix/CollectionView_ScrollingFeatureTests.cs:line 1838
   at System.Runtim
...
VerifyGroupItemScrollToByIndexWithEndPositionAndHorizontalGrid_Potato
System.TimeoutException : Timed out waiting for element...
at UITest.Appium.HelperExtensions.Wait(Func`1 query, Func`2 satisfactory, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2761
   at UITest.Appium.HelperExtensions.WaitForAtLeastOne(Func`1 query, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2788
   at UITest.Appium.HelperExtensions.WaitForElement(IApp app, String marked, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency, Nullable`1 postTimeout) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 797
   at Microsoft.Maui.TestCases.Tests.CollectionView_ScrollingFeatureTests.VerifyGroupItemScrollToByIndexWithEndPositionAndHorizontalGrid_Potato() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/FeatureMatrix/CollectionView_ScrollingFeatureTests.cs:line 3597
   at System.Runtime
...
VerifyGroupIndexScrollToByIndexWithCenterPositionAndHorizontalList_Tomato
System.TimeoutException : Timed out waiting for element...
at UITest.Appium.HelperExtensions.Wait(Func`1 query, Func`2 satisfactory, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2761
   at UITest.Appium.HelperExtensions.WaitForAtLeastOne(Func`1 query, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2788
   at UITest.Appium.HelperExtensions.WaitForElement(IApp app, String marked, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency, Nullable`1 postTimeout) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 797
   at Microsoft.Maui.TestCases.Tests.CollectionView_ScrollingFeatureTests.VerifyGroupIndexScrollToByIndexWithCenterPositionAndHorizontalList_Tomato() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/FeatureMatrix/CollectionView_ScrollingFeatureTests.cs:line 3026
   at System.Ref
...
VerifyGroupItemScrollToByItemWithMakeVisiblePositionAndVerticalList_Apricot
System.TimeoutException : Timed out waiting for element...
at UITest.Appium.HelperExtensions.Wait(Func`1 query, Func`2 satisfactory, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2761
   at UITest.Appium.HelperExtensions.WaitForAtLeastOne(Func`1 query, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2788
   at UITest.Appium.HelperExtensions.WaitForElement(IApp app, String marked, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency, Nullable`1 postTimeout) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 797
   at Microsoft.Maui.TestCases.Tests.CollectionView_ScrollingFeatureTests.VerifyGroupItemScrollToByItemWithMakeVisiblePositionAndVerticalList_Apricot() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/FeatureMatrix/CollectionView_ScrollingFeatureTests.cs:line 1943
   at System.R
...
VerifyGroupItemScrollToByItemWithCenterPositionAndVerticalList_Potato
System.TimeoutException : Timed out waiting for element...
at UITest.Appium.HelperExtensions.Wait(Func`1 query, Func`2 satisfactory, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2761
   at UITest.Appium.HelperExtensions.WaitForAtLeastOne(Func`1 query, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2788
   at UITest.Appium.HelperExtensions.WaitForElement(IApp app, String marked, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency, Nullable`1 postTimeout) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 797
   at Microsoft.Maui.TestCases.Tests.CollectionView_ScrollingFeatureTests.VerifyGroupItemScrollToByItemWithCenterPositionAndVerticalList_Potato() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/FeatureMatrix/CollectionView_ScrollingFeatureTests.cs:line 2007
   at System.Runtime
...
VerifyGroupItemScrollToByIndexWithMakeVisiblePositionAndHorizontalList_Kiwi
System.TimeoutException : Timed out waiting for element...
at UITest.Appium.HelperExtensions.Wait(Func`1 query, Func`2 satisfactory, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2761
   at UITest.Appium.HelperExtensions.WaitForAtLeastOne(Func`1 query, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2788
   at UITest.Appium.HelperExtensions.WaitForElement(IApp app, String marked, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency, Nullable`1 postTimeout) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 797
   at Microsoft.Maui.TestCases.Tests.CollectionView_ScrollingFeatureTests.VerifyGroupItemScrollToByIndexWithMakeVisiblePositionAndHorizontalList_Kiwi() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/FeatureMatrix/CollectionView_ScrollingFeatureTests.cs:line 3241
   at System.R
...
VerifyScrollToByItemWithEndPositionAndHorizontalList_Kiwi
System.TimeoutException : Timed out waiting for element...
at UITest.Appium.HelperExtensions.Wait(Func`1 query, Func`2 satisfactory, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2761
   at UITest.Appium.HelperExtensions.WaitForAtLeastOne(Func`1 query, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2788
   at UITest.Appium.HelperExtensions.WaitForElement(IApp app, String marked, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency, Nullable`1 postTimeout) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 797
   at Microsoft.Maui.TestCases.Tests.CollectionView_ScrollingFeatureTests.VerifyScrollToByItemWithEndPositionAndHorizontalList_Kiwi() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/FeatureMatrix/CollectionView_ScrollingFeatureTests.cs:line 2715
   at System.RuntimeMethodHandle
...
VerifyGroupIndexScrollToByIndexWithMakeVisiblePositionAndVerticalList_Apricot
System.TimeoutException : Timed out waiting for element...
at UITest.Appium.HelperExtensions.Wait(Func`1 query, Func`2 satisfactory, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2761
   at UITest.Appium.HelperExtensions.WaitForAtLeastOne(Func`1 query, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2788
   at UITest.Appium.HelperExtensions.WaitForElement(IApp app, String marked, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency, Nullable`1 postTimeout) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 797
   at Microsoft.Maui.TestCases.Tests.CollectionView_ScrollingFeatureTests.VerifyGroupIndexScrollToByIndexWithMakeVisiblePositionAndVerticalList_Apricot() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/FeatureMatrix/CollectionView_ScrollingFeatureTests.cs:line 1802
   at System
...
VerifyGroupIndexScrollToByIndexWithEndPositionAndHorizontalList_Kiwi
System.TimeoutException : Timed out waiting for element...
at UITest.Appium.HelperExtensions.Wait(Func`1 query, Func`2 satisfactory, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2761
   at UITest.Appium.HelperExtensions.WaitForAtLeastOne(Func`1 query, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2788
   at UITest.Appium.HelperExtensions.WaitForElement(IApp app, String marked, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency, Nullable`1 postTimeout) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 797
   at Microsoft.Maui.TestCases.Tests.CollectionView_ScrollingFeatureTests.VerifyGroupIndexScrollToByIndexWithEndPositionAndHorizontalList_Kiwi() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/FeatureMatrix/CollectionView_ScrollingFeatureTests.cs:line 3134
   at System.Reflecti
...
VerifyScrollToByIndexWithStartPositionAndHorizontalList_Kiwi
System.TimeoutException : Timed out waiting for element...
at UITest.Appium.HelperExtensions.Wait(Func`1 query, Func`2 satisfactory, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2761
   at UITest.Appium.HelperExtensions.WaitForAtLeastOne(Func`1 query, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2788
   at UITest.Appium.HelperExtensions.WaitForElement(IApp app, String marked, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency, Nullable`1 postTimeout) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 797
   at Microsoft.Maui.TestCases.Tests.CollectionView_ScrollingFeatureTests.VerifyScrollToByIndexWithStartPositionAndHorizontalList_Kiwi() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/FeatureMatrix/CollectionView_ScrollingFeatureTests.cs:line 2214
   at System.RuntimeMethodHan
...
⚠️ Material3 — 318 new snapshot tests need a baseline PNG

These tests call VerifyScreenshot but their baseline image isn't committed yet (brand-new snapshot tests get their baseline added separately by a maintainer). There's nothing to compare against, so this is not a regression — download the drop-deep-uitests artifact, confirm the rendering, and commit the baseline PNG.

  • Material3DatePicker_SetFontAttributesAndFormat_f_VerifyVisualState
  • VerifyMaterial3Button_SetShadowAndText
  • Material3Slider_SetMinTrackAndMaxTrackColor_VerifyVisualState
  • Material3Slider_ChangeThumbColor_VerifyVisualState
  • VerifyMaterial3ImageButtonAspect_AspectFitWithImageSourceFromFile
  • SearchBar_Material3_SetPlaceholderAndVerticalTextAlignment_VerifyVisualState
  • Material3Label_VerifyLabelWithTextAndLineBreakModeMiddleTruncation
  • SearchBar_Material3_InitialState_VerifyVisualState
  • Material3Label_VerifyLabelWithTextAndCharacterSpacing
  • VerifyMaterial3Button_SetPaddingAndText
  • Material3RadioButton_FlowDirectionAndContent_VerifyVisualState
  • SearchBar_Material3_SetCancelButtonAndTextColor_VerifyVisualState
  • VerifyMaterial3ImageButtonWithBorderColor
  • VerifyMaterial3Button_SetLineBreakModeHeadTruncation
  • VerifyMaterial3ImageAspect_CenterWithFontImageSource
  • Material3Label_VerifyLabelWithFormattedTextWhenLineBreakModeTailTruncation
  • VerifyMaterial3ImageAspect_CenterWithStreamSource
  • Material3DatePicker_SetDateAndIsVisible_VerifyVisualState
  • VerifyMaterial3Button_SetBorderWidthAndLineBreakMode
  • Material3RadioButton_Checking_Default_Configuration_VerifyVisualState
  • Material3Editor_VerifyEditorTextWhenCharacterSpacingSetValues
  • Material3Slider_SetIsEnableAndMaxTrackColor_VerifyVisualState
  • Material3ProgressBar_ProgressToMethod_VerifyVisualState
  • Material3Editor_VerifyEditorControlWhenPlaceholderTextSet
  • SearchBar_Material3_SetFontAttributesAndFontFamily_VerifyVisualState
  • Material3Label_VerifyLabelWithTextTypeAndLineBreakModeNoWrap
  • Material3Switch_SetToggledAndOnColor_VerifyVisualState
  • Material3Entry_TextColor_VerifyVisualState
  • VerifyMaterial3ImageAspect_FillWithFontImageSource
  • Material3Entry_FontAttributes_VerifyVisualState
    (+288 more — see TRX in artifact)

📎 Download drop-deep-uitests artifact (TRX + snapshot diffs)


📋 Pre-Flight — Context & Validation

Issue: #35637 - [Android] Implement material3 support for CarouselView
PR: #35640 - [Android] Implemented material3 support for CarouselView
Platforms Affected: Android Material3
Files Changed: 10 implementation/instruction/API, 1 test

Key Findings

  • The PR adds a Material3 Android CarouselView handler using CarouselLayoutManager and MaskableFrameLayout wrappers to avoid the startup/layout hang from the legacy looped adapter scale.
  • The already-completed gate failed on Android Material3 UI tests: swipe to item 2 renders item 2, but CurrentItem and PreviousItem labels remain at item 1 / no previous item.
  • The likely failing seam is CarouselViewOnScrollListener2.GetVisibleItemsIndex: it can render the snapped item without sending a scrolled event whose CenterItemIndex maps to that item.
  • The PR also intentionally disables or no-ops Loop, PeekAreaInsets, ItemSpacing, and visual states for the Material3 handler, which remains a broader product/API decision.

Code Review Summary

Verdict: NEEDS_CHANGES
Confidence: low
Errors: 2 | Warnings: 1 | Suggestions: 0

Key code review findings:

  • ✗ Android Material3 CarouselView silently loses default Loop=true behavior because MauiCarouselRecyclerView2.IsLoopEnabled is forced false and CarouselViewAdapter2.ItemCount exposes the real count.
  • ✗ Android Material3 swipe does not update CurrentItem / previous-item state in CI; the new scroll listener does not publish the snapped item after gesture completion.
  • PeekAreaInsets, ItemSpacing, and per-item visual state behavior become documented no-ops under the default Material3 handler.

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #35640 Add Android Material3 CarouselView handler with real item count, MaskableFrameLayout holders, Material snap helper, and documented unsupported features. ❌ FAILED (Gate) Items2/Android/*, handler registration, tests Gate failed current/previous item propagation after swipe.

🔬 Code Review — Deep Analysis

Code Review — PR #35640

Independent Assessment

What this changes: Adds an Android Material3 CarouselViewHandler2 using CarouselLayoutManager, wraps items in MaskableFrameLayout, routes Android Material3 CarouselView to the new handler, and disables/omits several existing CarouselView behaviors (Loop, PeekAreaInsets, ItemSpacing, visual states/VisibleViews).

Inferred motivation: Fix Android Material3 CarouselView startup/layout hangs caused by using the existing looped adapter scale with Material's carousel layout manager.

Reconciliation with PR Narrative

Author claims: The PR intentionally supports only FullScreenCarouselStrategy; Loop, PeekAreaInsets, ItemSpacing, and per-item visual states are documented as unsupported limitations.

Agreement/disagreement: The code matches the narrative, but the limitation is introduced behind the default Android Material3 handler registration. That silently changes existing public CarouselView behavior for apps that did not opt into losing those features.

Prior Review Reconciliation

Prior ❌ Error Finding Source Status Evidence
Material3 handler disables/default-ignores CarouselView.Loop MauiBot inline reviews + expert reviewer ❌ Unresolved CarouselView.Loop defaults true; Android Material3 registers CarouselViewHandler2; MauiCarouselRecyclerView2.IsLoopEnabled => false; CarouselViewAdapter2.ItemCount returns real count.
PeekAreaInsets no-op / unsupported MauiBot inline reviews ❌ Unresolved / intentionally documented MapPeekAreaInsets remains empty.
ItemSpacing no-op / unsupported MauiBot inline reviews ❌ Unresolved / intentionally documented CreateSpacingDecoration returns NoOpItemDecoration.
Current/previous item state not updated after swipe Current CI + prior related comments ❌ Unresolved Current Android Material3 UI tests fail after ScrollRight: CurrentItemLabel remains Item 1; PreviousItemLabel remains No previous item.
Raw string items crash due unwrapped TextView MauiBot inline reviews ✅ Fixed MaskableTextItemViewHolder now wraps text content in MaskableFrameLayout.

Blast Radius Assessment

  • Runs for all instances: Yes — AppHostBuilderExtensions registers CarouselViewHandler2 for every Android Material3 CarouselView.
  • Startup impact: Yes — handler registration and carousel measurement/layout run during page initialization.
  • Static/shared state: No new global mutable state found, but public handler registration affects all Material3 apps.

External Output Contract

Consumer token/pattern Producer location Producer emission condition Consumer assumption Ordinary negative case Downstream effect
N/A N/A No changed code classifies external tool output by regex/string literal. N/A N/A N/A

CI Status

  • Required-check result: fail / unable to use gh pr checks because gh is unauthenticated; public GitHub Checks API shows Android Material3 UI failures on head c7a66fe.
  • Classification: PR-caused failure ❌ for Android Material3 UI tests. Material3VerifyCarouselViewWithCurrentItems and Material3VerifyCarouselViewWithPreviousItem fail after swipe.
  • Action taken: Used prior gate evidence supplied by the caller and public PR context; did not re-run the separate gate phase.

Findings

❌ Error — Default looping behavior is silently removed for Android Material3 CarouselView

src/Controls/src/Core/Hosting/AppHostBuilderExtensions.cs registers CarouselViewHandler2 for all Android Material3 CarouselViews, while MauiCarouselRecyclerView2.IsLoopEnabled => false and CarouselViewAdapter2.ItemCount exposes only the real item count. Since CarouselView.Loop defaults to true, existing apps stop wrapping at the ends simply by running with Material3 enabled.

❌ Error — Swipe does not update CurrentItem / previous-item state in current CI

The current Android Material3 UI run fails the PR's own carousel tests after a swipe: Material3VerifyCarouselViewWithCurrentItems leaves CurrentItemLabel at Item 1, and Material3VerifyCarouselViewWithPreviousItem leaves PreviousItemLabel at No previous item. This points at the new scroll/current-item propagation path (CarouselViewOnScrollListener2.GetVisibleItemsIndex) not publishing the snapped item after gesture completion.

⚠️ Warning — Several public CarouselView features become no-ops under the default Material3 handler

MapPeekAreaInsets is empty, CreateSpacingDecoration returns a no-op, and the handler explicitly does not drive visual states/VisibleViews. These may be conscious FullScreenCarouselStrategy tradeoffs, but because the handler is globally registered for Material3 CarouselView, existing apps using these public properties receive no runtime signal that the properties no longer work.

Failure-Mode Probing

  • Default Loop=true with multiple items: Material3 handler ignores looping; user reaches the last item and cannot wrap.
  • Swipe from item 1 to item 2: CI shows labels stay on item 1 / no previous item, so state propagation is broken.
  • Empty collection: code switches to LinearLayoutManager; this appears addressed.
  • Handler disconnect/reconnect: snap helper is detached in Dispose and TearDownOldElement.
  • Runtime property changes: PeekAreaInsets and spacing updates are deliberate no-ops; behavior requires human/API decision.

Verdict: NEEDS_CHANGES

Confidence: low
Summary: The code introduces a broad Android Material3 handler replacement with public behavior regressions, and current CI has PR-relevant Android Material3 CarouselView failures. The loop/default behavior regression and failing current-item propagation should be resolved before merge.


🛠️ Fix — Analysis & Comparison

Fix Candidates

# Source Approach Test Result Files Changed Notes
1 try-fix Publish Material snap target directly on scroll idle from CarouselViewOnScrollListener2. ❌ FAIL 1 file Test invocation failed before original assertion; approach also introduced a risky second state-publication path.
2 try-fix Update CurrentItem from the existing shared Android CarouselViewScrolled path after Position is updated. ✅ PASS 1 file Passed targeted Android Material3 CarouselView setup + current/previous item tests.
PR PR #35640 Add Material3 handler with real item count, Material snap helper, and MaskableFrameLayout item wrappers. ❌ FAILED (Gate) Multiple files Original PR fixes startup/layout hang but gate failed current/previous item propagation after swipe.

Cross-Pollination

Model Round New Ideas? Details
maui-expert-reviewer 1 Yes Code review identified the failing seam as scroll/current-item propagation, not item rendering.
try-fix-1 failure 1 Yes Avoid direct idle-time property publication; use existing scroll event pipeline.
try-fix-2 1 No Passing candidate found; no further materially different candidate needed for the gate failure.

Exhausted: No — stopped because Candidate #2 passed all targeted regression tests and is demonstrably better than the PR's current fix for the failed gate.
Selected Fix: Candidate #2 — it fixes current/previous item propagation through the shared Android carousel state path with a one-line implementation change and no Material-specific lifecycle callback.


📝 Recommended PR Title & Description

Assessment: ✏️ Recommend updating — the current title is close but not in the preferred component/title form, and the description should include the winning current-item propagation fix while preserving the detailed Material3 limitations.

Recommended title

[Android] CarouselView: Implement Material3 support

Recommended description

### Description of Change
This pull request introduces Material Design Carousel support for Android `CarouselView` under Material3. It adds a Material3-specific handler path built around Material's `CarouselLayoutManager` and `FullScreenCarouselStrategy`, wraps carousel item roots in `MaskableFrameLayout`, and adjusts the shared Android carousel state path so gesture scrolling updates both `Position` and `CurrentItem`.

**Material Carousel Support and Adapter Enhancements:**

* Added `CarouselViewAdapter2`, a new adapter for `MauiCarouselRecyclerView2`, which wraps each item in a `MaskableFrameLayout` to satisfy Material's `CarouselLayoutManager` requirements. This adapter also disables virtual looping, exposing the real item count to avoid performance issues and infinite layout loops with the Material carousel. (`src/Controls/src/Core/Handlers/Items2/Android/Adapters/CarouselViewAdapter2.cs`)
* Introduced `MaskableCarouselItemViewHolder`, a view holder that manages MAUI content inside a `MaskableFrameLayout`, ensuring correct handling of item templates and data binding for the Material carousel. (`src/Controls/src/Core/Handlers/Items2/Android/MaskableCarouselItemViewHolder.cs`)
* Added `MaskableTextItemViewHolder` so raw string items (a `CarouselView` bound to plain strings with no `ItemTemplate`) are also wrapped in a `MaskableFrameLayout`, since `CarouselLayoutManager` rejects direct RecyclerView children that are not `MaskableFrameLayout`.
* Added `CarouselViewOnScrollListener2`, a scroll listener tailored for `MauiCarouselRecyclerView2` that works directly with `CarouselLayoutManager` and does not depend on the legacy loop manager.
* Updated the shared Android carousel scrolled path to publish `CurrentItem` after `Position` changes, so Material3 gesture scrolling updates `CurrentItem` and previous-item state consistently.
* The Material handler renders the EmptyView using a plain `LinearLayoutManager` instead of Material's `CarouselLayoutManager`. `MauiCarouselRecyclerView2.SelectLayoutManager` returns a `LinearLayoutManager` whenever the active adapter is the `EmptyViewAdapter`, because Material's keyline mask would collapse a normally-sized EmptyView.

**Loop Logic Improvements:**

* Refactored loop logic in `MauiCarouselRecyclerView` by introducing the `IsLoopEnabled` property, allowing subclasses to override loop behavior. `MauiCarouselRecyclerView2` overrides this to disable the legacy virtual looping path because Material's `CarouselLayoutManager` does not support the `LoopScale` virtual-range model.

> [!IMPORTANT]
> The Material3 path is locked to `FullScreenCarouselStrategy` (one item masked to the full viewport, snapping one page at a time). The following `CarouselView` behaviors are intentionally not supported under this strategy and are documented in code:
>
> - **`Loop` is not supported.** Material's `CarouselLayoutManager` has no virtual-range model, so the legacy `LoopScale` trick used by the `LinearLayoutManager` path causes infinite measure/GC loops. Handler2 forces non-loop behavior (`IsLoopEnabled => false`) and exposes the real item count. Keep `CarouselView.Loop=\"False\"`.
> - **`PeekAreaInsets` is not supported.** `FullScreenCarouselStrategy` masks every item to fill the viewport, so there is no peek of adjacent items. The mapper is a documented no-op and item sizing deliberately ignores the insets.
> - **`LinearItemsLayout.ItemSpacing` is not honoured.** Material's `CarouselLayoutManager` has no spacing API and builds its `KeylineState` from the decorated measured size of the first child, so injecting spacing offsets would distort the keyline geometry.
> - **Per-item visual states / `VisibleViews` are not supported.** The inherited visual-state machinery depends on `LinearLayoutManager` and direct `ItemContentView` children; the Material handler uses `CarouselLayoutManager` with `MaskableFrameLayout` roots.

### Issues Fixed
Fixes #35637

### Platforms Tested
- [x] Android

🏁 Report — Final Recommendation

Comparative Report — PR #35640 STEP 5a Candidates

Candidate Ranking

Rank Candidate Regression result Assessment
1 try-fix-2 ✅ Passed targeted Android Material3 CurrentItem / PreviousItem tests Best candidate. It fixes the observed gate failure by adding SetCurrentItem(index) to the existing shared Android carousel scrolled pipeline after UpdatePosition(index), avoiding a second Material-specific state publication path.
2 pr-plus-reviewer Not independently re-run; analytically equivalent to try-fix-2 for the scroll-state finding Applying the expert reviewer's concrete feedback yields the same one-line current-item propagation fix as try-fix-2. It remains ranked below try-fix-2 because STEP 5a provides direct pass evidence for try-fix-2, while the sandbox candidate was not separately executed.
3 pr ❌ Failed supplied gate / pre-flight evidence The raw PR fixes the Material3 startup/layout hang and wraps Material carousel children correctly, but gesture scrolling does not update CurrentItem / previous-item state.
4 try-fix-1 ❌ Failed Adds a direct idle-time state publication path in CarouselViewOnScrollListener2; test execution failed before reaching the original assertion and the approach is lifecycle-riskier than reusing the shared scrolled pipeline.

Candidate Details

pr

The submitted PR introduces the core Material3 CarouselView implementation: CarouselViewHandler2, MauiCarouselRecyclerView2, CarouselViewAdapter2, MaskableCarouselItemViewHolder, MaskableTextItemViewHolder, a Material-specific scroll listener, global Android Material3 handler registration, EmptyView layout-manager switching, and Material3 UI coverage.

It is not sufficient as submitted. The forced non-loop path in MauiCarouselRecyclerView.CarouselViewScrolled updates Position but not CurrentItem, so Android Material3 swipe tests render the next item while labels bound to CurrentItem / previous item remain stale. The raw PR also leaves the broader Loop=true compatibility issue unresolved.

pr-plus-reviewer

The expert reviewer produced two major inline findings in inline-findings.json:

  1. Publish CurrentItem from the existing scroll pipeline after the non-loop Material3 path updates Position.
  2. Resolve or explicitly reconsider the global removal of default Loop=true behavior for Android Material3 CarouselView.

The sandbox-applied concrete fix for finding 1 is the same as try-fix-2:

diff --git a/src/Controls/src/Core/Handlers/Items/Android/MauiCarouselRecyclerView.cs b/src/Controls/src/Core/Handlers/Items/Android/MauiCarouselRecyclerView.cs
index 86a3811d81..acabced811 100644
--- a/src/Controls/src/Core/Handlers/Items/Android/MauiCarouselRecyclerView.cs
+++ b/src/Controls/src/Core/Handlers/Items/Android/MauiCarouselRecyclerView.cs
@@ -557,6 +557,7 @@ namespace Microsoft.Maui.Controls.Handlers.Items
 				return;
 
 			UpdatePosition(index);
+			SetCurrentItem(index);
 			UpdateVisualStates();
 		}

The loop finding is not safely fixable by re-enabling the legacy virtual range, because that would reintroduce the Material CarouselLayoutManager hang. It needs a separate design or an explicit product decision. Therefore pr-plus-reviewer is a valid improvement over pr for the failed gate, but it is not stronger than the empirically passing try-fix-2.

try-fix-1

try-fix-1 attempted to publish Position and CurrentItem directly from CarouselViewOnScrollListener2.OnScrollStateChanged when RecyclerView becomes idle. It failed the targeted invocation before reaching the original assertion and introduced a second state-publication path that can fire during setup or lifecycle transitions. It should not be selected.

try-fix-2

try-fix-2 updates MauiCarouselRecyclerView.CarouselViewScrolled to call the existing SetCurrentItem(index) helper immediately after UpdatePosition(index). This is the smallest fix for the actual failed seam: the scroll listener already computes the visible center index and the base carousel code already owns the cross-platform Position/CurrentItem state propagation. STEP 5a reports the targeted Android Material3 setup/current/previous-item tests passed with this change.

Winning Candidate

Winner: try-fix-2.

try-fix-2 is the only candidate with direct passing regression evidence, fixes the raw PR's observed gate failure, and does so through existing Android CarouselView state propagation rather than adding a Material-specific idle callback. It does not resolve the broader Loop=true compatibility concern, but every viable candidate that preserves the Material3 implementation shares that limitation; the passed regression fix is still required before the PR can proceed.


🧭 Next Steps — alternative fix proposed (try-fix-2)

Automated review — alternative fix proposed

The expert-reviewer evaluation compared the PR fix against automatically generated candidates and selected try-fix-2 as the strongest fix.

Why: try-fix-2 wins because it is the only candidate with direct passing Android Material3 regression evidence and it fixes the raw PR's missing CurrentItem/PreviousItem propagation through the existing shared CarouselView scrolled pipeline. The broader Loop=true compatibility concern remains unresolved, but the raw PR and try-fix-1 both failed the relevant regression path.

Please consider applying the candidate diff below (or use it as guidance). Once you push an update, this workflow will re-trigger and re-evaluate.

Candidate diff (try-fix-2)
diff --git a/src/Controls/src/Core/Handlers/Items/Android/MauiCarouselRecyclerView.cs b/src/Controls/src/Core/Handlers/Items/Android/MauiCarouselRecyclerView.cs
index 86a3811d81..acabced811 100644
--- a/src/Controls/src/Core/Handlers/Items/Android/MauiCarouselRecyclerView.cs
+++ b/src/Controls/src/Core/Handlers/Items/Android/MauiCarouselRecyclerView.cs
@@ -557,6 +557,7 @@ namespace Microsoft.Maui.Controls.Handlers.Items
 				return;
 
 			UpdatePosition(index);
+			SetCurrentItem(index);
 			UpdateVisualStates();
 		}

@Dhivya-SF4094

Copy link
Copy Markdown
Contributor Author

#35640 (review)

Reviewed the AI summary and confirmed that the reported concerns are not valid.

@kubaflo kubaflo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can we merge it?

@sheiksyedm

sheiksyedm commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Can we merge it?

@kubaflo We can hold this for now. We need to discuss the Material Carousel behavior further, as the new Material implementation will not support some existing MAUI APIs that users may expect to work.

Please hold off on merging this PR until we confirm the behavior.

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

Labels

area-controls-collectionview CollectionView, CarouselView, IndicatorView do-not-merge Don't merge this PR material3 partner/syncfusion Issues / PR's with Syncfusion collaboration platform/android s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-fix-win AI found a better alternative fix than the PR s/agent-gate-failed AI could not verify tests catch the bug s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Android] Implement material3 support for CarouselView

7 participants