[iOS] Fix VerticalOffset Update When Modifying CollectionView.ItemsSource While Scrolled#34153
Conversation
There was a problem hiding this comment.
Pull request overview
This PR targets iOS/MacCatalyst CollectionView scrolling events to ensure ItemsViewScrolledEventArgs.HorizontalOffset/VerticalOffset report 0 when the ItemsSource is modified/cleared while the view is scrolled, addressing incorrect offset values reported after updates.
Changes:
- On iOS delegators, stop returning early when there are no visible items so a
Scrolledevent can be raised with offsets coerced to0. - Set
contentOffsetX/Yto0when no visible items are present (instead of usingscrollView.ContentOffset).
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
src/Controls/src/Core/Handlers/Items2/iOS/ItemsViewDelegator2.cs |
Emits scrolled offsets as 0 when the collection has no visible items (Items2 handler for iOS/MacCatalyst). |
src/Controls/src/Core/Handlers/Items/iOS/ItemsViewDelegator.cs |
Applies the same scrolled-offset behavior to the legacy iOS handler. |
| var contentInset = scrollView.ContentInset; | ||
| var contentOffsetX = scrollView.ContentOffset.X + contentInset.Left; | ||
| var contentOffsetY = scrollView.ContentOffset.Y + contentInset.Top; | ||
| var contentOffsetX = !visibleItems ? 0 : scrollView.ContentOffset.X + contentInset.Left; | ||
| var contentOffsetY = !visibleItems ? 0 : scrollView.ContentOffset.Y + contentInset.Top; |
There was a problem hiding this comment.
Because the method no longer returns early when there are no visible items, lastVisibleItemIndex can be -1 while source.ItemCount may be 0. In that case, the RemainingItemsThreshold logic below can incorrectly fire SendRemainingItemsThresholdReached() (e.g., -1 == source.ItemCount - 1). Add a guard (e.g., if (lastVisibleItemIndex == -1) return;) before evaluating the remaining-items threshold, similar to the Android implementation.
| var contentInset = scrollView.ContentInset; | ||
| var contentOffsetX = scrollView.ContentOffset.X + contentInset.Left; | ||
| var contentOffsetY = scrollView.ContentOffset.Y + contentInset.Top; | ||
| var contentOffsetX = !visibleItems ? 0 : scrollView.ContentOffset.X + contentInset.Left; | ||
| var contentOffsetY = !visibleItems ? 0 : scrollView.ContentOffset.Y + contentInset.Top; |
There was a problem hiding this comment.
Since we now continue when there are no visible items, lastVisibleItemIndex can be -1 (and source.ItemCount can be 0). This makes the remaining-items threshold checks below potentially fire SendRemainingItemsThresholdReached() incorrectly (e.g., -1 == source.ItemCount - 1). Add a guard (e.g., return when lastVisibleItemIndex == -1) before running the threshold logic, matching the Android pattern.
🤖 AI Summary📊 Expand Full Review🔍 Pre-Flight — Context & Validation📝 Review Session — Added test for the pr agent ·
|
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #34153 | Remove early return, set offsets to 0 when ! PENDING (Gate) | 2 impl files, 3 test files | Original PR; has potential RemainingItemsThreshold regression | visibleItems |
🚦 Gate — Test Verification
📝 Review Session — Added test for the pr agent · 53dac0e
Result PASSED:
Platform: iOS
Mode: Full Verification (verify-tests-fail-without-fix skill)
- Tests FAIL without fix (bug is present, offset not resetting)
- Tests PASS with fix (fix correctly resets offset to 0)
Test: VerifyCollectionViewVerticalOffset in Issue21708
Fix Files Verified: ItemsViewDelegator.cs, ItemsViewDelegator2.cs
🔧 Fix — Analysis & Comparison
📝 Review Session — Added test for the pr agent · 53dac0e
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| 1 | try-fix (claude-sonnet-4.6) | Use (ContentSize==0) to zero offsets | PASS | 2 impl files | Similar to PR fix but uses ContentSize; same RemainingItemsThreshold regression |
| 2 | try-fix (claude-haiku-4.5) | Only update PreviousHorizontalOffset/PreviousVerticalOffset when visibleItems=true PASS | 2 impl files | More complex; same regression risk | |
| 3 | try-fix (claude-opus-4.5) | source.ItemCount == 0 condition + reset PreviousOffset fields PASS | 2 impl files | ItemCount check; still has regression | |
| 4 | try-fix (gpt-4.1) | Reset PreviousOffset fields only when ItemCount==0 (no event args FAIL | 2 impl files | Test failed: event args still stale | change) |
| 5 | try-fix (gemini-3-pro-preview) | Fire Scrolled event with 0 offsets inside !visibleItems block before PASS |
2 impl files | Avoids regression: keeps early return, fires reset event only when Previous!=0 | returning |
| fire with 0, preserve early return otherwise PASS | 2 impl files | Has regression in the !ContentOffset==0 path | |||
| 7 | try-fix (cross-poll sonnet) | Internal method fires reset event before early return | PASS | 2 impl files | Avoids regression: keeps early return; more complex than Attempt 5 |
| PR | PR #34153 | Remove early return on !visibleItems; set offsets to 0 with ternary PASS (Gate) | 2 impl files | Simplest fix; has RemainingItemsThreshold regression (Copilot reviewer flagged) |
Cross-pollination: 3 rounds; models exhausted at round 3 (3 of 5 models saying NO NEW IDEAS for all approaches tried).
Exhausted: Yes (for practical purposes; remaining ideas from models are increasingly complex architectural alternatives)
Selected Fix: PR's fix with required guard The PR's 2-line-per-file change is the simplest approach, but it needs a guard if (!visibleItems) return; (or if (lastVisibleItemIndex == -1) return;) before the switch (itemsView.RemainingItemsThreshold) block to prevent SendRemainingItemsThresholdReached() from firing incorrectly when items are cleared. Alternatively, Attempt 5 (Gemini) avoids the regression entirely by keeping the early return and firing a reset event inside the !visibleItems block, but is more complex.added
Root Cause: The Scrolled() method originally returned early when there were no visible items (!visibleItems), preventing any offset reset event from firing when ItemsSource is cleared while scrolled. The previous offsets were retained because no SendScrolled call was made. The fix must fire a Scrolled event with 0 offsets when items become empty.
Regression Risk: The PR's approach of removing the early return exposes the RemainingItemsThreshold switch to lastVisibleItemIndex == -1 and source.ItemCount == 0, causing SendRemainingItemsThresholdReached() to fire incorrectly on any clear of ItemsSource (when threshold != -1). This is a critical regression.
📋 Report — Final Recommendation
📝 Review Session — Added test for the pr agent · 53dac0e
Final Recommendation: REQUEST CHANGES##
Summary
PR #34153 fixes a real iOS/MacCatalyst bug where ItemsViewScrolledEventArgs.VerticalOffset and HorizontalOffset fail to reset to 0 when ItemsSource is cleared while the CollectionView is scrolled. The fix approach is simple and but it introduces a critical regression in the RemainingItemsThreshold logic that must be addressed before merging. The Copilot reviewer already flagged this issue with inline comments.correct
Gate verified: tests FAIL without fix, PASS with fix (iOS, Issue21708).
Root Cause
When ItemsSource is cleared, iOS fires the UIScrollView.Scrolled delegate while IndexPathsForVisibleItems is empty. The original code returned early (if (!visibleItems) return;), so no Scrolled event was sent to the MAUI layer and PreviousHorizontalOffset/PreviousVerticalOffset kept their stale values. When new items were added later, the stale values caused incorrect deltas and offset values.
Fix Quality
The PR's removing the early return and setting offsets to 0 via ternary when ! is correct for fixing the offset bug. It passes the gate tests and is the simplest possible change (2 lines per file). However, it introduces a regression:visibleItems approach
Critical regression (RemainingItemsThreshold):
After removing the early return, lastVisibleItemIndex can be -1 when visibleItems is false, and source.ItemCount can be 0 when items are cleared. The following switch logic then fires incorrectly:
case 0:
fires incorrectly!
if (lastVisibleItemIndex == source.ItemCount - 1)
itemsView.SendRemainingItemsThresholdReached();
break;
default:
fires incorrectly!
if (source.ItemCount - 1 - lastVisibleItemIndex <= itemsView.RemainingItemsThreshold)
itemsView.SendRemainingItemsThresholdReached();
break;Any user using RemainingItemsThreshold != -1 would see RemainingItemsThresholdReached fire every time items are cleared from the collection. This is a high-severity regression.
The Copilot reviewer already identified this in both files (Items/ and Items2/) and suggested adding a guard.
Required Changes
1. Add guard before RemainingItemsThreshold switch (both files)
In src/Controls/src/Core/Handlers/Items/iOS/ItemsViewDelegator.cs and src/Controls/src/Core/Handlers/Items2/iOS/ItemsViewDelegator2.cs, add after itemsView.SendScrolled(...):
if (!visibleItems)
return;
switch (itemsView.RemainingItemsThreshold)
{ ... }This matches the pattern suggested by the Copilot reviewer.
2. Test naming consistency (minor)
Test files are named Issue21708 but the PR description says it fixes #26798. Issue #21708 is a related but different (Android) issue. If the intent is to test the iOS behavior, the test should reference #26798 or the test description should be updated to clarify the dual-platform coverage.
3. Missing newlines at end of files (cosmetic)
All three new test files are missing newlines at end of file.
Code Review Findings
RemainingItemsThreshold regression (flagged by Copilot reviewer)
- Files:
ItemsViewDelegator.cs,ItemsViewDelegator2.cs(both files) - Problem: Removing
if (!visibleItems) return;exposes theswitch (itemsView.RemainingItemsThreshold)tolastVisibleItemIndex == -1andsource.ItemCount == 0, causingSendRemainingItemsThresholdReached()to fire on everyItemsSourceclear when threshold != -1 - Recommendation: Add
if (!visibleItems) return;immediately after theitemsView.SendScrolled(itemsViewScrolledEventArgs);line in both files
- Test naming:
Issue21708test references the Android issue (CollectionView.Scrolled event offset isn't correctly reset when items change on Android #21708); should reference the iOS issue ([iOS]VerticalOffset Not Reset to Zero After Clearing ItemSource in CollectionView #26798) that this PR actually fixes, or add a comment explaining the dual-platform intent - Test assertion quality:
Is.GreaterThan("0")on line comparing a string label text is a lexicographic string comparison. Works in practice (scroll offset > 0 as string), butIs.Not.EqualTo("0")would be more semantically correct - Missing EOF newlines: Three new test files are missing newlines at end of file
Looks Good
- The core fix logic is correct and minimal (2 lines changed per file)
- Applied symmetrically to both
Items/(legacy) andItems2/(current) iOS handlers
Empty flow correctly - PR description has the required NOTE block at the top
PreviousHorizontalOffset/PreviousVerticalOffsetcorrectly reset to 0 in the empty case (via the ternary assignment)
Try-Fix Exploration
7 independent approaches were tested. Notable finding: Approaches that preserve the early return avoid the regression entirely.
Among alternatives, Gemini's Attempt 5 avoids the regression cleanly:
if (!visibleItems)
{
// Fire reset event only if we were previously scrolled
if (PreviousHorizontalOffset != 0 || PreviousVerticalOffset != 0)
{
// fire Scrolled event with 0 offsets
PreviousHorizontalOffset = 0;
PreviousVerticalOffset = 0;
}
RemainingItemsThreshold NOT affected
}However, the simplest fix remains the PR's approach + the guard from the Copilot reviewer.
Title & Description Review
Title: [iOS] Fix VerticalOffset Update When Modifying CollectionView.ItemsSource While Scrolled
- Has platform prefix
[iOS] - Describes the fix clearly
- Suggestion: Could be simplified to
[iOS] CollectionView: Reset scroll offsets to zero when ItemsSource is cleared
Description: Has NOTE block, brief description. Missing root cause and technical detail, but acceptable for a small focused fix.
What NOT to Do (for future agents)
Don't remove if (!visibleItems) return; without adding a guard before the RemainingItemsThreshold lastVisibleItemIndex == -1 and ItemCount == 0 cause spurious SendRemainingItemsThresholdReached() callsswitch -
Don't reset Previous offsets alone (Attempt stale contentOffsetX/Y values are still used in event args even after resetting the cached fields4) -
📋 Expand PR Finalization Review
Title: ✅ Good
Current: [iOS] Fix VerticalOffset Update When Modifying CollectionView.ItemsSource While Scrolled
Description: ⚠️ Needs Update
- Verbose and slightly inaccurate — the fix resets offsets to zero, not just "updates" them
- Affects MacCatalyst too (same iOS handler files are compiled for both), but the title says
[iOS]only — acceptable since issue was filed as iOS/macOS - "While Scrolled" is technically imprecise; the issue is that offsets are not reset after clearing items when previously scrolled
✨ 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
When a CollectionView's ItemsSource is cleared while the list is scrolled, iOS fires a Scrolled event with no visible items (visibleItems == false). The previous code returned early in that case:
if (!visibleItems)
return;Because of this early return, no ItemsViewScrolled event was raised with offset = 0, so the old offset values were retained from the last scroll position. The fix removes this early return and instead reports offsets as 0 when there are no visible items, ensuring the event fires and consumers see the reset.
Description of Change
In ItemsViewDelegator.cs (Items/) and ItemsViewDelegator2.cs (Items2/), the Scrolled override no longer returns early when !visibleItems. Instead, contentOffsetX and contentOffsetY are set to 0 in that case using a ternary:
var contentOffsetX = !visibleItems ? 0 : scrollView.ContentOffset.X + contentInset.Left;
var contentOffsetY = !visibleItems ? 0 : scrollView.ContentOffset.Y + contentInset.Top;This ensures ItemsViewScrolled fires with VerticalOffset = 0 and HorizontalOffset = 0 after items are cleared, correctly resetting any listeners.
Applied symmetrically to both Items/iOS/ItemsViewDelegator.cs (legacy handler) and Items2/iOS/ItemsViewDelegator2.cs (current CV2 handler).
⚠️ Known Regression Risk: RemainingItemsThreshold
By removing the early return, the RemainingItemsThreshold switch block is now reachable when !visibleItems. In that case, lastVisibleItemIndex == -1 and source.ItemCount == 0, which means:
case 0:→lastVisibleItemIndex == source.ItemCount - 1→-1 == -1→ always firesSendRemainingItemsThresholdReached()when items are cleared and threshold is 0default:→source.ItemCount - 1 - lastVisibleItemIndex <= threshold→0 <= threshold→ fires for any non-negative threshold
A guard should be added after SendScrolled to prevent the threshold logic from running with empty data.
What NOT to Do (for future agents)
- ❌ Don't remove the
if (!visibleItems) return;without adding a guard before theRemainingItemsThresholdswitch —lastVisibleItemIndex == -1andsource.ItemCount == 0cause spuriousSendRemainingItemsThresholdReached()calls when items are cleared
Issues Fixed
Fixes #26798
Platforms Tested
- iOS
- MacCatalyst (same code path via
.ios.csextension) - Android (not affected — different handler)
- Windows (not affected — different handler)
Code Review: ⚠️ Issues Found
Code Review — PR #34153
🔴 Critical Issues
RemainingItemsThreshold Regression
Files:
src/Controls/src/Core/Handlers/Items/iOS/ItemsViewDelegator.cssrc/Controls/src/Core/Handlers/Items2/iOS/ItemsViewDelegator2.cs
Problem:
Removing the early if (!visibleItems) return; means the RemainingItemsThreshold switch at the bottom of Scrolled() is now reachable with lastVisibleItemIndex == -1 and source.ItemCount == 0. Evaluating the switch conditions in this state produces incorrect results:
case 0:checkslastVisibleItemIndex == source.ItemCount - 1→-1 == 0 - 1→-1 == -1→trueSendRemainingItemsThresholdReached()fires spuriously whenever items are cleared andRemainingItemsThreshold == 0
default:checkssource.ItemCount - 1 - lastVisibleItemIndex <= itemsView.RemainingItemsThreshold→0 - 1 - (-1) <= threshold→0 <= threshold- Fires for any non-negative threshold value when items are cleared
This regression affects any app that uses RemainingItemsThreshold on iOS/MacCatalyst CollectionView.
Recommended Fix: Add a guard after SendScrolled and before the switch in both files:
itemsView.SendScrolled(itemsViewScrolledEventArgs);
PreviousHorizontalOffset = (float)contentOffsetX;
PreviousVerticalOffset = (float)contentOffsetY;
if (!visibleItems)
return;
switch (itemsView.RemainingItemsThreshold)
{
...
}This was also flagged by the Copilot reviewer via inline comments on the PR.
🟡 Suggestions
Test Naming Inconsistency
Files:
src/Controls/tests/TestCases.HostApp/Issues/Issue21708.xamlsrc/Controls/tests/TestCases.HostApp/Issues/Issue21708.xaml.cssrc/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue21708.cs
Problem: The test files are named Issue21708 and use [Issue(IssueTracker.Github, 21708, ...)] in the [Issue] attribute, but this PR fixes issue #26798. Issue #21708 appears to be a related (possibly Android) issue. Future developers searching for tests covering #26798 won't find them by name.
Recommendation: Either:
- Rename files to
Issue26798.*(preferred), or - Add a comment in the
[Issue]attribute explaining the relationship to [iOS]VerticalOffset Not Reset to Zero After Clearing ItemSource in CollectionView #26798
Test Assertion Uses String Comparison
File: src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue21708.cs
Line: Assert.That(App.FindElement("Label").GetText(), Is.GreaterThan("0"));
Problem: Is.GreaterThan("0") performs a lexicographic string comparison, not a numeric one. This works for small positive integers (e.g., "5" > "0" lexicographically), but it is semantically incorrect and fragile (e.g., "10" < "9" lexicographically).
Recommendation: Use Is.Not.EqualTo("0") which is what the assertion actually intends to check (that scroll happened):
Assert.That(App.FindElement("Label").GetText(), Is.Not.EqualTo("0"));Missing Newline at End of Files
Files: All three new test files are missing a newline at end of file:
src/Controls/tests/TestCases.HostApp/Issues/Issue21708.xamlsrc/Controls/tests/TestCases.HostApp/Issues/Issue21708.xaml.cssrc/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue21708.cs
✅ Looks Good
- Core fix is correct and minimal — 2 lines changed per file; ternary replaces early return to correctly report 0 offsets when no items are visible
- Symmetric application — Fix applied to both
Items/iOS/ItemsViewDelegator.cs(legacy handler) andItems2/iOS/ItemsViewDelegator2.cs(CV2 handler), covering all iOS CollectionView configurations PreviousHorizontalOffset/PreviousVerticalOffsetcorrectly reset — BecausecontentOffsetX/Yare assigned 0 and then used to update the previous-offset fields, the delta will be correctly computed on the next scroll after refilling items- Gate verified — Tests were confirmed to FAIL without the fix and PASS with the fix on iOS (per the AI Summary comment on the PR)
- NOTE block present — PR description has the required user-testing note at the top
kubaflo
left a comment
There was a problem hiding this comment.
Hi @devanathan-vaithiyanathan could you please look at the ai summary comment? Thanks!
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 34153Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 34153" |
@kubaflo , I have addressed the AI summary comment. |
…urce While Scrolled (#34153) > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details The offsets (VerticalOffset and HorizontalOffset) were being calculated incrementally and did not reset properly when the ItemsSource changed, leading to incorrect offset values. ### Description of Change <!-- Enter description of the fix in this section --> The change resets the VerticalOffset and HorizontalOffset to 0 when the ItemsSource is updated. This ensures correct offset values after adding or removing items, fixing the issue of incorrect offsets while scrolling. ### Regarding test case The test case was added in PR #26782 , so this PR includes only the iOS fix. ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #26798 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> --------- Co-authored-by: Jakub Florkowski <kubaflo123@gmail.com>
…urce While Scrolled (#34153) > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details The offsets (VerticalOffset and HorizontalOffset) were being calculated incrementally and did not reset properly when the ItemsSource changed, leading to incorrect offset values. ### Description of Change <!-- Enter description of the fix in this section --> The change resets the VerticalOffset and HorizontalOffset to 0 when the ItemsSource is updated. This ensures correct offset values after adding or removing items, fixing the issue of incorrect offsets while scrolling. ### Regarding test case The test case was added in PR #26782 , so this PR includes only the iOS fix. ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #26798 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> --------- Co-authored-by: Jakub Florkowski <kubaflo123@gmail.com>
…urce While Scrolled (#34153) > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details The offsets (VerticalOffset and HorizontalOffset) were being calculated incrementally and did not reset properly when the ItemsSource changed, leading to incorrect offset values. ### Description of Change <!-- Enter description of the fix in this section --> The change resets the VerticalOffset and HorizontalOffset to 0 when the ItemsSource is updated. This ensures correct offset values after adding or removing items, fixing the issue of incorrect offsets while scrolling. ### Regarding test case The test case was added in PR #26782 , so this PR includes only the iOS fix. ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #26798 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> --------- Co-authored-by: Jakub Florkowski <kubaflo123@gmail.com>
…urce While Scrolled (dotnet#34153) > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details The offsets (VerticalOffset and HorizontalOffset) were being calculated incrementally and did not reset properly when the ItemsSource changed, leading to incorrect offset values. ### Description of Change <!-- Enter description of the fix in this section --> The change resets the VerticalOffset and HorizontalOffset to 0 when the ItemsSource is updated. This ensures correct offset values after adding or removing items, fixing the issue of incorrect offsets while scrolling. ### Regarding test case The test case was added in PR dotnet#26782 , so this PR includes only the iOS fix. ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes dotnet#26798 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> --------- Co-authored-by: Jakub Florkowski <kubaflo123@gmail.com>
…urce While Scrolled (#34153) > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details The offsets (VerticalOffset and HorizontalOffset) were being calculated incrementally and did not reset properly when the ItemsSource changed, leading to incorrect offset values. ### Description of Change <!-- Enter description of the fix in this section --> The change resets the VerticalOffset and HorizontalOffset to 0 when the ItemsSource is updated. This ensures correct offset values after adding or removing items, fixing the issue of incorrect offsets while scrolling. ### Regarding test case The test case was added in PR #26782 , so this PR includes only the iOS fix. ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #26798 <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. --> --------- Co-authored-by: Jakub Florkowski <kubaflo123@gmail.com>
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
The offsets (VerticalOffset and HorizontalOffset) were being calculated incrementally and did not reset properly when the ItemsSource changed, leading to incorrect offset values.
Description of Change
The change resets the VerticalOffset and HorizontalOffset to 0 when the ItemsSource is updated. This ensures correct offset values after adding or removing items, fixing the issue of incorrect offsets while scrolling.
Regarding test case
The test case was added in PR #26782 , so this PR includes only the iOS fix.
Issues Fixed
Fixes #26798