Skip to content

Fix CollectionView.Header is header is not scrollable in Android platform#31661

Draft
SuthiYuvaraj wants to merge 11 commits into
dotnet:mainfrom
SuthiYuvaraj:fix-22120
Draft

Fix CollectionView.Header is header is not scrollable in Android platform#31661
SuthiYuvaraj wants to merge 11 commits into
dotnet:mainfrom
SuthiYuvaraj:fix-22120

Conversation

@SuthiYuvaraj

Copy link
Copy Markdown
Contributor

Note

Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!

Issue Description:

CollectionView.Header content is not scrollable on Android platform when it contains scrollable content like ScrollView with ListView.

Root Cause:

When the scrollable content is loaded inside the Header of the collectionview , touch is not passed to the internal scrollable control , which is handled by the TemplatedContentView in CollectionView.

Fix Description:

I have included the Touch Events in ItemContentView to handle the touch when the content is scrollable inside the header/ footer , Remaining cases it will not affects the previous behavior

Issues Fixed

Fixes #22120

Tested the behaviour in the following platforms

  • Android
  • Windows
  • iOS
  • Mac

Output Screenshot

Before Issue Fix After Issue Fix
Before.mov
After.mov

@dotnet-policy-service dotnet-policy-service Bot added the community ✨ Community Contribution label Sep 17, 2025
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Hey there @@SuthiYuvaraj! Thank you so much for your PR! Someone from the team will get assigned to your PR shortly and we'll get it reviewed.

@dotnet-policy-service dotnet-policy-service Bot added the partner/syncfusion Issues / PR's with Syncfusion collaboration label Sep 17, 2025
@SuthiYuvaraj SuthiYuvaraj changed the title Fix 22120 Fix CollectionView.Header is header is not scrollable in Android platform Sep 17, 2025
@jsuarezruiz jsuarezruiz added the area-controls-collectionview CollectionView, CarouselView, IndicatorView label Sep 18, 2025
@jsuarezruiz

Copy link
Copy Markdown
Contributor

/azp run MAUI-UITests-public

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@jsuarezruiz

Copy link
Copy Markdown
Contributor

/rebase

@jsuarezruiz jsuarezruiz 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.

@SuthiYuvaraj Could you rebase to fix the conflict?

@rmarinho

rmarinho commented Feb 18, 2026

Copy link
Copy Markdown
Member

🤖 AI Summary

📊 Expand Full Review
🔍 Pre-Flight — Context & Validation
📝 Review SessionCreate problems-report.html · 05a9003

Issue: #22120 - CollectionView.Header is not scrollable in Android platform
PR: #31661 - Fix CollectionView.Header is header is not scrollable in Android platform
Platforms Affected: Android only
PR Status: DRAFT
Files Changed: 2 implementation files, 2 test files

Issue Summary

On Android, when CollectionView.Header contains scrollable content (e.g., a ScrollView wrapping a ListView), touch events are not passed to the inner scrollable control. The RecyclerView intercepts all touch events, preventing the header's ScrollView from scrolling.

Fix Approach

Override DispatchTouchEvent and OnInterceptTouchEvent in ItemContentView (Android-specific ViewGroup). On MotionEventActions.Down for header/footer content, call Parent?.RequestDisallowInterceptTouchEvent(true) to prevent the parent RecyclerView from intercepting touch events. On Up/Cancel events, reset with RequestDisallowInterceptTouchEvent(false).

Files Changed

  • Fix files:
    • src/Controls/src/Core/Handlers/Items/Android/ItemContentView.cs (+71)
    • src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt (+2)
  • Test files:
    • src/Controls/tests/TestCases.HostApp/Issues/Issue22120.cs (+86, added)
    • src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue22120.cs (+27, added)

PR Discussion

  • MAUI team member (jsuarezruiz) triggered UI tests and requested a rebase
  • No inline review comments
  • No reviewer rejections

Disagreements / Edge Cases

File:Line Concern Notes
ItemContentView.cs IsHeaderOrFooterContent() called on every touch event (performance) Traverses logical parent tree on each touch
ItemContentView.cs RequestDisallowInterceptTouchEvent(true) applied to ALL header/footer content on DOWN, not just scrollable Could affect non-scrollable headers
ItemContentView.cs DispatchTouchEvent and OnInterceptTouchEvent become public API PublicAPI.Unshipped.txt updated, but are these appropriate as public API?
ItemContentView.cs FindParentItemsView() traverses MAUI logical parent chain May not work with HeaderTemplate

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #31661 Override DispatchTouchEvent/OnInterceptTouchEvent in ItemContentView to call RequestDisallowInterceptTouchEvent for header/footer content ⏳ PENDING (Gate) ItemContentView.cs (+71), PublicAPI.Unshipped.txt (+2) Original PR

🚦 Gate — Test Verification
📝 Review SessionCreate problems-report.html · 05a9003

Result: ✅ PASSED
Platform: android
Mode: Full Verification
Test Filter: Issue22120

  • Tests FAIL without fix ✅
  • Tests PASS with fix ✅

The tests correctly catch the bug (CollectionView.Header not scrollable in Android) and confirm the PR's fix resolves it.


🔧 Fix — Analysis & Comparison
📝 Review SessionCreate problems-report.html · 05a9003

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #31661 Override DispatchTouchEvent/OnInterceptTouchEvent in ItemContentView to call RequestDisallowInterceptTouchEvent for header/footer content ✅ PASS (Gate) ItemContentView.cs (+71), PublicAPI.Unshipped.txt (+2) Original PR

Exhausted: No (try-fix skipped due to rate limit errors on task agent - 429 Too Many Requests after 3 attempts)
Selected Fix: PR's fix - Gate confirmed tests pass. try-fix exploration blocked by environment rate limits.


📋 Report — Final Recommendation
📝 Review SessionCreate problems-report.html · 05a9003

⚠️ Final Recommendation: REQUEST CHANGES

Summary

PR #31661 fixes Android-specific issue where CollectionView.Header containing scrollable content (e.g. ScrollView with ListView) was not scrollable due to RecyclerView intercepting all touch events. The fix uses RequestDisallowInterceptTouchEvent, which is the correct Android mechanism for nested scrolling. Gate verified tests fail without the fix and pass with it. However, several issues need to be addressed before merging.

Root Cause

Android's RecyclerView intercepts all touch events (via onInterceptTouchEvent) to handle its own scrolling, preventing nested scrollable views inside the header from receiving touch events. The fix overrides OnInterceptTouchEvent and DispatchTouchEvent in ItemContentView to call Parent?.RequestDisallowInterceptTouchEvent(true) on DOWN events for header/footer content, temporarily disabling RecyclerView's touch interception.

Fix Quality

The core approach (RequestDisallowInterceptTouchEvent) is the standard Android pattern for nested scrolling and is technically correct. However:

Issues Found

1. Unused Import (code quality)

using AndroidX.RecyclerView.Widget;  // Added but never used

RecyclerView is imported but not referenced anywhere in the modified code. Should be removed.

2. HeaderTemplate Edge Case (functional limitation)
IsHeaderOrFooterContent() checks ReferenceEquals(View, structuredItemsView.Header). When HeaderTemplate is used instead of Header, structuredItemsView.Header returns null and the fix won't activate. This is an undocumented limitation that affects a common usage pattern. Should either be documented or handled.

3. Touch Event Logic Review
Setting RequestDisallowInterceptTouchEvent(true) unconditionally on DOWN for ALL header/footer content (not just when the content has scrollable children) is overly broad. A tap on a non-scrollable header button will also prevent RecyclerView from later receiving MOVE events until UP. While functionally correct (UP resets the flag), this is more aggressive than necessary and could potentially cause subtle interaction issues.

4. PR Is In DRAFT State
The PR is marked as draft. This may indicate the author is still working on it.

Test Coverage

Tests are well-structured:

  • Issue22120.cs (HostApp): Creates CollectionView with ScrollView header containing 15-item ListView
  • Issue22120.cs (SharedTests): Verifies scroll down and scroll up behavior with element visibility checks
  • Category: UITestCategories.CollectionView
  • Platform: PlatformAffected.Android

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #31661 Override DispatchTouchEvent/OnInterceptTouchEvent in ItemContentView to use RequestDisallowInterceptTouchEvent ✅ PASS (Gate) ItemContentView.cs (+71), PublicAPI.Unshipped.txt (+2) Original PR

try-fix: Skipped due to environment rate limit (429 errors). PR's fix is the only validated candidate.

Changes Requested

  1. Remove unused import using AndroidX.RecyclerView.Widget;
  2. Document or fix HeaderTemplate limitation - add a comment or extend to handle templated headers
  3. Mark PR as ready for review (remove draft status) when changes are complete

📋 Expand PR Finalization Review
Title: ✅ Good

Current: Fix CollectionView.Header is header is not scrollable in Android platform

Description: ⚠️ Needs Update
  • Grammatical error: "is header is" (double "is")
  • Missing platform prefix [Android]
  • Verbose phrasing

✨ Suggested PR Description

[!NOTE]
Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!

Root Cause

On Android, the RecyclerView that backs CollectionView intercepts all touch events to handle its own scrolling. When a scrollable control (e.g., ScrollView containing a ListView) is placed inside the CollectionView.Header or CollectionView.Footer, the RecyclerView consumes the touch events before they can reach the inner scrollable view, making the header/footer content unscrollable.

Description of Change

Added OnInterceptTouchEvent and DispatchTouchEvent overrides to ItemContentView (Android) to pass touch events through to scrollable header/footer content.

When the ItemContentView is rendering a header or footer (detected by comparing the logical view reference against StructuredItemsView.Header / StructuredItemsView.Footer):

  • OnInterceptTouchEvent (Down): Calls Parent.RequestDisallowInterceptTouchEvent(true) to prevent the parent RecyclerView from stealing touch events, then returns false so child views can handle the gesture.
  • DispatchTouchEvent (Up/Cancel): Calls Parent.RequestDisallowInterceptTouchEvent(false) to restore normal RecyclerView touch interception after the gesture ends.

This is the standard Android nested scrolling pattern. Regular CollectionView items are unaffected — the overrides are no-ops when IsHeaderOrFooterContent() returns false.

Note: This fix applies when Header/Footer is set directly as a View. If HeaderTemplate/FooterTemplate is used (DataTemplate), the fix does not apply because the ReferenceEquals check compares against the template object, not the inflated view.

Issues Fixed

Fixes #22120

Platforms Tested

  • Android
  • Windows
  • iOS
  • Mac
Code Review: ⚠️ Issues Found

Code Review – PR #31661

🔴 Critical Issues

Unused using Directives

File: src/Controls/src/Core/Handlers/Items/Android/ItemContentView.cs

Problem: The PR adds two using directives that are not referenced anywhere in the new or existing code:

using AndroidX.Core.Widget;       // unused
using AndroidX.RecyclerView.Widget; // unused

Neither NestedScrollView (from AndroidX.Core.Widget) nor RecyclerView (from AndroidX.RecyclerView.Widget) is referenced in the new logic. The IsHeaderOrFooterContent / FindParentItemsView methods work purely with MAUI logical types (IView, StructuredItemsView).

Recommendation: Remove both unused using directives before merge.


🟡 Suggestions

1. Fix Does Not Cover HeaderTemplate / FooterTemplate

File: src/Controls/src/Core/Handlers/Items/Android/ItemContentView.csIsHeaderOrFooterContent()

The ReferenceEquals check compares View (the MAUI virtual view) to structuredItemsView.Header:

return ReferenceEquals(View, structuredItemsView.Header) ||
       ReferenceEquals(View, structuredItemsView.Footer);

When Header / Footer is set directly as a View, this works correctly. However, when HeaderTemplate / FooterTemplate is used (a DataTemplate), structuredItemsView.Header holds the DataTemplate object, not the inflated view — so the check will always return false and the fix won't apply.

Recommendation: Either document this known limitation in a code comment and in the PR description, or extend the fix to handle the template case. At minimum, a // Note: Does not handle HeaderTemplate/FooterTemplate comment would prevent future confusion.

2. Extra Blank Line in DispatchTouchEvent

File: src/Controls/src/Core/Handlers/Items/Android/ItemContentView.cs

There is an extra blank line inside the outer if block:

public override bool DispatchTouchEvent(MotionEvent e)
{
    if (IsHeaderOrFooterContent())
    {
        // ← extra blank line here
        if (e.Action == MotionEventActions.Up || e.Action == MotionEventActions.Cancel)
        {

Recommendation: Remove the spurious blank line for consistency with the rest of the file's style.


✅ Looks Good

  • Core fix logic is correct: RequestDisallowInterceptTouchEvent(true) on MotionEventActions.Down / false on Up/Cancel is the standard Android pattern for nested scroll containers and is widely used in the Android ecosystem.
  • Regular items unaffected: IsHeaderOrFooterContent() returns false for non-header/footer ItemContentView instances, so existing RecyclerView item behavior is unchanged.
  • PublicAPI.Unshipped.txt updated: Both new public overrides (DispatchTouchEvent, OnInterceptTouchEvent) are correctly added to net-android/PublicAPI.Unshipped.txt.
  • UI test included: Issue22120.cs tests scroll-up and scroll-down on a ScrollView inside CollectionView.Header with proper AutomationId attributes. The test uses [Category(UITestCategories.CollectionView)] (single category, correct).
  • Logical tree traversal: FindParentItemsView() traverses the MAUI logical parent chain (not the Android view hierarchy), which is the correct approach for finding the owning StructuredItemsView.

@rmarinho rmarinho added s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-gate-passed AI verified tests catch the bug (fail without fix, pass with fix) 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 Feb 18, 2026
@kubaflo kubaflo added s/agent-fix-lose Author adopted the agent's fix and it turned out to be bad s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates and removed s/agent-fix-win AI found a better alternative fix than the PR s/agent-fix-lose Author adopted the agent's fix and it turned out to be bad labels Feb 20, 2026
@github-actions

github-actions Bot commented Apr 2, 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 -- 31661

Or

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

@dotnet dotnet deleted a comment from MauiBot May 3, 2026

@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 resolve conflicts?

@kubaflo

kubaflo commented May 24, 2026

Copy link
Copy Markdown
Contributor

/review -b feature/refactor-copilot-yml

@kubaflo

kubaflo commented May 30, 2026

Copy link
Copy Markdown
Contributor

/review -b feature/refactor-copilot-yml -p android

@MauiBot

This comment has been minimized.

@kubaflo

kubaflo commented May 31, 2026

Copy link
Copy Markdown
Contributor

/review -b feature/enhanced-reviewer

@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 — 2 findings

See inline comments for details.

if (itemsView is StructuredItemsView structuredItemsView)
{
// Check if our View is the same object reference as the header or footer
return ReferenceEquals(View, structuredItemsView.Header) ||

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.

[major] CollectionView Android - This only recognizes direct Header/Footer views. CreateHeaderFooterViewHolder also supports HeaderTemplate/FooterTemplate, where the realized View is created from the template and is not reference-equal to structuredItemsView.Header or .Footer, so templated scrollable headers/footers still allow the parent RecyclerView to steal the gesture. Consider tagging header/footer ItemContentViews when the adapter creates those holders instead of inferring it from the realized view reference.

{
if (ev.Action == MotionEventActions.Down)
{
Parent?.RequestDisallowInterceptTouchEvent(true);

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.

[major] Android Platform Specifics - Disallowing parent interception for the entire gesture means a drag that starts in a header/footer scroller cannot hand off to the outer CollectionView when the nested scroller is already at, or reaches, its top/bottom edge. The user-visible case is a scrollable header at its boundary: the same swipe should continue moving the collection, but the parent remains disallowed until Up/Cancel. Please scope this to actual scrollable-child handling, or release/re-evaluate once the nested target cannot scroll in the gesture direction.

@MauiBot MauiBot added s/agent-fix-win AI found a better alternative fix than the PR and removed s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates labels May 31, 2026
MauiBot

This comment was marked as outdated.

@kubaflo

kubaflo commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

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

@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

@SuthiYuvaraj — new AI review results are available based on this last commit: bd4a8d3.
Merge branch 'main' into fix-22120 To request a fresh review after new comments or commits, comment /review rerun.

Gate Passed Code Review In Review Confidence Medium Platform Android

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

Gate Result: ✅ PASSED

Platform: ANDROID · Base: main · Merge base: e904e900

Test Without Fix (expect FAIL) With Fix (expect PASS)
🖥️ Issue22120 Issue22120 ✅ FAIL — 794s ✅ PASS — 1320s
🔴 Without fix — 🖥️ Issue22120: FAIL ✅ · 794s
  Determining projects to restore...
  Restored /home/vsts/work/1/s/src/Controls/src/Core/Controls.Core.csproj (in 6.37 sec).
  Restored /home/vsts/work/1/s/src/Controls/Maps/src/Controls.Maps.csproj (in 6.31 sec).
  Restored /home/vsts/work/1/s/src/Controls/Foldable/src/Controls.Foldable.csproj (in 153 ms).
  Restored /home/vsts/work/1/s/src/Graphics/src/Graphics/Graphics.csproj (in 12 ms).
  Restored /home/vsts/work/1/s/src/Essentials/src/Essentials.csproj (in 24 ms).
  Restored /home/vsts/work/1/s/src/Core/src/Core.csproj (in 41 ms).
  Restored /home/vsts/work/1/s/src/Core/maps/src/Maps.csproj (in 26 ms).
  Restored /home/vsts/work/1/s/src/BlazorWebView/src/Maui/Microsoft.AspNetCore.Components.WebView.Maui.csproj (in 1.02 sec).
  Restored /home/vsts/work/1/s/src/Controls/src/Xaml/Controls.Xaml.csproj (in 33 ms).
  Restored /home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj (in 800 ms).
  1 of 11 projects are up-to-date for restore.
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0-android36.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0-android36.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  Core -> /home/vsts/work/1/s/artifacts/bin/Core/Debug/net10.0-android36.0/Microsoft.Maui.dll
  Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  Maps -> /home/vsts/work/1/s/artifacts/bin/Maps/Debug/net10.0-android36.0/Microsoft.Maui.Maps.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.Core/Debug/net10.0-android36.0/Microsoft.Maui.Controls.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  Microsoft.AspNetCore.Components.WebView.Maui -> /home/vsts/work/1/s/artifacts/bin/Microsoft.AspNetCore.Components.WebView.Maui/Debug/net10.0-android36.0/Microsoft.AspNetCore.Components.WebView.Maui.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  Controls.Xaml -> /home/vsts/work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Xaml.dll
  Controls.Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.Maps/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Maps.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  Controls.Foldable -> /home/vsts/work/1/s/artifacts/bin/Controls.Foldable/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Foldable.dll
  Controls.TestCases.HostApp -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Controls.TestCases.HostApp.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  Core -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.dll
  Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Maps.dll
  Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  Microsoft.AspNetCore.Components.WebView.Maui -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.AspNetCore.Components.WebView.Maui.dll
  Controls.Foldable -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Foldable.dll
  Controls.Xaml -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Xaml.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  Controls.Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Maps.dll

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:08:34.68
Broadcasting: Intent { act=android.intent.action.CLOSE_SYSTEM_DIALOGS flg=0x400000 }
Broadcast completed: result=0
  Determining projects to restore...
  Restored /home/vsts/work/1/s/src/TestUtils/src/VisualTestUtils/VisualTestUtils.csproj (in 1.02 sec).
  Restored /home/vsts/work/1/s/src/TestUtils/src/UITest.NUnit/UITest.NUnit.csproj (in 838 ms).
  Restored /home/vsts/work/1/s/src/TestUtils/src/UITest.Core/UITest.Core.csproj (in 6 ms).
  Restored /home/vsts/work/1/s/src/TestUtils/src/VisualTestUtils.MagickNet/VisualTestUtils.MagickNet.csproj (in 8.66 sec).
  Restored /home/vsts/work/1/s/src/Controls/tests/CustomAttributes/Controls.CustomAttributes.csproj (in 6 ms).
  Restored /home/vsts/work/1/s/src/TestUtils/src/UITest.Appium/UITest.Appium.csproj (in 10 ms).
  Restored /home/vsts/work/1/s/src/Controls/tests/TestCases.Android.Tests/Controls.TestCases.Android.Tests.csproj (in 6.78 sec).
  Restored /home/vsts/work/1/s/src/TestUtils/src/UITest.Analyzers/UITest.Analyzers.csproj (in 2.07 sec).
  5 of 13 projects are up-to-date for restore.
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  Controls.CustomAttributes -> /home/vsts/work/1/s/artifacts/bin/Controls.CustomAttributes/Debug/net10.0/Controls.CustomAttributes.dll
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  Core -> /home/vsts/work/1/s/artifacts/bin/Core/Debug/net10.0/Microsoft.Maui.dll
  Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
  UITest.Core -> /home/vsts/work/1/s/artifacts/bin/UITest.Core/Debug/net10.0/UITest.Core.dll
  UITest.Appium -> /home/vsts/work/1/s/artifacts/bin/UITest.Appium/Debug/net10.0/UITest.Appium.dll
  UITest.NUnit -> /home/vsts/work/1/s/artifacts/bin/UITest.NUnit/Debug/net10.0/UITest.NUnit.dll
  VisualTestUtils -> /home/vsts/work/1/s/artifacts/bin/VisualTestUtils/Debug/netstandard2.0/VisualTestUtils.dll
  VisualTestUtils.MagickNet -> /home/vsts/work/1/s/artifacts/bin/VisualTestUtils.MagickNet/Debug/netstandard2.0/VisualTestUtils.MagickNet.dll
  UITest.Analyzers -> /home/vsts/work/1/s/artifacts/bin/UITest.Analyzers/Debug/netstandard2.0/UITest.Analyzers.dll
  Controls.TestCases.Android.Tests -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll
Test run for /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (x64)

Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 10.0.0)
[xUnit.net 00:00:00.18]   Discovering: Controls.TestCases.Android.Tests
[xUnit.net 00:00:00.67]   Discovered:  Controls.TestCases.Android.Tests
NUnit Adapter 4.5.0.0: Test execution started
Running selected tests in /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll
   NUnit3TestExecutor discovered 1 of 1 NUnit test cases using Current Discovery mode, Non-Explicit run
>>>>> 06/06/2026 22:11:34 FixtureSetup for Issue22120(Android)
>>>>> 06/06/2026 22:11:35 CollectionViewHeaderScrollViewIsScrollable Start
>>>>> 06/06/2026 22:11:50 CollectionViewHeaderScrollViewIsScrollable Stop
>>>>> 06/06/2026 22:11:50 Log types: logcat, bugreport, server
  Failed CollectionViewHeaderScrollViewIsScrollable [16 s]
  Error Message:
   System.TimeoutException : Timed out waiting for element...
  Stack Trace:
     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 2757
   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 2784
   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 793
   at Microsoft.Maui.TestCases.Tests.Issues.Issue22120.CollectionViewHeaderScrollViewIsScrollable() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue22120.cs:line 20
   at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
   at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)

NUnit Adapter 4.5.0.0: Test execution complete
Results File: /home/vsts/work/1/s/CustomAgentLogsTmp/UITests/TestResults/Issue22120.trx

Total tests: 1
     Failed: 1
Test Run Failed.
 Total time: 1.8339 Minutes
>>> TRX_RESULT_FILE: /home/vsts/work/1/s/CustomAgentLogsTmp/UITests/TestResults/Issue22120.trx

🟢 With fix — 🖥️ Issue22120: PASS ✅ · 1320s

(truncated to last 15,000 chars)

rk/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010:    at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: --- End of stack trace from previous location --- [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010:    at AndroidDeviceExtensions.PushAndInstallPackageAsync(AndroidDevice device, PushAndInstallCommand command, CancellationToken token) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010:    at AndroidDeviceExtensions.PushAndInstallPackageAsync(AndroidDevice device, PushAndInstallCommand command, CancellationToken token) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010:    at Xamarin.Android.Tasks.FastDeploy.InstallPackage(Boolean installed) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010:    at Xamarin.Android.Tasks.FastDeploy.InstallPackage(Boolean installed) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010:    at Xamarin.Android.Tasks.FastDeploy.RunInstall() [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]

Build FAILED.

/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: Mono.AndroidTools.InstallFailedException: Unexpected install output: cmd: Failure calling service package: Broken pipe (32) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010:  [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010:    at Mono.AndroidTools.Internal.AdbOutputParsing.CheckInstallSuccess(String output, String packageName) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010:    at Mono.AndroidTools.AndroidDevice.<>c__DisplayClass105_0.<InstallPackage>b__0(Task`1 t) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010:    at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: --- End of stack trace from previous location --- [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010:    at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010:    at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: --- End of stack trace from previous location --- [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010:    at AndroidDeviceExtensions.PushAndInstallPackageAsync(AndroidDevice device, PushAndInstallCommand command, CancellationToken token) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010:    at AndroidDeviceExtensions.PushAndInstallPackageAsync(AndroidDevice device, PushAndInstallCommand command, CancellationToken token) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010:    at Xamarin.Android.Tasks.FastDeploy.InstallPackage(Boolean installed) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010:    at Xamarin.Android.Tasks.FastDeploy.InstallPackage(Boolean installed) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010:    at Xamarin.Android.Tasks.FastDeploy.RunInstall() [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
    0 Warning(s)
    1 Error(s)

Time Elapsed 00:11:07.97
* daemon not running; starting now at tcp:5037
* daemon started successfully
  Determining projects to restore...
  All projects are up-to-date for restore.
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0-android36.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0-android36.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  Core -> /home/vsts/work/1/s/artifacts/bin/Core/Debug/net10.0-android36.0/Microsoft.Maui.dll
  Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  Maps -> /home/vsts/work/1/s/artifacts/bin/Maps/Debug/net10.0-android36.0/Microsoft.Maui.Maps.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.Core/Debug/net10.0-android36.0/Microsoft.Maui.Controls.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  Controls.Foldable -> /home/vsts/work/1/s/artifacts/bin/Controls.Foldable/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Foldable.dll
  Microsoft.AspNetCore.Components.WebView.Maui -> /home/vsts/work/1/s/artifacts/bin/Microsoft.AspNetCore.Components.WebView.Maui/Debug/net10.0-android36.0/Microsoft.AspNetCore.Components.WebView.Maui.dll
  Controls.Xaml -> /home/vsts/work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Xaml.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  Controls.Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.Maps/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Maps.dll
  Controls.TestCases.HostApp -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Controls.TestCases.HostApp.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  Core -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.dll
  Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Maps.dll
  Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  Controls.Foldable -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Foldable.dll
  Microsoft.AspNetCore.Components.WebView.Maui -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.AspNetCore.Components.WebView.Maui.dll
  Controls.Xaml -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Xaml.dll
  Controls.Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Maps.dll

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:08:18.09
Broadcasting: Intent { act=android.intent.action.CLOSE_SYSTEM_DIALOGS flg=0x400000 }
Broadcast completed: result=0
  Determining projects to restore...
  All projects are up-to-date for restore.
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
  Controls.CustomAttributes -> /home/vsts/work/1/s/artifacts/bin/Controls.CustomAttributes/Debug/net10.0/Controls.CustomAttributes.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  Core -> /home/vsts/work/1/s/artifacts/bin/Core/Debug/net10.0/Microsoft.Maui.dll
  Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.80-ci+azdo.14304655
  Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
  UITest.Core -> /home/vsts/work/1/s/artifacts/bin/UITest.Core/Debug/net10.0/UITest.Core.dll
  VisualTestUtils -> /home/vsts/work/1/s/artifacts/bin/VisualTestUtils/Debug/netstandard2.0/VisualTestUtils.dll
  UITest.NUnit -> /home/vsts/work/1/s/artifacts/bin/UITest.NUnit/Debug/net10.0/UITest.NUnit.dll
  VisualTestUtils.MagickNet -> /home/vsts/work/1/s/artifacts/bin/VisualTestUtils.MagickNet/Debug/netstandard2.0/VisualTestUtils.MagickNet.dll
  UITest.Appium -> /home/vsts/work/1/s/artifacts/bin/UITest.Appium/Debug/net10.0/UITest.Appium.dll
  UITest.Analyzers -> /home/vsts/work/1/s/artifacts/bin/UITest.Analyzers/Debug/netstandard2.0/UITest.Analyzers.dll
  Controls.TestCases.Android.Tests -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll
Test run for /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (x64)

Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 10.0.0)
[xUnit.net 00:00:00.12]   Discovering: Controls.TestCases.Android.Tests
[xUnit.net 00:00:00.37]   Discovered:  Controls.TestCases.Android.Tests
NUnit Adapter 4.5.0.0: Test execution started
Running selected tests in /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll
   NUnit3TestExecutor discovered 1 of 1 NUnit test cases using Current Discovery mode, Non-Explicit run
>>>>> 06/06/2026 22:33:41 FixtureSetup for Issue22120(Android)
>>>>> 06/06/2026 22:33:41 CollectionViewHeaderScrollViewIsScrollable Start
>>>>> 06/06/2026 22:34:01 CollectionViewHeaderScrollViewIsScrollable Stop
  Passed CollectionViewHeaderScrollViewIsScrollable [19 s]
NUnit Adapter 4.5.0.0: Test execution complete
Results File: /home/vsts/work/1/s/CustomAgentLogsTmp/UITests/TestResults/Issue22120.trx

Test Run Successful.
Total tests: 1
     Passed: 1
 Total time: 38.2434 Seconds
>>> TRX_RESULT_FILE: /home/vsts/work/1/s/CustomAgentLogsTmp/UITests/TestResults/Issue22120.trx

📁 Fix files reverted (3 files)
  • eng/pipelines/ci-copilot.yml
  • src/Controls/src/Core/Handlers/Items/Android/ItemContentView.cs
  • src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt

UI Tests — CollectionView

Detected UI test categories: CollectionView


Pre-Flight — Context & Validation

Issue: #22120 - CollectionView.Header is not scrollable in Android platform
PR: #31661 - Android CollectionView header nested scrolling fix
Platforms Affected: Android
Files Changed: 2 implementation/API, 2 test (focused Android fix); broader checked-out branch also contains unrelated CI-agent files

Key Findings

  • Remote PR/issue metadata could not be fetched because gh is not authenticated; local checked-out PR branch and diff were used.
  • The PR fix adds touch interception overrides to ItemContentView and tests a direct Header = ScrollView case.
  • Supplied gate result: Gate ✅ PASSED — tests fail without the fix and pass with the PR fix. Gate was not re-run.
  • Expert review found the PR approach does not cover HeaderTemplate/FooterTemplate, traverses the MAUI logical tree on touch hot paths, and captures gestures that start on non-scrollable header/footer content.

Code Review Summary

Verdict: NEEDS_CHANGES
Confidence: medium
Errors: 1 | Warnings: 2 | Suggestions: 1

Key code review findings:

  • ItemContentView.IsHeaderOrFooterContent() only detects direct Header/Footer views; template-created header/footer views are not reference-equal to StructuredItemsView.Header/Footer.
  • ⚠️ Touch handling does repeated logical-parent traversal in DispatchTouchEvent and OnInterceptTouchEvent.
  • ⚠️ Parent intercept is disallowed for every header/footer DOWN, including non-scrollable header/footer content.
  • 💡 Prefer adapter item-type knowledge or an internal flag over public API-surfaced overrides and unused imports.

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #31661 ItemContentView detects direct header/footer views by walking MAUI logical parents and disallows parent intercept on DOWN ✅ PASSED (Gate) ItemContentView.cs, PublicAPI, UI test files Original PR; gate supplied by caller

Code Review — Deep Analysis

Code Review — PR #31661

Independent Assessment

What this changes: Adds Android touch-interception handling to ItemContentView so CollectionView header/footer content can receive nested scroll gestures, plus an Android UI test for a scrollable header.
Inferred motivation: A scrollable view placed in a CollectionView header cannot scroll because the parent RecyclerView intercepts the drag gesture.

Reconciliation with PR Narrative

Author claims: Remote PR narrative was unavailable because gh is not authenticated in this environment. Local issue/test names indicate the target bug is "CollectionView.Header is not scrollable in Android platform" (#22120).
Agreement/disagreement: The local diff addresses the direct Header = View case exercised by the test. Expert review found gaps for HeaderTemplate/FooterTemplate, hot-path tree walking, and overly broad gesture capture for non-scrollable header/footer content.

Findings

❌ Error — Template headers/footers are not covered

ItemContentView.IsHeaderOrFooterContent() compares the realized MAUI View with StructuredItemsView.Header/Footer. For HeaderTemplate/FooterTemplate, the realized View is the DataTemplate-created child while Header/Footer is the binding context object, so ReferenceEquals is false and the fix does not run for template-based headers/footers.

⚠️ Warning — Per-touch logical parent traversal in a hot path

DispatchTouchEvent and OnInterceptTouchEvent call IsHeaderOrFooterContent() for every event. Regular cells traverse the MAUI logical tree before returning false, adding repeated O(depth) work during touch/scroll paths.

⚠️ Warning — Header/footer gestures are captured even for non-scrollable content

Calling RequestDisallowInterceptTouchEvent(true) on every DOWN inside a header/footer prevents the RecyclerView from taking over a drag that starts on non-scrollable header/footer content.

💡 Suggestion — Remove unused imports/public API delta

The current implementation imports AndroidX namespaces that are not used and adds two public overrides to the Android public API list for behavior that could remain internal to existing handler classes.

Devil's Advocate

The direct-view header test passes with the PR fix according to the supplied gate result, and the Android pattern of disallowing parent intercept is established elsewhere (for example WebView). However, CollectionView header/footer creation has multiple adapter paths, and the current detection relies on MAUI logical parent identity rather than adapter knowledge, leaving real supported scenarios unhandled.

Verdict: NEEDS_CHANGES

Confidence: medium
Summary: The fix addresses the tested direct-header case but misses template-based header/footer content and adds hot-path overhead. Alternative candidates should move header/footer knowledge to adapter creation or RecyclerView interception, where the item type is authoritative.


Fix — Analysis & Comparison

Fix Candidates

# Source Approach Test Result Files Changed Notes
1 try-fix-1 Adapter-set ItemContentView.IsHeaderOrFooter flag; O(1) touch check; covers direct and templated header/footer creation paths ✅ PASS 4 files Better than PR for HeaderTemplate/FooterTemplate and hot-path cost; still broad for non-scrollable header content
2 try-fix-2 MauiRecyclerView decides interception by child adapter item type (Header/Footer) and tracks the gesture ✅ PASS 3 files Architecturally cleaner parent-layer fix; covers template/direct header/footer without ItemContentView API changes
PR PR #31661 ItemContentView walks MAUI logical parents on touch and compares realized view to StructuredItemsView.Header/Footer ✅ PASSED (Gate) 4 focused files Original PR; gate supplied by caller

Cross-Pollination

Model Round New Ideas? Details
maui-expert-reviewer 1 Yes Suggested adapter-set flag and RecyclerView item-type interception as materially different alternatives.
local loop 2 No After two passing, materially distinct alternatives, remaining ideas are broader framework nested-scrolling changes or minor variations of the same gesture policy.

Exhausted: Yes
Selected Fix: Candidate #2 — passes the targeted Android UI test, removes the PR's child-level logical-tree walk and ItemContentView public API additions, and uses the RecyclerView adapter item type as the authoritative header/footer signal. Candidate #1 is also viable and simpler if maintainers prefer localized ItemContentView changes.


Future Action — review latest findings

No alternative fix was selected for this run. Review the session findings and CI results before merging.

@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 the ai's suggestions?

@kubaflo

kubaflo commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

/review rerun

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 community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration s/agent-fix-win AI found a better alternative fix than the PR s/agent-gate-passed AI verified tests catch the bug (fail without fix, pass with fix) 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.

CollectionView.Header is header is not scrollable in Android platform.

6 participants