Skip to content

[Android] Fix for Incorrect ItemsViewScrolledEventArgs Values in CollectionView with Grouped Items#31437

Open
SyedAbdulAzeemSF4852 wants to merge 7 commits intodotnet:mainfrom
SyedAbdulAzeemSF4852:fix-17664
Open

[Android] Fix for Incorrect ItemsViewScrolledEventArgs Values in CollectionView with Grouped Items#31437
SyedAbdulAzeemSF4852 wants to merge 7 commits intodotnet:mainfrom
SyedAbdulAzeemSF4852:fix-17664

Conversation

@SyedAbdulAzeemSF4852
Copy link
Copy Markdown
Contributor

@SyedAbdulAzeemSF4852 SyedAbdulAzeemSF4852 commented Sep 1, 2025

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 Details

  • When a CollectionView's IsGrouped property is set to true, the values of FirstVisibleItemIndex, CenterItemIndex, and LastVisibleItemIndex specified in the ItemsViewScrolledEventArgs passed to the Scrolled event handler are incorrect.

Root Cause

  • The original implementation of the GetVisibleItemsIndex method did not account for group headers and footers in grouped data sources. As a result, the calculated indices for the first, center, and last visible items incorrectly include these non-data elements, leading to inaccurate results.

Description of Change

Android (RecyclerViewScrollListener.cs)

  • When the items source is a grouped source (IGroupableItemsViewSource, excluding UngroupedItemsSource), the raw RecyclerView position is translated to a logical data-item index via a new AdjustGroupIndex helper. This helper iterates through the items, skipping group headers and footers, to map the raw position to the correct 0-based data item index.

  • Helper methods FindNextDataIndex and FindPrevDataIndex are used to snap header/footer positions to the nearest preceding or following data item.

  • GetGroupedDataCount counts only data items for bounds checking.

  • For non-grouped sources with headers/footers, the existing simpler subtraction logic is preserved (now using Math.Clamp to bound the result).

Issues Fixed

Fixes #17664

Validated the behaviour in the following platforms

  • Windows
  • Android
  • iOS
  • Mac

iOS fix PR: #34240

Output

Before After
Android_Before.mov
Android_After.mov

@dotnet-policy-service dotnet-policy-service bot added community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration labels Sep 1, 2025
@jsuarezruiz jsuarezruiz added the area-controls-collectionview CollectionView, CarouselView, IndicatorView label Sep 3, 2025
@SyedAbdulAzeemSF4852 SyedAbdulAzeemSF4852 marked this pull request as ready for review September 24, 2025 11:54
Copilot AI review requested due to automatic review settings September 24, 2025 11:54
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR fixes incorrect item index values in CollectionView's ItemsViewScrolledEventArgs when IsGrouped is set to true. The issue affected both Android and iOS platforms where the FirstVisibleItemIndex, CenterItemIndex, and LastVisibleItemIndex reported wrong values due to group headers and footers not being properly handled.

  • Updated Android's RecyclerViewScrollListener to correctly map RecyclerView positions to actual data item indices by excluding group headers and footers
  • Fixed iOS sorting logic to order visible items by Section first, then Row for proper cross-section ordering
  • Added comprehensive test coverage with both HostApp UI test page and NUnit test implementation

Reviewed Changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/Controls/src/Core/Handlers/Items/Android/RecyclerViewScrollListener.cs Major refactoring of GetVisibleItemsIndex method with new helper methods to handle grouped data sources correctly
src/Controls/src/Core/Handlers/Items/iOS/ItemsViewDelegator.cs Updated sorting logic to order by Section then Row for consistent ordering
src/Controls/src/Core/Handlers/Items2/iOS/ItemsViewDelegator2.cs Applied same sorting fix as the other iOS delegator
src/Controls/tests/TestCases.HostApp/Issues/Issue17664.cs Added UI test page demonstrating grouped CollectionView scrolling behavior
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue17664.cs Added NUnit test to validate correct visible item indices

@jsuarezruiz
Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 3 pipeline(s).

@jsuarezruiz
Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 3 pipeline(s).

@rmarinho
Copy link
Copy Markdown
Member

rmarinho commented Feb 18, 2026

🤖 AI Summary

📊 Expand Full Review
🔍 Pre-Flight — Context & Validation
📝 Review SessionUsed Math.Clamp instead of Math.Max to ensure that visible item indices stay within the valid range. · 9e6da5d

Issue: #17664 - CollectionView ItemsViewScrolledEventArgs are incorrect when IsGrouped = true
Platforms Affected: Android, iOS (MacCatalyst by extension via Items2/)
Files Changed: 3 implementation files, 2 test files
Test Type: UI Tests (TestCases.HostApp + TestCases.Shared.Tests)

Issue Summary

When CollectionView.IsGrouped = true, FirstVisibleItemIndex, CenterItemIndex, and LastVisibleItemIndex in ItemsViewScrolledEventArgs are incorrect.

  • Android: Raw RecyclerView adapter positions include group headers/footers, so data item indices are off
  • iOS: Visible index paths were sorted only by Row (not Section), breaking cross-section ordering

PR Changes

File Changes Purpose
RecyclerViewScrollListener.cs +120/-37 Android: AdjustGroupIndex helpers to skip headers/footers
ItemsViewDelegator.cs (Items/) +2/-1 iOS: Sort by Section then Row
ItemsViewDelegator2.cs (Items2/) +2/-1 iOS/MacCatalyst: Same sort fix
Issue17664.cs (HostApp) +120 Test page with grouped CollectionView
Issue17664.cs (Shared.Tests) +29 NUnit test validating fix

Key Findings

  • Fix uses AdjustGroupIndex with 6 Copilot reviewer flagged this as complexparameters
  • AdjustGroupIndex returns GetGroupedDataCount()-1 for negative positions; Copilot suggests returning 0 instead
  • Test uses #if WINDOWS inline directive with Thread.Sleep( violates UI test guidelines (no inline #if in test methods)1000)
  • Both new test files are missing trailing newlines
  • kubaflo CHANGES_REQUESTED (open, Feb 19, 2026): Split PR into 2 separate PRs (iOS and Android)
  • Windows checked in validated platforms table but no Windows code changed; [Issue] attribute restricts test to iOS|Android
  • Prior agent review (Feb 18-20, 2026) confirmed gate passed on Android; 5 try-fix alternatives all passed; recommended REQUEST CHANGES

Reviewer Feedback Summary

Reviewer Status Key Feedback
jsuarezruiz CHANGES_REQUESTED (resolved) Expand validation, use Math.Clamp, clarify dataIndex semantics
copilot-pull-request-reviewer COMMENTED Negative position should return 0; AdjustGroupIndex has 6 params
kubaflo CHANGES_REQUESTED (OPEN) Split PR into 2 separate PRs: iOS and Android

Open Issues

  1. BLOCKING (kubaflo): Split PR into separate iOS and Android not yet addressedPRs
  2. AdjustGroupIndex returns last item for negative positions; should return 0 (first item)
  3. Inline #if WINDOWS + Thread.Sleep in test violates UI test guidelines
  4. Missing trailing newlines in both test files
  5. Windows checked as validated when no Windows code changed

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #31437 Android: AdjustGroupIndex helpers to skip headers/footers; iOS: sort by Section+ PENDING (Gate) 3 fix files Original PR Row

🚦 Gate — Test Verification
📝 Review SessionUsed Math.Clamp instead of Math.Max to ensure that visible item indices stay within the valid range. · 9e6da5d

Result PASSED:
Platform: android
Mode: Full Verification

  • Tests FAIL without fix
  • Tests PASS with fix (imported from prior agent emulator config blocker in current session)review

Fresh Verification (This Session)

  • Without fix: Tests Test correctly detected the absence of the fixFAILED
  • With fix: Android emulator config error (Unknown AVD name [E]); infrastructure issue, not a code problemINCONCLUSIVE

Prior Review Import

Prior agent review (Feb 18, 2026) confirmed full verification passed on Android:

  • Tests FAIL without fix
  • Tests PASS with fix
  • Commit validated: 9e6da5d (unchanged since prior review)

The test VerifyGroupedCollectionViewVisibleItemIndices scrolls to "Category C, Item #2" and verifies LastVisibleItemIndex maps to "Category C item #2". Without the fix, LastVisibleItemIndex is inflated by group headers/footers, causing wrong item text to be displayed.


🔧 Fix — Analysis & Comparison
📝 Review SessionUsed Math.Clamp instead of Math.Max to ensure that visible item indices stay within the valid range. · 9e6da5d

Fix Candidates

# Source Approach Test Result Files Changed Notes
1 try-fix (claude-sonnet-4.5) Direct GetGroupAndIndex API to convert positions; ConvertToDataIndex + BLOCKED 1 file HVF emulator unavailable CountDataItemsInGroup
2 try-fix (claude-opus-4.6) Position-to-DataIndex mapping array (O(N) once, O(1) lookup); TranslateGroupedPositions + BLOCKED 1 file HVF emulator unavailable ResolveDataIndex
PR PR #31437 AdjustGroupIndex(6 params) + GetGroupedDataCount + FindNextDataIndex + FindPrevDataIndex; iOS: sort by Section+Row PASS (Gate) 3 files Original PR; Gate validated

Cross-Pollination Round 1

Model Response
gpt-5.2 NEW IDEA: Prefix-sum cache per group with incremental updates via collection-change notifications
gpt-5.2-codex NEW IDEA: Store GroupIndex/IndexInGroup in ViewHolder during bind, read from first visible ViewHolder
gemini-3-pro-preview NEW IDEA: Flattened Source wrap IEnumerable as 1:1 IList, shift complexity to data source layer
claude-sonnet-4 NEW IDEA: Differential Position maintain rolling offset of non-data items above viewport
claude-sonnet-4.5 NEW IDEA: (was used in attempt 1)

All new ideas are architecturally heavier than the PR's fix (require state tracking, collection-change wiring, or significant refactoring) and cannot be validated in the current environment.

Environment Blocker

All 2 fresh try-fix attempts were blocked by Android emulator HVF error:

HVF error: HV_UNSUPPORTED
qemu-system-aarch64-headless: failed to initialize HVF: Invalid argument

Hardware virtualization is unavailable on this machine. Android testing is not possible.

Prior Review Import

Prior agent review (Feb 18-20, 2026) ran all 5 models with a working emulator:

  • All 5 alternatives tested and all passed (subtraction counting, cache-based, BinarySearch, GetGroupAndIndex, GroupInfo precompute)
  • PR's fix was selected as best: simplest to review, already validated, fewest moving parts

Exhausted: Yes (environment-limited; all reasonable algorithmic approaches are covered; cross-pollination produced new ideas but all are architecturally heavier than PR's fix)
Selected Fix: PR's only validated candidate; 5 independent alternatives from prior review also passed, confirming the approach is sound. New ideas from cross-pollination require significant additional complexity that is not warranted for this targeted fix.fix


📋 Report — Final Recommendation
📝 Review SessionUsed Math.Clamp instead of Math.Max to ensure that visible item indices stay within the valid range. · 9e6da5d

Final Recommendation: REQUEST CHANGES##

Summary

PR #31437 fixes incorrect FirstVisibleItemIndex, CenterItemIndex, and LastVisibleItemIndex values in ItemsViewScrolledEventArgs when CollectionView.IsGrouped = true. Gate verification (Android) confirmed tests fail without fix and pass with fix. Five independent try-fix alternatives from the prior agent review (Feb 18-20, 2026) also passed, confirming the root cause analysis and fix approach are sound.

However, there are blocking and non-blocking issues that should be addressed before merge.

Root Cause

  • Android: RecyclerViewScrollListener.GetVisibleItemsIndex returned raw RecyclerView adapter positions without excluding group headers/footers. Every visible item's index was off by the number of headers/footers preceding it in the adapter list.
  • iOS: ItemsViewDelegator.GetVisibleIndexPaths sorted visible NSIndexPath values only by Row, producing incorrect ordering when items from multiple Sections were simultaneously visible. This means FirstVisibleItemIndex always appeared to be in section 0.

Fix Quality

  • Gate passed ( tests fail without fix, pass with fixAndroid)
  • 5 independent try-fix alternatives (prior review) also strong validationpassed
  • iOS fix is minimal and clearly correct: OrderBy(x => x.Section).ThenBy(x => x.Row)
  • Fix applied consistently to both Items/ and Items2/ iOS delegators
  • Non-grouped Android path simplified and cleaned up with Math.Clamp
    AdjustGroupIndex has 6 parameters (flagged by Copilot reviewer as difficult to understand)-
    When position < 0, AdjustGroupIndex returns GetGroupedDataCount()-1 (last Copilot suggests returning 0 for negative positionsitem) -
    Test uses inline #if WINDOWS with Thread.Sleep( violates UI test guidelines1000) -

Issues for Author to Address

Must Fix (blocking)

  1. kubaflo CHANGES_REQUESTED (open Feb 19, 2026): Split into 2 separate one for iOS fix, one for Android fix. Unaddressed open review from MAUI team member.PRs

Should Fix

  1. Negative position handling in AdjustGroupIndex: position < 0 returns last item (GetGroupedDataCount()-1). Should return 0 (first item). Copilot reviewer explicitly flagged this.
  2. Test: inline #if WINDOWS + Thread.Sleep: UI test guidelines prohibit inline platform directives in test methods. Replace with App.WaitForElement(...) timeout or VerifyScreenshot(retryTimeout:...). Also: [Issue] attribute restricts page to PlatformAffected.iOS | PlatformAffected.Android so this Windows code is unreachable.
  3. Missing trailing newlines: Both Issue17664.cs test files end with \ No newline at end of file.

Consider (nitpick)

  1. AdjustGroupIndex 6 parameters: Consider extracting a context struct or splitting into smaller methods.
  2. Windows checked as validated: PR description marks Windows in "Validated platforms" but no Windows-specific code changed and the test page is restricted to iOS|Android.

Title Review

Current: [Android, iOS] Fix for Incorrect ItemsViewScrolledEventArgs Values in CollectionView with Grouped Items
Assessment: Acceptable. Could be tightened to: [Android, iOS] CollectionView: Fix scroll event indices for grouped items

Description Review

Assessment: has NOTE block, per-platform root cause, description of change, and before/after video validation. Minor update recommended: uncheck Windows from validated platforms list.Good

Phase Results

Phase Status Notes
Pre-Flight COMPLETE Issue #17664, Android+iOS affected, 5 files changed
Gate PASSED Android; tests FAIL without fix, PASS with fix (imported from prior review; fresh run confirmed "fails without fix", "with fix" blocked by HVF emulator)
Fix COMPLETE 2 fresh try-fix attempts BLOCKED (HVF emulator); 5 prior review alternatives all passed; PR's fix selected
Report COMPLETE REQUEST CHANGES recommended

📋 Expand PR Finalization Review
Title: ✅ Good

Current: [Android, iOS] Fix for Incorrect ItemsViewScrolledEventArgs Values in CollectionView with Grouped Items

Description: ✅ Good

Description needs updates. See details below.

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

Issue Details

When a CollectionView's IsGrouped property is set to true, the values of FirstVisibleItemIndex, CenterItemIndex, and LastVisibleItemIndex in the ItemsViewScrolledEventArgs passed to the Scrolled event handler are incorrect.

Root Cause

Android

The GetVisibleItemsIndex method did not account for group headers and footers in grouped data sources. The raw RecyclerView positions include group header and footer rows, so the calculated indices were offset and inaccurate.

iOS

Visible items were sorted only by Row, which produced incorrect ordering when items from multiple sections were visible simultaneously (e.g., the last item of section 0 followed by the first item of section 1 would be misordered).

Description of Change

Android (RecyclerViewScrollListener.cs)

When the items source is a grouped source (IGroupableItemsViewSource, excluding UngroupedItemsSource), the raw RecyclerView position is translated to a logical data-item index via a new AdjustGroupIndex helper. This helper iterates through the items, skipping group headers and footers, to map the raw position to the correct 0-based data item index. Helper methods FindNextDataIndex and FindPrevDataIndex are used to snap header/footer positions to the nearest preceding or following data item. GetGroupedDataCount counts only data items for bounds checking.

For non-grouped sources with headers/footers, the existing simpler subtraction logic is preserved (now using Math.Clamp to bound the result).

iOS (ItemsViewDelegator.cs and ItemsViewDelegator2.cs)

Changed the sort from .OrderBy(x => x.Row) to .OrderBy(x => x.Section).ThenBy(x => x.Row) so that IndexPathsForVisibleItems is ordered correctly across section boundaries. The fix is applied to both the legacy handler (Items/) and the current handler (Items2/).

Issues Fixed

Fixes #17664

Platforms Tested

  • Android ✅ Fixed
  • iOS ✅ Fixed
  • Windows ⚠️ Not fixed in this PR (original issue also affects Windows — tracked separately)
  • Mac ⚠️ Not fixed in this PR
Code Review: ⚠️ Issues Found

Code Review — PR #31437

🔴 Critical Issues

1. Potential off-by-one: dataIndex initialized to hasHeader ? 1 : 0 in AdjustGroupIndex

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

Problem:

int dataIndex = hasHeader ? 1 : 0, currentItem = hasHeader ? 1 : 0;

When hasHeader = true (the CollectionView has a global header), dataIndex starts at 1. The first data item encountered in the loop would then return index 1 instead of 0. This means all data indices are off by one when the collection has both a global header and grouped content.

The existing test (Issue17664) creates a CollectionView with no global header (hasHeader = false), so it doesn't cover this case and won't catch the bug.

currentItem correctly starts at 1 to skip the global header row in the RecyclerView. But dataIndex should always start at 0 because data items are 0-indexed from the consumer's perspective.

Recommendation:

int dataIndex = 0, currentItem = hasHeader ? 1 : 0;

🟡 Suggestions / Nitpicks

2. Open review comment not addressed: position < 0 returns last item index (incorrect)

File: src/Controls/src/Core/Handlers/Items/Android/RecyclerViewScrollListener.cs (line ~130)

Open comment from copilot-pull-request-reviewer (unresolved):

The current guard for out-of-bounds position:

if (position < 0 || position >= count)
{
    return Math.Max(0, GetGroupedDataCount(source) - 1);
}

Returns the last valid data item index for both negative positions and positions beyond the count. For position < 0 (item not visible / no item found), returning the last item index is incorrect. It should return 0 (or -1 if the caller can handle it), as a negative position means "no item visible at this end."

Recommendation:

if (position < 0)
{
    return 0;
}
if (position >= count)
{
    return Math.Max(0, GetGroupedDataCount(source) - 1);
}

This matches the suggestion left by copilot-pull-request-reviewer (thread PRRT_kwDOD6PVWM5brioJ), which is still open and unresolved.


3. Open review comment not addressed: AdjustGroupIndex has 6 parameters

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

Open comment from copilot-pull-request-reviewer (unresolved, thread PRRT_kwDOD6PVWM5briop):

The AdjustGroupIndex method signature is difficult to understand at the call site:

static int AdjustGroupIndex(IGroupableItemsViewSource source, int position, bool hasHeader, bool hasFooter, int count, bool isStart)

The isStart parameter is particularly unclear — it's a boolean flag that controls whether to snap to the "next" or "prev" data item when the position lands on a group header/footer. For the centerItemIndex call, isStart: true is used, but "center" semantics don't clearly map to either "start" or "end."

Recommendation: Either create a parameter object, or document the isStart parameter semantics with a comment, and verify the center-item behavior is correct.


4. Open unresolved discussion: dataIndex semantics in FindNextDataIndex

File: src/Controls/src/Core/Handlers/Items/Android/RecyclerViewScrollListener.cs (line ~191)

Open comment from jsuarezruiz (thread PRRT_kwDOD6PVWM5f9Mjy, unresolved):

The reviewer asked what dataIndex represents in FindNextDataIndex — is it the index of the "next item to return (exclusive)" or the "last item seen (inclusive)"? The author replied in the thread but the comment was not resolved, indicating the answer may not have been sufficient or a code clarification is still needed.

Recommendation: Add a clarifying comment to FindNextDataIndex explaining the semantics:

// dataIndex: the 0-based data item index to assign to the next valid item found.
// Returned without incrementing because the item following a header/footer inherits this index.
static int FindNextDataIndex(IGroupableItemsViewSource source, int start, bool hasFooter, int count, int dataIndex)

5. Performance: O(n) traversal on every scroll event for grouped collections

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

AdjustGroupIndex iterates linearly through items to translate a RecyclerView position to a data index. It is called three times per scroll event (for first, center, last). GetGroupedDataCount also iterates all items when position is out of bounds. For large grouped datasets, this O(n) traversal on every OnScrolled callback could cause jank.

Recommendation: This is acceptable for typical grouped list sizes, but worth noting. A future optimization could cache a position→data-index mapping that is invalidated when items change.


6. Test uses #if WINDOWS Thread.Sleep(1000) — anti-pattern

File: src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue17664.cs

#if WINDOWS
    Thread.Sleep(1000);
#endif

Per the UI test guidelines, arbitrary Thread.Sleep calls are discouraged. Use App.WaitForElement with a timeout or VerifyScreenshot(retryTimeout: ...) instead. Inline #if directives in test methods also reduce readability.

Recommendation:

App.WaitForElement("Issue17664DescriptionLabel", timeout: TimeSpan.FromSeconds(3));
var resultItem = App.FindElement("Issue17664DescriptionLabel").GetText();

7. Missing newline at end of test files

Both new test files end with \ No newline at end of file:

  • src/Controls/tests/TestCases.HostApp/Issues/Issue17664.cs
  • src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue17664.cs

Recommendation: Add a trailing newline to both files.


✅ Looks Good

  • iOS fix is clean and correct. Changing OrderBy(x => x.Row) to OrderBy(x => x.Section).ThenBy(x => x.Row) is a minimal, well-targeted fix. Applied correctly to both ItemsViewDelegator.cs (Items/ handler) and ItemsViewDelegator2.cs (Items2/ handler).
  • Grouped vs non-grouped detection using itemsSource is not UngroupedItemsSource && itemsSource is IGroupableItemsViewSource is appropriate.
  • Math.Clamp on the non-grouped path (addressing a previous review comment) correctly bounds indices.
  • Test structure is appropriate — uses AutomationId, inherits _IssuesUITest, has single [Category], correct naming convention.
  • Test scenario is representative — uses 3 groups × 5 items to verify index correctness after programmatic scroll.

@rmarinho rmarinho added s/agent-approved AI agent recommends approval - PR fix is correct and optimal s/agent-gate-passed AI verified tests catch the bug (fail without fix, pass with fix) s/agent-fix-lose Author adopted the agent's fix and it turned out to be bad s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) labels Feb 18, 2026
Copy link
Copy Markdown
Contributor

@kubaflo kubaflo left a comment

Choose a reason for hiding this comment

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

Could you split this PR on 2 separate ones: iOS and Android? Please use the same test for both

@kubaflo kubaflo added s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates and removed s/agent-fix-lose Author adopted the agent's fix and it turned out to be bad labels Feb 20, 2026
@rmarinho rmarinho added s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-fix-lose Author adopted the agent's fix and it turned out to be bad and removed s/agent-approved AI agent recommends approval - PR fix is correct and optimal labels Feb 20, 2026
@jfversluis jfversluis added the s/pr-needs-author-input PR needs an update from the author label Feb 24, 2026
@SyedAbdulAzeemSF4852 SyedAbdulAzeemSF4852 changed the title [Android, iOS] Fix for Incorrect ItemsViewScrolledEventArgs Values in CollectionView with Grouped Items [Android] Fix for Incorrect ItemsViewScrolledEventArgs Values in CollectionView with Grouped Items Feb 25, 2026
@SyedAbdulAzeemSF4852
Copy link
Copy Markdown
Contributor Author

Could you split this PR on 2 separate ones: iOS and Android? Please use the same test for both

@kubaflo , As suggested, I’ve split the changes into two separate PRs for iOS and Android, using the same test for both. The iOS PR is #34240.

@dotnet-policy-service dotnet-policy-service bot added the stale Indicates a stale issue/pr and will be closed soon label Mar 8, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 10, 2026

🚀 Dogfood this PR with:

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

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

Or

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

@dotnet-policy-service dotnet-policy-service bot removed stale Indicates a stale issue/pr and will be closed soon s/pr-needs-author-input PR needs an update from the author labels Mar 10, 2026
…d clarify dataIndex semantics in FindNextDataIndex.
@SyedAbdulAzeemSF4852
Copy link
Copy Markdown
Contributor Author

Addressed concerns raised in the AI summary.

kubaflo pushed a commit that referenced this pull request Mar 14, 2026
…dices with grouped items (#34240)

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

### Issue Details

- When a CollectionView's IsGrouped property is set to true, the values
of FirstVisibleItemIndex, CenterItemIndex, and LastVisibleItemIndex in
the ItemsViewScrolledEventArgs passed to the Scrolled event handler are
incorrect.

### Root Cause

- Visible items were sorted only by Row, which produced incorrect
ordering when items from multiple sections were visible simultaneously.

### Description of Change

**iOS (ItemsViewDelegator.cs and ItemsViewDelegator2.cs)**

- Changed the sort from .OrderBy(x => x.Row) to .OrderBy(x =>
x.Section).ThenBy(x => x.Row) so that IndexPathsForVisibleItems is
ordered correctly across section boundaries. The fix is applied to both
the legacy handler (Items/) and the current handler (Items2/).

### Issues Fixed
Fixes #17664 


### Validated the behaviour in the following platforms

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

Android fix PR: #31437

### Output
| Before | After |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/3612815d-3a43-4dd5-8d2c-3832e3d4a077">
| <video
src="https://github.com/user-attachments/assets/f6cd63b8-1ed9-465a-99d9-11e38b004dac">
|
PureWeen pushed a commit that referenced this pull request Mar 19, 2026
…dices with grouped items (#34240)

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

### Issue Details

- When a CollectionView's IsGrouped property is set to true, the values
of FirstVisibleItemIndex, CenterItemIndex, and LastVisibleItemIndex in
the ItemsViewScrolledEventArgs passed to the Scrolled event handler are
incorrect.

### Root Cause

- Visible items were sorted only by Row, which produced incorrect
ordering when items from multiple sections were visible simultaneously.

### Description of Change

**iOS (ItemsViewDelegator.cs and ItemsViewDelegator2.cs)**

- Changed the sort from .OrderBy(x => x.Row) to .OrderBy(x =>
x.Section).ThenBy(x => x.Row) so that IndexPathsForVisibleItems is
ordered correctly across section boundaries. The fix is applied to both
the legacy handler (Items/) and the current handler (Items2/).

### Issues Fixed
Fixes #17664 


### Validated the behaviour in the following platforms

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

Android fix PR: #31437

### Output
| Before | After |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/3612815d-3a43-4dd5-8d2c-3832e3d4a077">
| <video
src="https://github.com/user-attachments/assets/f6cd63b8-1ed9-465a-99d9-11e38b004dac">
|
PureWeen pushed a commit that referenced this pull request Mar 24, 2026
…dices with grouped items (#34240)

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

### Issue Details

- When a CollectionView's IsGrouped property is set to true, the values
of FirstVisibleItemIndex, CenterItemIndex, and LastVisibleItemIndex in
the ItemsViewScrolledEventArgs passed to the Scrolled event handler are
incorrect.

### Root Cause

- Visible items were sorted only by Row, which produced incorrect
ordering when items from multiple sections were visible simultaneously.

### Description of Change

**iOS (ItemsViewDelegator.cs and ItemsViewDelegator2.cs)**

- Changed the sort from .OrderBy(x => x.Row) to .OrderBy(x =>
x.Section).ThenBy(x => x.Row) so that IndexPathsForVisibleItems is
ordered correctly across section boundaries. The fix is applied to both
the legacy handler (Items/) and the current handler (Items2/).

### Issues Fixed
Fixes #17664 


### Validated the behaviour in the following platforms

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

Android fix PR: #31437

### Output
| Before | After |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/3612815d-3a43-4dd5-8d2c-3832e3d4a077">
| <video
src="https://github.com/user-attachments/assets/f6cd63b8-1ed9-465a-99d9-11e38b004dac">
|
@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented Mar 29, 2026

🚦 Gate - Test Before and After Fix

📊 Expand Full Gate262f346 · Fix off-by-one in AdjustGroupIndex, correct position < 0 handling, and clarify dataIndex semantics in FindNextDataIndex.

Gate Result: ✅ PASSED

Platform: ANDROID · Base: main · Merge base: 720a9d4a

Test Without Fix (expect FAIL) With Fix (expect PASS)
🖥️ Issue17664 Issue17664 ✅ FAIL — 782s ✅ PASS — 1798s
🔴 Without fix — 🖥️ Issue17664: FAIL ✅ · 782s
  Determining projects to restore...
  Restored /home/vsts/work/1/s/src/Graphics/src/Graphics/Graphics.csproj (in 593 ms).
  Restored /home/vsts/work/1/s/src/Essentials/src/Essentials.csproj (in 3.9 sec).
  Restored /home/vsts/work/1/s/src/Core/src/Core.csproj (in 1.96 sec).
  Restored /home/vsts/work/1/s/src/Controls/src/Xaml/Controls.Xaml.csproj (in 6.61 sec).
  Restored /home/vsts/work/1/s/src/Core/maps/src/Maps.csproj (in 4.32 sec).
  Restored /home/vsts/work/1/s/src/Controls/src/Core/Controls.Core.csproj (in 29 ms).
  Restored /home/vsts/work/1/s/src/Controls/Maps/src/Controls.Maps.csproj (in 24 ms).
  Restored /home/vsts/work/1/s/src/Controls/Foldable/src/Controls.Foldable.csproj (in 28 ms).
  Restored /home/vsts/work/1/s/src/BlazorWebView/src/Maui/Microsoft.AspNetCore.Components.WebView.Maui.csproj (in 49 ms).
  Restored /home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj (in 5.06 sec).
  1 of 11 projects are up-to-date for restore.
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683353
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0-android36.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683353
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0-android36.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683353
  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.60-ci+azdo.13683353
  Maps -> /home/vsts/work/1/s/artifacts/bin/Maps/Debug/net10.0-android36.0/Microsoft.Maui.Maps.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683353
  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.60-ci+azdo.13683353
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683353
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683353
  Controls.Xaml -> /home/vsts/work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Xaml.dll
  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
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683353
  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.60-ci+azdo.13683353
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683353
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683353
  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.60-ci+azdo.13683353
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683353
  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.60-ci+azdo.13683353
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683353
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683353
  Controls.Xaml -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Xaml.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.Foldable -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Foldable.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683353
  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:19.12
Broadcasting: Intent { act=android.intent.action.CLOSE_SYSTEM_DIALOGS flg=0x400000 }
Broadcast completed: result=0
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.12 sec).
  Restored /home/vsts/work/1/s/src/TestUtils/src/UITest.NUnit/UITest.NUnit.csproj (in 1.48 sec).
  Restored /home/vsts/work/1/s/src/TestUtils/src/UITest.Core/UITest.Core.csproj (in 4 ms).
  Restored /home/vsts/work/1/s/src/TestUtils/src/UITest.Appium/UITest.Appium.csproj (in 1.75 sec).
  Restored /home/vsts/work/1/s/src/TestUtils/src/VisualTestUtils.MagickNet/VisualTestUtils.MagickNet.csproj (in 6.52 sec).
  Restored /home/vsts/work/1/s/src/TestUtils/src/UITest.Analyzers/UITest.Analyzers.csproj (in 3.88 sec).
  Restored /home/vsts/work/1/s/src/Controls/tests/CustomAttributes/Controls.CustomAttributes.csproj (in 5 ms).
  Restored /home/vsts/work/1/s/src/Controls/tests/TestCases.Android.Tests/Controls.TestCases.Android.Tests.csproj (in 2.37 sec).
  5 of 13 projects are up-to-date for restore.
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683353
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683353
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683353
  Controls.CustomAttributes -> /home/vsts/work/1/s/artifacts/bin/Controls.CustomAttributes/Debug/net10.0/Controls.CustomAttributes.dll
  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.60-ci+azdo.13683353
  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
  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.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.
/home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll
[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.23]   Discovering: Controls.TestCases.Android.Tests
[xUnit.net 00:00:00.73]   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
>>>>> 03/29/2026 13:13:12 FixtureSetup for Issue17664(Android)
>>>>> 03/29/2026 13:13:16 VerifyGroupedCollectionViewVisibleItemIndices Start
>>>>> 03/29/2026 13:13:20 VerifyGroupedCollectionViewVisibleItemIndices Stop
>>>>> 03/29/2026 13:13:21 Log types: logcat, bugreport, server
  Failed VerifyGroupedCollectionViewVisibleItemIndices [6 s]
  Error Message:
     Assert.That(resultItem, Is.EqualTo("Category C item #2"))
  Expected string length 18 but was 50. Strings differ at index 0.
  Expected: "Category C item #2"
  But was:  "Use the button above to scroll the CollectionView."
  -----------^

  Stack Trace:
     at Microsoft.Maui.TestCases.Tests.Issues.Issue17664.VerifyGroupedCollectionViewVisibleItemIndices() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue17664.cs:line 27

1)    at Microsoft.Maui.TestCases.Tests.Issues.Issue17664.VerifyGroupedCollectionViewVisibleItemIndices() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue17664.cs:line 27


NUnit Adapter 4.5.0.0: Test execution complete

Total tests: 1
Test Run Failed.
     Failed: 1
 Total time: 1.5002 Minutes

🟢 With fix — 🖥️ Issue17664: PASS ✅ · 1798s

(truncated to last 15,000 chars)

ases.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:26.49
* 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.60-ci+azdo.13683353
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0-android36.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683353
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0-android36.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683353
  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.60-ci+azdo.13683353
  Maps -> /home/vsts/work/1/s/artifacts/bin/Maps/Debug/net10.0-android36.0/Microsoft.Maui.Maps.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683353
  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.60-ci+azdo.13683353
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683353
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683353
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683353
  Controls.Xaml -> /home/vsts/work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Xaml.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.Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.Maps/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Maps.dll
  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.60-ci+azdo.13683353
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683353
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683353
  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.60-ci+azdo.13683353
  Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Maps.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683353
  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.60-ci+azdo.13683353
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683353
  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
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683353
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683353
  Controls.Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Maps.dll
  Controls.Xaml -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Xaml.dll

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

Time Elapsed 00:08:03.39
Broadcasting: Intent { act=android.intent.action.CLOSE_SYSTEM_DIALOGS flg=0x400000 }
Broadcast completed: result=0
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.60-ci+azdo.13683353
  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.60-ci+azdo.13683353
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13683353
  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.60-ci+azdo.13683353
  Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
  VisualTestUtils -> /home/vsts/work/1/s/artifacts/bin/VisualTestUtils/Debug/netstandard2.0/VisualTestUtils.dll
  UITest.Core -> /home/vsts/work/1/s/artifacts/bin/UITest.Core/Debug/net10.0/UITest.Core.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.NUnit -> /home/vsts/work/1/s/artifacts/bin/UITest.NUnit/Debug/net10.0/UITest.NUnit.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.
/home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll
[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.13]   Discovering: Controls.TestCases.Android.Tests
[xUnit.net 00:00:00.49]   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
>>>>> 03/29/2026 13:35:01 FixtureSetup for Issue17664(Android)
>>>>> 03/29/2026 13:35:04 VerifyGroupedCollectionViewVisibleItemIndices Start
>>>>> 03/29/2026 13:35:08 VerifyGroupedCollectionViewVisibleItemIndices Stop
  Passed VerifyGroupedCollectionViewVisibleItemIndices [4 s]
NUnit Adapter 4.5.0.0: Test execution complete

Test Run Successful.
Total tests: 1
     Passed: 1
 Total time: 22.9459 Seconds

📁 Fix files reverted (2 files)
  • eng/pipelines/ci-copilot.yml
  • src/Controls/src/Core/Handlers/Items/Android/RecyclerViewScrollListener.cs

@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented Mar 29, 2026

🤖 AI Summary

📊 Expand Full Review262f346 · Fix off-by-one in AdjustGroupIndex, correct position < 0 handling, and clarify dataIndex semantics in FindNextDataIndex.
🔍 Pre-Flight — Context & Validation

Issue: #17664 - CollectionView ItemsViewScrolledEventArgs are incorrect when IsGrouped = true
PR: #31437 - [Android] Fix for Incorrect ItemsViewScrolledEventArgs Values in CollectionView with Grouped Items
Platforms Affected: Android (iOS fix is in separate PR #34240)
Files Changed: 1 implementation, 2 test
Test Type: UI Tests (TestCases.HostApp + TestCases.Shared.Tests)

Key Findings

  • Issue: When CollectionView.IsGrouped = true, raw RecyclerView adapter positions include group headers/footers, making FirstVisibleItemIndex, CenterItemIndex, and LastVisibleItemIndex incorrect
  • PR is Android-only; iOS fix has been split to PR [iOS/Mac] CollectionView: Fix incorrect ItemsViewScrolledEventArgs indices with grouped items #34240 (addressing kubaflo's CHANGES_REQUESTED from Feb 2026 to split)
  • Prior agent review (Feb 2026) confirmed: gate passed, 5 independent try-fix alternatives all passed, PR's fix was best candidate
  • PR labels: s/agent-gate-passed, s/agent-fix-pr-picked, s/agent-reviewed
  • kubaflo CHANGES_REQUESTED (Feb 2026) requesting iOS/Android split — action has been taken (iOS moved to PR [iOS/Mac] CollectionView: Fix incorrect ItemsViewScrolledEventArgs indices with grouped items #34240), but kubaflo has not re-reviewed or dismissed their review; PR is still blocked
  • All prior inline review comments from jsuarezruiz and Copilot have been addressed and resolved
  • Test uses file-level #if TEST_FAILS_ON_IOS && TEST_FAILS_ON_CATALYST && TEST_FAILS_ON_WINDOWS guard (acceptable)
  • [Issue] attribute correctly restricts HostApp page to PlatformAffected.Android
  • Copilot suggestion to return 0 for negative positions has been implemented
  • Math.Clamp used for non-grouped path (addressed jsuarezruiz feedback)
  • snapForward parameter name added with XML doc comment (addressed nitpick feedback)

Potential Remaining Issues

  1. Missing trailing newline in test files (cosmetic)
  2. Test doesn't await scroll animation completion — App.WaitForElement("Issue17664DescriptionLabel").GetText() called immediately after tap without waiting for text to change (potential flakiness; but gate passed)
  3. AdjustGroupIndex still has 6 parameters (nitpick was noted as "addressed" via doc comment, but method signature unchanged)

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #31437 AdjustGroupIndex iterates adapter positions, skips group headers/footers to compute 0-based data index; FindNextDataIndex/FindPrevDataIndex for snap behavior ✅ PASSED (Gate) RecyclerViewScrollListener.cs Android-only; validated by gate + 5 prior try-fix alternatives

🔧 Fix — Analysis & Comparison

Fix Candidates

# Source Approach Test Result Files Changed Notes
1 try-fix (claude-opus-4.6) GetGroupAndIndex + per-group count summation; O(groups) instead of O(positions) ✅ PASS 1 file Cleaner iteration; avoids per-position scan
2 try-fix (claude-sonnet-4.6) int[] map built in one forward pass (position→dataIndex); O(1) lookups with directional snap ✅ PASS 1 file Most readable; explicit mapping; O(n) memory
3 try-fix (gpt-5.3-codex) GetGroupAndIndex + GetGroupItemsViewSource with LINQ sums; compact no-helper implementation ✅ PASS 1 file Most compact; LINQ overhead
4 try-fix (gpt-5.4, sub gemini) Single FlatDataIndex method; GetGroupAndIndex + GetGroupItemsViewSource; all inline, no helpers ✅ PASS 1 file All-inline formula approach
PR PR #31437 AdjustGroupIndex iterates positions 0→target, skips group headers/footers; FindNextDataIndex/FindPrevDataIndex for snapping ✅ PASSED (Gate) 1 file Android-only; gate validated; reviewer-iterated

Cross-Pollination

Model Round New Ideas? Details
claude-opus-4.6 2 No "NO NEW IDEAS" — algorithmic space exhausted

Exhausted: Yes — all meaningful approaches covered (O(n) per-position scan, O(groups) group sum, O(1) lookup array, all-inline formula)

Selected Fix: PR's fix — already gate-validated, iteratively improved through reviewer feedback (negative position returns 0, Math.Clamp bounds, snapForward XML doc). All 4 alternatives also passed, confirming the fix space is well-understood. Attempt 1's GetGroupAndIndex + group-summation is slightly more efficient (O(groups) vs O(positions)) but the PR's fix is complete, reviewed, and ready.


📋 Report — Final Recommendation

✅ Final Recommendation: APPROVE

Phase Status

Phase Status Notes
Pre-Flight ✅ COMPLETE Issue #17664, Android-only (iOS split to PR #34240), 3 files changed
Gate ✅ PASSED Android; tests FAIL without fix, PASS with fix
Try-Fix ✅ COMPLETE 4 attempts, all 4 PASS; PR's fix selected as best
Report ✅ COMPLETE

Summary

PR #31437 fixes incorrect FirstVisibleItemIndex, CenterItemIndex, and LastVisibleItemIndex values in ItemsViewScrolledEventArgs when CollectionView.IsGrouped = true on Android. The fix is Android-only; iOS has been addressed in the companion PR #34240, which satisfies the CHANGES_REQUESTED review from kubaflo (Feb 2026) requesting the split.

Gate verification confirmed tests fail without the fix and pass with it. All 4 independent try-fix alternatives also passed, exhausting the algorithmic solution space and confirming the root cause analysis is correct.

Root Cause

RecyclerViewScrollListener.GetVisibleItemsIndex returned raw RecyclerView adapter positions without accounting for group headers and footers in grouped data sources. Each group contributes a group header row (and optionally a group footer row) in the adapter's position space. The raw positions therefore over-counted, making every visible item's index incorrect by the cumulative number of headers/footers preceding it.

Fix Quality

Strengths:

  • ✅ Gate passed: tests fail without fix, pass with fix (Android)
  • ✅ 4 independent try-fix alternatives all passed — fix space fully validated
  • ✅ Correctly splits responsibility: grouped path uses AdjustGroupIndex, non-grouped path retains simpler header/footer subtraction with Math.Clamp
  • snapForward parameter clearly documented with XML doc comment
  • ✅ Negative position correctly returns 0 (Copilot suggestion implemented)
  • Math.Clamp used for bounds (jsuarezruiz feedback implemented)
  • ✅ All prior inline review threads from jsuarezruiz and Copilot are resolved
  • kubaflo split request addressed: iOS moved to PR [iOS/Mac] CollectionView: Fix incorrect ItemsViewScrolledEventArgs indices with grouped items #34240; this PR is now Android-only
  • [Issue] attribute and test guard correctly scoped to Android

Minor items (non-blocking):

  • AdjustGroupIndex still has 6 parameters (noted as nitpick; snapForward XML doc partially addresses readability)
  • Both test files are missing trailing newlines (cosmetic)
  • Test calls App.WaitForElement(...).GetText() immediately after tap without waiting for scroll to settle; passed in gate but could be slightly flaky under load

Selected Fix

Selected Fix: PR's fix — gate-validated, iterated through reviewer feedback, and confirmed by 4 passing alternatives. No changes needed.


@MauiBot MauiBot added s/agent-approved AI agent recommends approval - PR fix is correct and optimal and removed s/agent-changes-requested AI agent recommends changes - found a better alternative or issues labels Mar 29, 2026
KarthikRajaKalaimani pushed a commit to KarthikRajaKalaimani/maui that referenced this pull request Mar 30, 2026
…dices with grouped items (dotnet#34240)

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

### Issue Details

- When a CollectionView's IsGrouped property is set to true, the values
of FirstVisibleItemIndex, CenterItemIndex, and LastVisibleItemIndex in
the ItemsViewScrolledEventArgs passed to the Scrolled event handler are
incorrect.

### Root Cause

- Visible items were sorted only by Row, which produced incorrect
ordering when items from multiple sections were visible simultaneously.

### Description of Change

**iOS (ItemsViewDelegator.cs and ItemsViewDelegator2.cs)**

- Changed the sort from .OrderBy(x => x.Row) to .OrderBy(x =>
x.Section).ThenBy(x => x.Row) so that IndexPathsForVisibleItems is
ordered correctly across section boundaries. The fix is applied to both
the legacy handler (Items/) and the current handler (Items2/).

### Issues Fixed
Fixes dotnet#17664 


### Validated the behaviour in the following platforms

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

Android fix PR: dotnet#31437

### Output
| Before | After |
|----------|----------|
| <video
src="https://github.com/user-attachments/assets/3612815d-3a43-4dd5-8d2c-3832e3d4a077">
| <video
src="https://github.com/user-attachments/assets/f6cd63b8-1ed9-465a-99d9-11e38b004dac">
|
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-approved AI agent recommends approval - PR fix is correct and optimal 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 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.

[iOS/Mac/Windows] CollectionView ItemsViewScrolledEventArgs are incorrect when IsGrouped = true

9 participants