Skip to content

[Android] CarouselView: Fix position jump when tapping non-Start aligned Entry - #34532

Merged
kubaflo merged 11 commits into
dotnet:inflight/currentfrom
praveenkumarkarunanithi:fix-13323
Jun 22, 2026
Merged

[Android] CarouselView: Fix position jump when tapping non-Start aligned Entry#34532
kubaflo merged 11 commits into
dotnet:inflight/currentfrom
praveenkumarkarunanithi:fix-13323

Conversation

@praveenkumarkarunanithi

Copy link
Copy Markdown
Contributor

Note

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

Root Cause

On Android, when an Entry inside a CarouselView receives focus, two independent RecyclerView mechanisms trigger unintended horizontal scrolls.
First, requestRectangleOnScreen() is called to ensure the cursor is visible. For Center or End alignment, the cursor’s X position is greater than zero, so RecyclerView initiates a horizontal smooth scroll. With Loop=True, the large virtual item pool amplifies the scroll delta, often jumping to position 0.

Second, LinearLayoutManager.onRequestChildFocus() also triggers a settling scroll on focus. This behavior is correct for lists but incorrect for a full-page pager like CarouselView, where items are never partially visible.

Start alignment is unaffected because the cursor’s X position is zero, so no scroll is triggered.

Description of Change

In MauiCarouselRecyclerView.cs, two overrides were added.
RequestChildRectangleOnScreen now returns false to suppress cursor-driven scroll requests.
RequestChildFocus calls base to preserve normal focus, keyboard, and accessibility behavior, then calls StopScroll() to cancel the unintended scroll side-effect.
Since MauiCarouselRecyclerView is used only by CarouselView, no conditional logic is required. The fix preserves expected focus behavior while preventing incorrect page jumps.

Issues Fixed

Fixes #13323

Tested the behaviour in the following platforms

  • Android
  • Windows
  • iOS
  • Mac

Screenshots

Before Issue Fix After Issue Fix
BeforeFix.25.mov
AfterFix.31.mov

@github-actions

github-actions Bot commented Mar 18, 2026

Copy link
Copy Markdown
Contributor

🚀 Dogfood this PR with:

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

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

Or

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

@praveenkumarkarunanithi praveenkumarkarunanithi added platform/android area-controls-collectionview CollectionView, CarouselView, IndicatorView labels Mar 18, 2026
@dotnet-policy-service dotnet-policy-service Bot added the partner/syncfusion Issues / PR's with Syncfusion collaboration label Mar 18, 2026
@sheiksyedm
sheiksyedm marked this pull request as ready for review March 19, 2026 10:46
Copilot AI review requested due to automatic review settings March 19, 2026 10:46

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Fixes an Android CarouselView page-jump caused by focus/cursor-driven RecyclerView scrolling when tapping a non-Start-aligned Entry, and adds a UI test + repro page for issue #13323.

Changes:

  • Override MauiCarouselRecyclerView focus/rectangle scrolling APIs to suppress/cancel unintended horizontal scrolling.
  • Add a HostApp repro page (entries centered) and new Appium UI tests validating position stability (with/without Loop).
  • Update Android PublicAPI baseline for the new overrides.

Reviewed changes

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

File Description
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue13323.cs Adds Appium UI tests asserting carousel position doesn’t jump after tapping a centered Entry.
src/Controls/tests/TestCases.HostApp/Issues/Issue13323.cs Adds a repro page with two CarouselViews (looping and non-looping) and centered Entry controls.
src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt Records new Android public overrides in the API baseline.
src/Controls/src/Core/Handlers/Items/Android/MauiCarouselRecyclerView.cs Adds overrides to suppress rectangle scroll requests and cancel focus-driven settling scroll.

Comment thread src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt
Comment thread src/Controls/tests/TestCases.HostApp/Issues/Issue13323.cs
Comment thread src/Controls/tests/TestCases.HostApp/Issues/Issue13323.cs
Comment thread src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue13323.cs Outdated
@MauiBot MauiBot added s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) labels Mar 20, 2026

@kubaflo kubaflo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks like the build is not working

@karthikraja-arumugam karthikraja-arumugam added the community ✨ Community Contribution label Mar 24, 2026
@MauiBot MauiBot added s/agent-review-incomplete s/agent-changes-requested AI agent recommends changes - found a better alternative or issues and removed s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-review-incomplete labels Mar 28, 2026
@dotnet dotnet deleted a comment from MauiBot Apr 1, 2026
@sheiksyedm

Copy link
Copy Markdown
Contributor

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

@azure-pipelines

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

@dotnet dotnet deleted a comment from MauiBot Apr 12, 2026
@MauiBot MauiBot added the s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates label Apr 12, 2026
@sheiksyedm

Copy link
Copy Markdown
Contributor

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

@kubaflo

kubaflo commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

/review rerun

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

This comment has been minimized.

@github-actions github-actions Bot added s/agent-review-in-progress AI review is currently running for this PR and removed s/agent-ready-for-rerun AI review has a new PR-author comment or commit and is ready for rerun labels Jun 21, 2026
@MauiBot MauiBot added s/agent-gate-passed AI verified tests catch the bug (fail without fix, pass with fix) s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates and removed s/agent-fix-win AI found a better alternative fix than the PR labels Jun 21, 2026
MauiBot

This comment was marked as outdated.

@MauiBot MauiBot removed the s/agent-review-in-progress AI review is currently running for this PR label Jun 21, 2026
@kubaflo
kubaflo changed the base branch from main to inflight/current June 22, 2026 13:06
@kubaflo
kubaflo merged commit 8995f69 into dotnet:inflight/current Jun 22, 2026
2 of 11 checks passed
@github-actions github-actions Bot added this to the .NET 10 SR9 milestone Jun 22, 2026
PureWeen pushed a commit that referenced this pull request Jun 22, 2026
…gned Entry (#34532)

<!-- Please let the below note in for people that find this PR -->
   > [!NOTE]
   > Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
  Thank you!
 
### Root Cause
On Android, when an `Entry` inside a `CarouselView` receives focus, two
independent `RecyclerView` mechanisms trigger unintended horizontal
scrolls.
First, `requestRectangleOnScreen()` is called to ensure the cursor is
visible. For `Center` or `End` alignment, the cursor’s X position is
greater than zero, so `RecyclerView` initiates a horizontal smooth
scroll. With `Loop=True`, the large virtual item pool amplifies the
scroll delta, often jumping to position 0.

Second, `LinearLayoutManager.onRequestChildFocus()` also triggers a
settling scroll on focus. This behavior is correct for lists but
incorrect for a full-page pager like `CarouselView`, where items are
never partially visible.

`Start` alignment is unaffected because the cursor’s X position is zero,
so no scroll is triggered.
 
### Description of Change
In `MauiCarouselRecyclerView.cs`, two overrides were added.
`RequestChildRectangleOnScreen` now returns `false` to suppress
cursor-driven scroll requests.
`RequestChildFocus` calls `base` to preserve normal focus, keyboard, and
accessibility behavior, then calls `StopScroll()` to cancel the
unintended scroll side-effect.
Since `MauiCarouselRecyclerView` is used only by `CarouselView`, no
conditional logic is required. The fix preserves expected focus behavior
while preventing incorrect page jumps.
 
### Issues Fixed
Fixes #13323   
 
Tested the behaviour in the following platforms
- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Screenshots
| Before Issue Fix | After Issue Fix |
|------------------|-----------------|
| <video width="350" alt="withoutfix"
src="https://github.com/user-attachments/assets/0c35c184-c162-444e-98c2-afef1c48516b"
/> | <video width="350" alt="withfix"
src="https://github.com/user-attachments/assets/4e86e451-e0cc-4dad-be64-b3211b7d2326"
/> |

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>

@MauiBot MauiBot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

AI Review Summary

@praveenkumarkarunanithi — new AI review results are available based on this last commit: 116f4a7. To request a fresh review after new comments or commits, comment /review rerun.

Gate Passed Confidence Low Platform Android


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

Gate Result: ✅ PASSED

Platform: ANDROID · Base: main · Merge base: 4567a055

Test Without Fix (expect FAIL) With Fix (expect PASS)
🖥️ Issue13323 Issue13323 ✅ FAIL — 947s ✅ PASS — 916s
🔴 Without fix — 🖥️ Issue13323: FAIL ✅ · 947s
  Determining projects to restore...
  Restored /home/vsts/work/1/s/src/Controls/src/Core/Controls.Core.csproj (in 8.02 sec).
  Restored /home/vsts/work/1/s/src/Controls/Maps/src/Controls.Maps.csproj (in 7.92 sec).
  Restored /home/vsts/work/1/s/src/Controls/Foldable/src/Controls.Foldable.csproj (in 223 ms).
  Restored /home/vsts/work/1/s/src/Graphics/src/Graphics/Graphics.csproj (in 8 ms).
  Restored /home/vsts/work/1/s/src/Essentials/src/Essentials.csproj (in 14 ms).
  Restored /home/vsts/work/1/s/src/Core/src/Core.csproj (in 39 ms).
  Restored /home/vsts/work/1/s/src/Core/maps/src/Maps.csproj (in 23 ms).
  Restored /home/vsts/work/1/s/src/BlazorWebView/src/Maui/Microsoft.AspNetCore.Components.WebView.Maui.csproj (in 2.53 sec).
  Restored /home/vsts/work/1/s/src/Controls/src/Xaml/Controls.Xaml.csproj (in 31 ms).
  Restored /home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj (in 2.28 sec).
  1 of 11 projects are up-to-date for restore.
  ##vso[build.updatebuildnumber]10.0.90-ci+azdo.14445927
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0-android36.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.90-ci+azdo.14445927
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0-android36.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.90-ci+azdo.14445927
  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.90-ci+azdo.14445927
  Maps -> /home/vsts/work/1/s/artifacts/bin/Maps/Debug/net10.0-android36.0/Microsoft.Maui.Maps.dll
  ##vso[build.updatebuildnumber]10.0.90-ci+azdo.14445927
  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.90-ci+azdo.14445927
  ##vso[build.updatebuildnumber]10.0.90-ci+azdo.14445927
  ##vso[build.updatebuildnumber]10.0.90-ci+azdo.14445927
  Controls.Foldable -> /home/vsts/work/1/s/artifacts/bin/Controls.Foldable/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Foldable.dll
  Microsoft.AspNetCore.Components.WebView.Maui -> /home/vsts/work/1/s/artifacts/bin/Microsoft.AspNetCore.Components.WebView.Maui/Debug/net10.0-android36.0/Microsoft.AspNetCore.Components.WebView.Maui.dll
  Controls.Xaml -> /home/vsts/work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Xaml.dll
  ##vso[build.updatebuildnumber]10.0.90-ci+azdo.14445927
  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.90-ci+azdo.14445927
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.90-ci+azdo.14445927
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.90-ci+azdo.14445927
  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.90-ci+azdo.14445927
  ##vso[build.updatebuildnumber]10.0.90-ci+azdo.14445927
  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.90-ci+azdo.14445927
  ##vso[build.updatebuildnumber]10.0.90-ci+azdo.14445927
  ##vso[build.updatebuildnumber]10.0.90-ci+azdo.14445927
  ##vso[build.updatebuildnumber]10.0.90-ci+azdo.14445927
  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.Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Maps.dll
  Controls.Foldable -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Foldable.dll

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

Time Elapsed 00:09:23.84
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.3 sec).
  Restored /home/vsts/work/1/s/src/TestUtils/src/VisualTestUtils.MagickNet/VisualTestUtils.MagickNet.csproj (in 7.07 sec).
  Restored /home/vsts/work/1/s/src/Controls/tests/TestCases.Android.Tests/Controls.TestCases.Android.Tests.csproj (in 8.52 sec).
  Restored /home/vsts/work/1/s/src/TestUtils/src/UITest.Core/UITest.Core.csproj (in 8 ms).
  Restored /home/vsts/work/1/s/src/TestUtils/src/UITest.Appium/UITest.Appium.csproj (in 3 ms).
  Restored /home/vsts/work/1/s/src/TestUtils/src/UITest.NUnit/UITest.NUnit.csproj (in 1.18 sec).
  Restored /home/vsts/work/1/s/src/Controls/tests/CustomAttributes/Controls.CustomAttributes.csproj (in 5 ms).
  Restored /home/vsts/work/1/s/src/TestUtils/src/UITest.Analyzers/UITest.Analyzers.csproj (in 2.89 sec).
  5 of 13 projects are up-to-date for restore.
  ##vso[build.updatebuildnumber]10.0.90-ci+azdo.14445927
  Controls.CustomAttributes -> /home/vsts/work/1/s/artifacts/bin/Controls.CustomAttributes/Debug/net10.0/Controls.CustomAttributes.dll
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.90-ci+azdo.14445927
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.90-ci+azdo.14445927
  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.90-ci+azdo.14445927
  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.NUnit -> /home/vsts/work/1/s/artifacts/bin/UITest.NUnit/Debug/net10.0/UITest.NUnit.dll
  UITest.Appium -> /home/vsts/work/1/s/artifacts/bin/UITest.Appium/Debug/net10.0/UITest.Appium.dll
  UITest.Analyzers -> /home/vsts/work/1/s/artifacts/bin/UITest.Analyzers/Debug/netstandard2.0/UITest.Analyzers.dll
  Controls.TestCases.Android.Tests -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll
Test run for /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (x64)

Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
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 2 of 2 NUnit test cases using Current Discovery mode, Non-Explicit run
>>>>> 06/22/2026 12:55:33 FixtureSetup for Issue13323(Android)
>>>>> 06/22/2026 12:55:37 CarouselView_EntryTap_DoesNotChangePosition Start
>>>>> 06/22/2026 12:56:07 CarouselView_EntryTap_DoesNotChangePosition Stop
>>>>> 06/22/2026 12:56:14 Log types: logcat, bugreport, server
  Failed CarouselView_EntryTap_DoesNotChangePosition [48 s]
  Error Message:
   System.TimeoutException : Timed out waiting for element...
  Stack Trace:
     at UITest.Appium.HelperExtensions.Wait(Func`1 query, Func`2 satisfactory, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2757
   at UITest.Appium.HelperExtensions.WaitForAtLeastOne(Func`1 query, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2784
   at UITest.Appium.HelperExtensions.WaitForElement(IApp app, String marked, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency, Nullable`1 postTimeout) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 793
   at Microsoft.Maui.AppUITests.Issues.Issue13323.CarouselView_EntryTap_DoesNotChangePosition() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue13323.cs:line 18
   at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
   at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)

>>>>> 06/22/2026 12:56:25 CarouselView_Loop_EntryTap_DoesNotChangePosition Start
>>>>> 06/22/2026 12:56:56 CarouselView_Loop_EntryTap_DoesNotChangePosition Stop
>>>>> 06/22/2026 12:57:03 Log types: logcat, bugreport, server
  Failed CarouselView_Loop_EntryTap_DoesNotChangePosition [48 s]
  Error Message:
   System.TimeoutException : Timed out waiting for element...
  Stack Trace:
     at UITest.Appium.HelperExtensions.Wait(Func`1 query, Func`2 satisfactory, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2757
   at UITest.Appium.HelperExtensions.WaitForAtLeastOne(Func`1 query, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 2784
   at UITest.Appium.HelperExtensions.WaitForElement(IApp app, String marked, String timeoutMessage, Nullable`1 timeout, Nullable`1 retryFrequency, Nullable`1 postTimeout) in /_/src/TestUtils/src/UITest.Appium/HelperExtensions.cs:line 793
   at Microsoft.Maui.AppUITests.Issues.Issue13323.CarouselView_Loop_EntryTap_DoesNotChangePosition() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue13323.cs:line 42
   at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
   at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)

NUnit Adapter 4.5.0.0: Test execution complete
[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.37]   Discovering: Controls.TestCases.Android.Tests
[xUnit.net 00:00:01.12]   Discovered:  Controls.TestCases.Android.Tests
Results File: /home/vsts/work/1/s/CustomAgentLogsTmp/UITests/TestResults/Issue13323.trx

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

🟢 With fix — 🖥️ Issue13323: PASS ✅ · 916s
  Determining projects to restore...
  All projects are up-to-date for restore.
  ##vso[build.updatebuildnumber]10.0.90-ci+azdo.14445927
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0-android36.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.90-ci+azdo.14445927
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0-android36.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.90-ci+azdo.14445927
  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.90-ci+azdo.14445927
  ##vso[build.updatebuildnumber]10.0.90-ci+azdo.14445927
  Maps -> /home/vsts/work/1/s/artifacts/bin/Maps/Debug/net10.0-android36.0/Microsoft.Maui.Maps.dll
  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.90-ci+azdo.14445927
  ##vso[build.updatebuildnumber]10.0.90-ci+azdo.14445927
  ##vso[build.updatebuildnumber]10.0.90-ci+azdo.14445927
  Controls.Foldable -> /home/vsts/work/1/s/artifacts/bin/Controls.Foldable/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Foldable.dll
  Microsoft.AspNetCore.Components.WebView.Maui -> /home/vsts/work/1/s/artifacts/bin/Microsoft.AspNetCore.Components.WebView.Maui/Debug/net10.0-android36.0/Microsoft.AspNetCore.Components.WebView.Maui.dll
  Controls.Xaml -> /home/vsts/work/1/s/artifacts/bin/Controls.Xaml/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Xaml.dll
  ##vso[build.updatebuildnumber]10.0.90-ci+azdo.14445927
  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.90-ci+azdo.14445927
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.90-ci+azdo.14445927
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.90-ci+azdo.14445927
  Core -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.dll
  ##vso[build.updatebuildnumber]10.0.90-ci+azdo.14445927
  Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Maps.dll
  ##vso[build.updatebuildnumber]10.0.90-ci+azdo.14445927
  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.90-ci+azdo.14445927
  ##vso[build.updatebuildnumber]10.0.90-ci+azdo.14445927
  ##vso[build.updatebuildnumber]10.0.90-ci+azdo.14445927
  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.90-ci+azdo.14445927
  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.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:12:46.34
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.90-ci+azdo.14445927
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.90-ci+azdo.14445927
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.90-ci+azdo.14445927
  Core -> /home/vsts/work/1/s/artifacts/bin/Core/Debug/net10.0/Microsoft.Maui.dll
  Controls.CustomAttributes -> /home/vsts/work/1/s/artifacts/bin/Controls.CustomAttributes/Debug/net10.0/Controls.CustomAttributes.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.90-ci+azdo.14445927
  Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
  UITest.Core -> /home/vsts/work/1/s/artifacts/bin/UITest.Core/Debug/net10.0/UITest.Core.dll
  VisualTestUtils -> /home/vsts/work/1/s/artifacts/bin/VisualTestUtils/Debug/netstandard2.0/VisualTestUtils.dll
  UITest.NUnit -> /home/vsts/work/1/s/artifacts/bin/UITest.NUnit/Debug/net10.0/UITest.NUnit.dll
  VisualTestUtils.MagickNet -> /home/vsts/work/1/s/artifacts/bin/VisualTestUtils.MagickNet/Debug/netstandard2.0/VisualTestUtils.MagickNet.dll
  UITest.Appium -> /home/vsts/work/1/s/artifacts/bin/UITest.Appium/Debug/net10.0/UITest.Appium.dll
  UITest.Analyzers -> /home/vsts/work/1/s/artifacts/bin/UITest.Analyzers/Debug/netstandard2.0/UITest.Analyzers.dll
  Controls.TestCases.Android.Tests -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll
Test run for /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (x64)

Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
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 2 of 2 NUnit test cases using Current Discovery mode, Non-Explicit run
>>>>> 06/22/2026 13:12:57 FixtureSetup for Issue13323(Android)
>>>>> 06/22/2026 13:12:58 CarouselView_EntryTap_DoesNotChangePosition Start
>>>>> 06/22/2026 13:13:10 CarouselView_EntryTap_DoesNotChangePosition Stop
  Passed CarouselView_EntryTap_DoesNotChangePosition [11 s]
>>>>> 06/22/2026 13:13:10 CarouselView_Loop_EntryTap_DoesNotChangePosition Start
>>>>> 06/22/2026 13:13:15 CarouselView_Loop_EntryTap_DoesNotChangePosition Stop
  Passed CarouselView_Loop_EntryTap_DoesNotChangePosition [5 s]
NUnit Adapter 4.5.0.0: Test execution complete
[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.68]   Discovered:  Controls.TestCases.Android.Tests
Results File: /home/vsts/work/1/s/CustomAgentLogsTmp/UITests/TestResults/Issue13323.trx

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

📁 Fix files reverted (2 files)
  • src/Controls/src/Core/Handlers/Items/Android/MauiCarouselRecyclerView.cs
  • src/Controls/src/Core/PublicAPI/net-android/PublicAPI.Unshipped.txt

📋 Pre-Flight — Context & Validation

Issue: #13323 - CarouselView on Android does not work if HorizontalTextAlignment in Entry is not Start
PR: #34532 - Android CarouselView Entry focus/rectangle scroll fix
Platforms Affected: Android
Files Changed: 2 implementation, 2 test

Key Findings

  • Local branch pr-review-34532 contains PR #34532 as a squashed commit over origin/main; GitHub CLI is unauthenticated, so PR body, linked issue body, comments, reviews, and CI checks could not be fetched.
  • Implementation changes Android MauiCarouselRecyclerView to suppress child rectangle scroll requests and cancel focus-driven scrolls started from an idle carousel.
  • Regression coverage adds an Android issue page and two CarouselView UI tests for Loop=false and Loop=true with a center-aligned Entry.
  • Applicable test category: CarouselView.

Code Review Summary

Verdict: NEEDS_DISCUSSION
Confidence: low
Errors: 0 | Warnings: 1 | Suggestions: 1

Key code review findings:

  • ⚠️ src/Controls/src/Core/Handlers/Items/Android/MauiCarouselRecyclerView.cs:641RequestChildFocus may not catch asynchronously scheduled RecyclerView focus-scroll paths if ScrollState remains idle immediately after base.RequestChildFocus; however, the RequestChildRectangleOnScreen override likely handles the primary Issue13323 path.
  • 💡 src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue13323.cs:32 — test uses inline #if ANDROID inside test methods for keyboard wait; repo UI-test guidance prefers platform-specific behavior behind helpers.
  • CI status is undetermined because gh is unauthenticated in this environment. Gate result was provided by the caller: Gate ✅ PASSED — tests fail without fix and pass with PR fix.

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #34532 Override RequestChildRectangleOnScreen to return false, and override RequestChildFocus to call StopScroll() if a focus request starts scrolling from idle. ✅ PASSED (Gate) MauiCarouselRecyclerView.cs, Android PublicAPI.Unshipped.txt, UI test files Original PR

🔬 Code Review — Deep Analysis

Code Review — PR #34532

Independent Assessment

What this changes: Android MauiCarouselRecyclerView gains two RecyclerView overrides: RequestChildRectangleOnScreen returns false, blocking child-initiated rectangle scroll requests such as EditText cursor positioning, and RequestChildFocus calls base.RequestChildFocus then calls StopScroll() if the carousel transitioned from idle to scrolling due to the focus event. Public API entries are registered. Two UI tests cover Loop=false and Loop=true.

Inferred motivation: CarouselView on Android unexpectedly scrolls to a different page when an embedded center-aligned Entry is tapped. RecyclerView's default child focus/rectangle behavior tries to bring the focused child or cursor rectangle into view, which is wrong for a pager-style CarouselView that owns its page position.

Reconciliation with PR Narrative

Author claims: GitHub CLI authentication is unavailable in this environment, so the PR body and linked issue text could not be fetched.

Agreement/disagreement: The local diff is consistent with the inferred issue: the fix targets Android RecyclerView child focus and rectangle-scroll paths, and the tests exercise tapping a center-aligned Entry without changing CarouselView position.

Prior Review Reconciliation

Prior ❌ Error Finding Source Status Evidence
(unavailable) GitHub review/comment surfaces 🔄 Cannot verify gh is unauthenticated (gh auth login required), so top-level reviews, inline comments, and issue comments could not be queried.

Blast Radius Assessment

  • Runs for all instances: No. The new methods run only when a child requests focus or requests a rectangle to be scrolled on screen.
  • Startup impact: No.
  • Static/shared state: No static or shared state introduced.
  • Platform scope: Android-only active CarouselView handler in Handlers/Items/Android.

CI Status

  • Required-check result: undetermined
  • Classification: tool unavailable
  • Action taken: confidence capped at low. The caller supplied the gate result separately: Gate ✅ PASSED.

Findings

⚠️ Warning — RequestChildFocus StopScroll may miss asynchronous focus-scroll paths

src/Controls/src/Core/Handlers/Items/Android/MauiCarouselRecyclerView.cs:641-652

base.RequestChildFocus can schedule scrolling asynchronously. If ScrollState is still ScrollStateIdle immediately after the base call, the StopScroll() branch does not run. This likely does not invalidate the PR because RequestChildRectangleOnScreen returning false appears to suppress the primary cursor-rectangle path, but it makes the second override a best-effort safeguard rather than a complete independent interception point.

💡 Suggestion — Avoid inline platform directives in UI test methods

src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue13323.cs:32-35 and src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue13323.cs:56-59

The repository UI-test guidance prefers platform-specific behavior behind extension helpers instead of inline #if ANDROID directives inside test methods. This is test readability guidance, not a correctness blocker.

Failure-Mode Probing

  • What happens when a child control that is not an Entry calls RequestChildRectangleOnScreen? The PR suppresses it too. For a full-page pager this is defensible, but it is broader than the exact Entry cursor scenario.
  • What happens if the user is already dragging? RequestChildFocus does not call StopScroll() when the carousel was not idle before focus, preserving user-driven swipes.
  • Does focus still propagate? Yes, the PR calls base.RequestChildFocus, so Entry focus/keyboard behavior should continue while only the scroll side effect is suppressed.
  • Does loop mode need a separate handler implementation? No. Android has only the Items/Android implementation; Items2 is iOS/MacCatalyst-only.

Verdict: NEEDS_DISCUSSION

Confidence: low
Summary: The Android fix is technically plausible and localized, and the supplied gate result indicates the regression tests validate the PR fix. Confidence remains low because GitHub context and CI checks are unavailable here, and because the RequestChildFocus safeguard may not catch asynchronous focus-scroll paths independently of the rectangle-scroll override.


🛠️ Fix — Analysis & Comparison

Fix Candidates

# Source Approach Test Result Files Changed Notes
1 try-fix Minimal rectangle suppression: only override RequestChildRectangleOnScreen to return false; remove RequestChildFocus. ⚠️ Blocked 2 files Timed out during Android HostApp build/deploy before tests executed. Simpler but may miss RecyclerView internal focus path.
2 try-fix Focus-only deferred cancel: override RequestChildFocus and Post(StopScroll) after idle focus requests; no rectangle suppression. ⚠️ Blocked 2 files Timed out during Android HostApp build/deploy before tests executed. Handles async focus scrolling but may miss direct rectangle requests and may over-cancel focus requests.
3 try-fix Text-input-only rectangle suppression: suppress rectangle requests only when an EditText is involved; remove RequestChildFocus. ⚠️ Blocked 2 files Timed out during Android HostApp build/deploy before tests executed. Narrower blast radius but likely misses container/internal focus paths.
PR PR #34532 Unconditionally suppress child rectangle scrolling and cancel focus-started scrolls when focus moves from idle to non-idle. ✅ PASSED (Gate) 4 files Original PR. Gate result supplied by caller: tests fail without fix and pass with PR fix.

Cross-Pollination

Model Round New Ideas? Details
maui-expert-reviewer 1 Yes Suggested the meaningful strategy space: minimal rectangle suppression, focus-only/deferred cancellation, conditional text-input suppression, plus a LayoutManager-level variant.
maui-expert-reviewer 2 No After reviewing attempts and environment-blocked results, concluded remaining ideas are equivalent or riskier variants of the PR fix/candidates.

Exhausted: Yes
Selected Fix: PR #34532 — It is the only fix with a supplied passing gate result. None of the alternative candidates reached test execution in this environment, and expert review found no remaining non-trivial approach likely to be better than the PR's combined rectangle + focus-path coverage.


🏁 Report — Final Recommendation

Comparative Report — PR #34532

Candidates Compared

Rank Candidate Result Assessment
1 pr ✅ Passed supplied gate Best candidate. It combines both relevant RecyclerView interception points: child rectangle scroll suppression and focus-scroll cancellation while preserving focus propagation. The Android regression tests fail without the PR and pass with it.
2 pr-plus-reviewer ✅ Equivalent to pr Expert review found no actionable changes to apply, so this candidate is functionally identical to pr. It ranks below pr only because it adds no improvement over the raw PR fix.
3 try-fix-1 ⚠️ Blocked / not validated Simpler rectangle-only suppression, but it drops the focus-scroll safeguard and never reached test execution. It is less robust than the passing PR candidate.
4 try-fix-3 ⚠️ Blocked / not validated Narrower text-input-only rectangle suppression, but it can miss container/internal request paths and drops the focus-scroll safeguard. It never reached test execution.
5 try-fix-2 ⚠️ Blocked / not validated Focus-only deferred cancellation may catch async focus scrolls, but it does not block direct cursor rectangle requests and posts StopScroll after every idle focus request. It never reached test execution.

Decision

Winner: pr

The raw PR fix is the only non-equivalent candidate with a supplied passing regression gate. It addresses both root-cause paths described by the PR: EditText/cursor rectangle requests and RecyclerView focus-driven scroll side effects. All try-fix candidates were blocked before test execution, so they cannot outrank a candidate with demonstrated fail-without/pass-with evidence.

Risk Notes

  • The PR's behavior change is Android-only and localized to MauiCarouselRecyclerView.
  • Suppressing child rectangle requests is broad, but appropriate for a full-page pager where child controls should not move the carousel page.
  • RequestChildFocus calls base first, preserving normal focus, keyboard, and accessibility propagation before cancelling unintended carousel scroll side effects.

🧭 Next Steps — review latest findings

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

kubaflo added a commit that referenced this pull request Jun 25, 2026
…gned Entry (#34532)

<!-- Please let the below note in for people that find this PR -->
   > [!NOTE]
   > Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
  Thank you!
 
### Root Cause
On Android, when an `Entry` inside a `CarouselView` receives focus, two
independent `RecyclerView` mechanisms trigger unintended horizontal
scrolls.
First, `requestRectangleOnScreen()` is called to ensure the cursor is
visible. For `Center` or `End` alignment, the cursor’s X position is
greater than zero, so `RecyclerView` initiates a horizontal smooth
scroll. With `Loop=True`, the large virtual item pool amplifies the
scroll delta, often jumping to position 0.

Second, `LinearLayoutManager.onRequestChildFocus()` also triggers a
settling scroll on focus. This behavior is correct for lists but
incorrect for a full-page pager like `CarouselView`, where items are
never partially visible.

`Start` alignment is unaffected because the cursor’s X position is zero,
so no scroll is triggered.
 
### Description of Change
In `MauiCarouselRecyclerView.cs`, two overrides were added.
`RequestChildRectangleOnScreen` now returns `false` to suppress
cursor-driven scroll requests.
`RequestChildFocus` calls `base` to preserve normal focus, keyboard, and
accessibility behavior, then calls `StopScroll()` to cancel the
unintended scroll side-effect.
Since `MauiCarouselRecyclerView` is used only by `CarouselView`, no
conditional logic is required. The fix preserves expected focus behavior
while preventing incorrect page jumps.
 
### Issues Fixed
Fixes #13323   
 
Tested the behaviour in the following platforms
- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Screenshots
| Before Issue Fix | After Issue Fix |
|------------------|-----------------|
| <video width="350" alt="withoutfix"
src="https://github.com/user-attachments/assets/0c35c184-c162-444e-98c2-afef1c48516b"
/> | <video width="350" alt="withfix"
src="https://github.com/user-attachments/assets/4e86e451-e0cc-4dad-be64-b3211b7d2326"
/> |

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
kubaflo added a commit that referenced this pull request Jul 3, 2026
…gned Entry (#34532)

<!-- Please let the below note in for people that find this PR -->
   > [!NOTE]
   > Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
  Thank you!
 
### Root Cause
On Android, when an `Entry` inside a `CarouselView` receives focus, two
independent `RecyclerView` mechanisms trigger unintended horizontal
scrolls.
First, `requestRectangleOnScreen()` is called to ensure the cursor is
visible. For `Center` or `End` alignment, the cursor’s X position is
greater than zero, so `RecyclerView` initiates a horizontal smooth
scroll. With `Loop=True`, the large virtual item pool amplifies the
scroll delta, often jumping to position 0.

Second, `LinearLayoutManager.onRequestChildFocus()` also triggers a
settling scroll on focus. This behavior is correct for lists but
incorrect for a full-page pager like `CarouselView`, where items are
never partially visible.

`Start` alignment is unaffected because the cursor’s X position is zero,
so no scroll is triggered.
 
### Description of Change
In `MauiCarouselRecyclerView.cs`, two overrides were added.
`RequestChildRectangleOnScreen` now returns `false` to suppress
cursor-driven scroll requests.
`RequestChildFocus` calls `base` to preserve normal focus, keyboard, and
accessibility behavior, then calls `StopScroll()` to cancel the
unintended scroll side-effect.
Since `MauiCarouselRecyclerView` is used only by `CarouselView`, no
conditional logic is required. The fix preserves expected focus behavior
while preventing incorrect page jumps.
 
### Issues Fixed
Fixes #13323   
 
Tested the behaviour in the following platforms
- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Screenshots
| Before Issue Fix | After Issue Fix |
|------------------|-----------------|
| <video width="350" alt="withoutfix"
src="https://github.com/user-attachments/assets/0c35c184-c162-444e-98c2-afef1c48516b"
/> | <video width="350" alt="withfix"
src="https://github.com/user-attachments/assets/4e86e451-e0cc-4dad-be64-b3211b7d2326"
/> |

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
@kubaflo kubaflo mentioned this pull request Jul 6, 2026
kubaflo added a commit that referenced this pull request Jul 6, 2026
…gned Entry (#34532)

<!-- Please let the below note in for people that find this PR -->
   > [!NOTE]
   > Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
  Thank you!
 
### Root Cause
On Android, when an `Entry` inside a `CarouselView` receives focus, two
independent `RecyclerView` mechanisms trigger unintended horizontal
scrolls.
First, `requestRectangleOnScreen()` is called to ensure the cursor is
visible. For `Center` or `End` alignment, the cursor’s X position is
greater than zero, so `RecyclerView` initiates a horizontal smooth
scroll. With `Loop=True`, the large virtual item pool amplifies the
scroll delta, often jumping to position 0.

Second, `LinearLayoutManager.onRequestChildFocus()` also triggers a
settling scroll on focus. This behavior is correct for lists but
incorrect for a full-page pager like `CarouselView`, where items are
never partially visible.

`Start` alignment is unaffected because the cursor’s X position is zero,
so no scroll is triggered.
 
### Description of Change
In `MauiCarouselRecyclerView.cs`, two overrides were added.
`RequestChildRectangleOnScreen` now returns `false` to suppress
cursor-driven scroll requests.
`RequestChildFocus` calls `base` to preserve normal focus, keyboard, and
accessibility behavior, then calls `StopScroll()` to cancel the
unintended scroll side-effect.
Since `MauiCarouselRecyclerView` is used only by `CarouselView`, no
conditional logic is required. The fix preserves expected focus behavior
while preventing incorrect page jumps.
 
### Issues Fixed
Fixes #13323   
 
Tested the behaviour in the following platforms
- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Screenshots
| Before Issue Fix | After Issue Fix |
|------------------|-----------------|
| <video width="350" alt="withoutfix"
src="https://github.com/user-attachments/assets/0c35c184-c162-444e-98c2-afef1c48516b"
/> | <video width="350" alt="withfix"
src="https://github.com/user-attachments/assets/4e86e451-e0cc-4dad-be64-b3211b7d2326"
/> |

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
PureWeen pushed a commit that referenced this pull request Jul 7, 2026
…gned Entry (#34532)

<!-- Please let the below note in for people that find this PR -->
   > [!NOTE]
   > Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
  Thank you!
 
### Root Cause
On Android, when an `Entry` inside a `CarouselView` receives focus, two
independent `RecyclerView` mechanisms trigger unintended horizontal
scrolls.
First, `requestRectangleOnScreen()` is called to ensure the cursor is
visible. For `Center` or `End` alignment, the cursor’s X position is
greater than zero, so `RecyclerView` initiates a horizontal smooth
scroll. With `Loop=True`, the large virtual item pool amplifies the
scroll delta, often jumping to position 0.

Second, `LinearLayoutManager.onRequestChildFocus()` also triggers a
settling scroll on focus. This behavior is correct for lists but
incorrect for a full-page pager like `CarouselView`, where items are
never partially visible.

`Start` alignment is unaffected because the cursor’s X position is zero,
so no scroll is triggered.
 
### Description of Change
In `MauiCarouselRecyclerView.cs`, two overrides were added.
`RequestChildRectangleOnScreen` now returns `false` to suppress
cursor-driven scroll requests.
`RequestChildFocus` calls `base` to preserve normal focus, keyboard, and
accessibility behavior, then calls `StopScroll()` to cancel the
unintended scroll side-effect.
Since `MauiCarouselRecyclerView` is used only by `CarouselView`, no
conditional logic is required. The fix preserves expected focus behavior
while preventing incorrect page jumps.
 
### Issues Fixed
Fixes #13323   
 
Tested the behaviour in the following platforms
- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Screenshots
| Before Issue Fix | After Issue Fix |
|------------------|-----------------|
| <video width="350" alt="withoutfix"
src="https://github.com/user-attachments/assets/0c35c184-c162-444e-98c2-afef1c48516b"
/> | <video width="350" alt="withfix"
src="https://github.com/user-attachments/assets/4e86e451-e0cc-4dad-be64-b3211b7d2326"
/> |

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
PureWeen pushed a commit that referenced this pull request Jul 7, 2026
…gned Entry (#34532)

<!-- Please let the below note in for people that find this PR -->
   > [!NOTE]
   > Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
  Thank you!
 
### Root Cause
On Android, when an `Entry` inside a `CarouselView` receives focus, two
independent `RecyclerView` mechanisms trigger unintended horizontal
scrolls.
First, `requestRectangleOnScreen()` is called to ensure the cursor is
visible. For `Center` or `End` alignment, the cursor’s X position is
greater than zero, so `RecyclerView` initiates a horizontal smooth
scroll. With `Loop=True`, the large virtual item pool amplifies the
scroll delta, often jumping to position 0.

Second, `LinearLayoutManager.onRequestChildFocus()` also triggers a
settling scroll on focus. This behavior is correct for lists but
incorrect for a full-page pager like `CarouselView`, where items are
never partially visible.

`Start` alignment is unaffected because the cursor’s X position is zero,
so no scroll is triggered.
 
### Description of Change
In `MauiCarouselRecyclerView.cs`, two overrides were added.
`RequestChildRectangleOnScreen` now returns `false` to suppress
cursor-driven scroll requests.
`RequestChildFocus` calls `base` to preserve normal focus, keyboard, and
accessibility behavior, then calls `StopScroll()` to cancel the
unintended scroll side-effect.
Since `MauiCarouselRecyclerView` is used only by `CarouselView`, no
conditional logic is required. The fix preserves expected focus behavior
while preventing incorrect page jumps.
 
### Issues Fixed
Fixes #13323   
 
Tested the behaviour in the following platforms
- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Screenshots
| Before Issue Fix | After Issue Fix |
|------------------|-----------------|
| <video width="350" alt="withoutfix"
src="https://github.com/user-attachments/assets/0c35c184-c162-444e-98c2-afef1c48516b"
/> | <video width="350" alt="withfix"
src="https://github.com/user-attachments/assets/4e86e451-e0cc-4dad-be64-b3211b7d2326"
/> |

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
kubaflo added a commit that referenced this pull request Jul 10, 2026
…gned Entry (#34532)

<!-- Please let the below note in for people that find this PR -->
   > [!NOTE]
   > Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
  Thank you!
 
### Root Cause
On Android, when an `Entry` inside a `CarouselView` receives focus, two
independent `RecyclerView` mechanisms trigger unintended horizontal
scrolls.
First, `requestRectangleOnScreen()` is called to ensure the cursor is
visible. For `Center` or `End` alignment, the cursor’s X position is
greater than zero, so `RecyclerView` initiates a horizontal smooth
scroll. With `Loop=True`, the large virtual item pool amplifies the
scroll delta, often jumping to position 0.

Second, `LinearLayoutManager.onRequestChildFocus()` also triggers a
settling scroll on focus. This behavior is correct for lists but
incorrect for a full-page pager like `CarouselView`, where items are
never partially visible.

`Start` alignment is unaffected because the cursor’s X position is zero,
so no scroll is triggered.
 
### Description of Change
In `MauiCarouselRecyclerView.cs`, two overrides were added.
`RequestChildRectangleOnScreen` now returns `false` to suppress
cursor-driven scroll requests.
`RequestChildFocus` calls `base` to preserve normal focus, keyboard, and
accessibility behavior, then calls `StopScroll()` to cancel the
unintended scroll side-effect.
Since `MauiCarouselRecyclerView` is used only by `CarouselView`, no
conditional logic is required. The fix preserves expected focus behavior
while preventing incorrect page jumps.
 
### Issues Fixed
Fixes #13323   
 
Tested the behaviour in the following platforms
- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Screenshots
| Before Issue Fix | After Issue Fix |
|------------------|-----------------|
| <video width="350" alt="withoutfix"
src="https://github.com/user-attachments/assets/0c35c184-c162-444e-98c2-afef1c48516b"
/> | <video width="350" alt="withfix"
src="https://github.com/user-attachments/assets/4e86e451-e0cc-4dad-be64-b3211b7d2326"
/> |

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
kubaflo added a commit that referenced this pull request Jul 15, 2026
…gned Entry (#34532)

<!-- Please let the below note in for people that find this PR -->
   > [!NOTE]
   > Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
  Thank you!
 
### Root Cause
On Android, when an `Entry` inside a `CarouselView` receives focus, two
independent `RecyclerView` mechanisms trigger unintended horizontal
scrolls.
First, `requestRectangleOnScreen()` is called to ensure the cursor is
visible. For `Center` or `End` alignment, the cursor’s X position is
greater than zero, so `RecyclerView` initiates a horizontal smooth
scroll. With `Loop=True`, the large virtual item pool amplifies the
scroll delta, often jumping to position 0.

Second, `LinearLayoutManager.onRequestChildFocus()` also triggers a
settling scroll on focus. This behavior is correct for lists but
incorrect for a full-page pager like `CarouselView`, where items are
never partially visible.

`Start` alignment is unaffected because the cursor’s X position is zero,
so no scroll is triggered.
 
### Description of Change
In `MauiCarouselRecyclerView.cs`, two overrides were added.
`RequestChildRectangleOnScreen` now returns `false` to suppress
cursor-driven scroll requests.
`RequestChildFocus` calls `base` to preserve normal focus, keyboard, and
accessibility behavior, then calls `StopScroll()` to cancel the
unintended scroll side-effect.
Since `MauiCarouselRecyclerView` is used only by `CarouselView`, no
conditional logic is required. The fix preserves expected focus behavior
while preventing incorrect page jumps.
 
### Issues Fixed
Fixes #13323   
 
Tested the behaviour in the following platforms
- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Screenshots
| Before Issue Fix | After Issue Fix |
|------------------|-----------------|
| <video width="350" alt="withoutfix"
src="https://github.com/user-attachments/assets/0c35c184-c162-444e-98c2-afef1c48516b"
/> | <video width="350" alt="withfix"
src="https://github.com/user-attachments/assets/4e86e451-e0cc-4dad-be64-b3211b7d2326"
/> |

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
kubaflo added a commit that referenced this pull request Jul 22, 2026
…gned Entry (#34532)

<!-- Please let the below note in for people that find this PR -->
   > [!NOTE]
   > Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
  Thank you!
 
### Root Cause
On Android, when an `Entry` inside a `CarouselView` receives focus, two
independent `RecyclerView` mechanisms trigger unintended horizontal
scrolls.
First, `requestRectangleOnScreen()` is called to ensure the cursor is
visible. For `Center` or `End` alignment, the cursor’s X position is
greater than zero, so `RecyclerView` initiates a horizontal smooth
scroll. With `Loop=True`, the large virtual item pool amplifies the
scroll delta, often jumping to position 0.

Second, `LinearLayoutManager.onRequestChildFocus()` also triggers a
settling scroll on focus. This behavior is correct for lists but
incorrect for a full-page pager like `CarouselView`, where items are
never partially visible.

`Start` alignment is unaffected because the cursor’s X position is zero,
so no scroll is triggered.
 
### Description of Change
In `MauiCarouselRecyclerView.cs`, two overrides were added.
`RequestChildRectangleOnScreen` now returns `false` to suppress
cursor-driven scroll requests.
`RequestChildFocus` calls `base` to preserve normal focus, keyboard, and
accessibility behavior, then calls `StopScroll()` to cancel the
unintended scroll side-effect.
Since `MauiCarouselRecyclerView` is used only by `CarouselView`, no
conditional logic is required. The fix preserves expected focus behavior
while preventing incorrect page jumps.
 
### Issues Fixed
Fixes #13323   
 
Tested the behaviour in the following platforms
- [x] Android
- [x] Windows
- [x] iOS
- [x] Mac

### Screenshots
| Before Issue Fix | After Issue Fix |
|------------------|-----------------|
| <video width="350" alt="withoutfix"
src="https://github.com/user-attachments/assets/0c35c184-c162-444e-98c2-afef1c48516b"
/> | <video width="350" alt="withfix"
src="https://github.com/user-attachments/assets/4e86e451-e0cc-4dad-be64-b3211b7d2326"
/> |

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Jakub Florkowski <42434498+kubaflo@users.noreply.github.com>
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 23, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-controls-collectionview CollectionView, CarouselView, IndicatorView community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration platform/android 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.

CarouselView on Android does not work if HorizontalTextAlignment in Entry is not Start

7 participants