[Android] Fix CollectionView dynamic item sizing reset after scroll#34882
[Android] Fix CollectionView dynamic item sizing reset after scroll#34882kubaflo merged 3 commits intodotnet:mainfrom
Conversation
…e scrollbar, all images will automatically return to their original size
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 34882Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 34882" |
There was a problem hiding this comment.
Pull request overview
Fixes an Android CollectionView regression where dynamically resized item views reset to their original size after being scrolled off-screen and recycled.
Changes:
- Adjusts
TemplatedItemViewHolder.Recycle()/Bind()to preserve the MAUI view instance across recycle and re-realize platform content when the handler has been disconnected. - Adds a HostApp reproduction page for Issue #34783 (dynamic image resizing in a CollectionView).
- Adds an Appium/NUnit UI test intended to verify the resized state persists after scroll/recycle.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
src/Controls/src/Core/Handlers/Items/Android/TemplatedItemViewHolder.cs |
Preserves View/_selectedTemplate across recycle and reconnects platform content when rebinding with the same template. |
src/Controls/tests/TestCases.HostApp/Issues/Issue34783.cs |
Adds a HostApp issue page that reproduces dynamic item resizing and scroll/recycle behavior. |
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34783.cs |
Adds a UI test to validate image size persists after scrolling/recycling. |
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34783.cs
Outdated
Show resolved
Hide resolved
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34783.cs
Outdated
Show resolved
Hide resolved
🚦 Gate - Test Before and After Fix📊 Expand Full Gate —
|
| Test | Without Fix (expect FAIL) | With Fix (expect PASS) |
|---|---|---|
🖥️ Issue34783 Issue34783 |
✅ PASS — 529s |
🔴 Without fix — 🖥️ Issue34783: ⚠️ ENV ERROR · 1698s
(truncated to last 15,000 chars)
stCases.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:15:54.43
* 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.13787373
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.13787373
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.13787373
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.13787373
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13787373
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.60-ci+azdo.13787373
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13787373
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13787373
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
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13787373
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.13787373
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.13787373
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.13787373
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.13787373
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13787373
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.13787373
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13787373
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13787373
Controls.Foldable -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Foldable.dll
Controls.Xaml -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Xaml.dll
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.13787373
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:36.14
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 957 ms).
Restored /home/vsts/work/1/s/src/TestUtils/src/UITest.NUnit/UITest.NUnit.csproj (in 854 ms).
Restored /home/vsts/work/1/s/src/TestUtils/src/UITest.Core/UITest.Core.csproj (in 3 ms).
Restored /home/vsts/work/1/s/src/TestUtils/src/UITest.Appium/UITest.Appium.csproj (in 2 sec).
Restored /home/vsts/work/1/s/src/TestUtils/src/VisualTestUtils.MagickNet/VisualTestUtils.MagickNet.csproj (in 5.09 sec).
Restored /home/vsts/work/1/s/src/TestUtils/src/UITest.Analyzers/UITest.Analyzers.csproj (in 2.3 sec).
Restored /home/vsts/work/1/s/src/Controls/tests/CustomAttributes/Controls.CustomAttributes.csproj (in 4 ms).
Restored /home/vsts/work/1/s/src/Controls/tests/TestCases.Android.Tests/Controls.TestCases.Android.Tests.csproj (in 1.88 sec).
5 of 13 projects are up-to-date for restore.
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13787373
Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13787373
Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13787373
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.13787373
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.11] Discovering: Controls.TestCases.Android.Tests
[xUnit.net 00:00:00.31] 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
>>>>> 04/09/2026 11:20:03 FixtureSetup for Issue34783(Android)
>>>>> 04/09/2026 11:20:06 ImagesKeepSizeAfterScrolling Start
>>>>> 04/09/2026 11:20:17 ImagesKeepSizeAfterScrolling Stop
>>>>> 04/09/2026 11:20:17 Log types: logcat, bugreport, server
Failed ImagesKeepSizeAfterScrolling [12 s]
Error Message:
Image should keep its enlarged size after scrolling; resetting to original size is the bug
Assert.That(afterScrollRect.Height, Is.GreaterThan(initialRect.Height))
Expected: greater than 158
But was: 158
Stack Trace:
at Microsoft.Maui.TestCases.Tests.Issues.Issue34783.ImagesKeepSizeAfterScrolling() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34783.cs:line 50
1) at Microsoft.Maui.TestCases.Tests.Issues.Issue34783.ImagesKeepSizeAfterScrolling() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue34783.cs:line 50
NUnit Adapter 4.5.0.0: Test execution complete
Test Run Failed.
Total tests: 1
Failed: 1
Total time: 38.0649 Seconds
🟢 With fix — 🖥️ Issue34783: PASS ✅ · 529s
Determining projects to restore...
All projects are up-to-date for restore.
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13787373
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.13787373
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.13787373
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.13787373
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.13787373
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.13787373
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13787373
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13787373
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13787373
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
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.13787373
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.13787373
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.13787373
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.13787373
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13787373
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.13787373
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13787373
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13787373
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13787373
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
Microsoft.AspNetCore.Components.WebView.Maui -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.AspNetCore.Components.WebView.Maui.dll
Controls.Xaml -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Xaml.dll
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:06:49.77
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.13787373
Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13787373
Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.60-ci+azdo.13787373
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.60-ci+azdo.13787373
Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
UITest.Core -> /home/vsts/work/1/s/artifacts/bin/UITest.Core/Debug/net10.0/UITest.Core.dll
UITest.Appium -> /home/vsts/work/1/s/artifacts/bin/UITest.Appium/Debug/net10.0/UITest.Appium.dll
UITest.NUnit -> /home/vsts/work/1/s/artifacts/bin/UITest.NUnit/Debug/net10.0/UITest.NUnit.dll
VisualTestUtils -> /home/vsts/work/1/s/artifacts/bin/VisualTestUtils/Debug/netstandard2.0/VisualTestUtils.dll
VisualTestUtils.MagickNet -> /home/vsts/work/1/s/artifacts/bin/VisualTestUtils.MagickNet/Debug/netstandard2.0/VisualTestUtils.MagickNet.dll
UITest.Analyzers -> /home/vsts/work/1/s/artifacts/bin/UITest.Analyzers/Debug/netstandard2.0/UITest.Analyzers.dll
Controls.TestCases.Android.Tests -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll
Test run for /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (x64)
Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
/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.12] Discovering: Controls.TestCases.Android.Tests
[xUnit.net 00:00:00.32] 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
>>>>> 04/09/2026 11:29:26 FixtureSetup for Issue34783(Android)
>>>>> 04/09/2026 11:29:29 ImagesKeepSizeAfterScrolling Start
>>>>> 04/09/2026 11:29:39 ImagesKeepSizeAfterScrolling Stop
Passed ImagesKeepSizeAfterScrolling [10 s]
NUnit Adapter 4.5.0.0: Test execution complete
Test Run Successful.
Total tests: 1
Passed: 1
Total time: 24.6209 Seconds
⚠️ Issues found
⚠️ Issue34783 without fix:Exception calling "Matches" with "2" argument(s): "Value cannot be null. (Parameter 'input')"
📁 Fix files reverted (2 files)
eng/pipelines/ci-copilot.ymlsrc/Controls/src/Core/Handlers/Items/Android/TemplatedItemViewHolder.cs
|
/azp run maui-pr-uitests, maui-pr-devicetests |
|
Azure Pipelines successfully started running 2 pipeline(s). |
🧪 PR Test EvaluationOverall Verdict: The test covers the primary fix scenario well (resize → scroll → verify size preserved), but uses
📊 Expand Full EvaluationPR Test Evaluation ReportPR: #34882 — CollectionView Dynamic item sizing - After dragging the scrollbar, all images return to their original size Overall VerdictThe core scenario is well covered: tap to resize, scroll to trigger RecyclerView recycling, scroll back, verify the size was preserved. However, 1. Fix Coverage — ✅The fix changes
The test would fail if the fix were reverted. ✅ 2. Edge Cases & Gaps —
|
| Risk Factor | Status |
|---|---|
TapCoordinates to hit image |
|
No stable AutomationId on tapped image |
"Baboon" name, not a static ID |
Multiple ScrollUp calls to return to top |
|
No retryTimeout on WaitForElement after scrolling |
Low — not a screenshot test; element presence assertion is adequate |
ScrollStrategy.Gesture |
Accepted pattern in MAUI UI tests; low risk |
Recommendation: Replace TapCoordinates with a stable approach. One option is to add a dedicated Button or use a TapGestureRecognizer on an Image that has a static AutomationId separate from the data-bound name. Another is to keep the image name binding and add a static AutomationId prefix (e.g., $"img_{Name}").
6. Duplicate Coverage — ✅ No duplicates
No existing test covers this exact scenario (dynamic HeightRequest surviving RecyclerView recycling). The listed similar tests (Issue10025, Issue11896, Issue15173, CollectionViewUITests.HiddenCollectionViewBind) cover unrelated scenarios.
7. Platform Scope — ✅
- Fix is in
src/Controls/src/Core/Handlers/Items/Android/TemplatedItemViewHolder.cs— Android-only. - HostApp page:
PlatformAffected.Android. - The
#if TEST_FAILS_ON_CATALYSTguard excludes MacCatalyst. The test runs on Android and iOS (though the bug is Android-specific, running on iOS is harmless). - Platform scope is appropriate. ✅
8. Assertion Quality — ✅
Assert.That(enlargedRect.Height, Is.GreaterThan(initialRect.Height), "...");
Assert.That(afterScrollRect.Height, Is.GreaterThan(initialRect.Height), "...");- Uses relative comparisons (
GreaterThan) rather than hardcoded pixel values — robust across screen sizes. ✅ - Both assertions include descriptive failure messages. ✅
- Two assertions: one confirms the tap worked (precondition), one tests the actual fix. Good structure. ✅
9. Fix-Test Alignment — ✅
The fix is in TemplatedItemViewHolder.Bind() / Recycle() — the Android ViewHolder for CollectionView items. The test uses a CollectionView with a DataTemplate (matching _template / _selectedTemplate) and triggers recycling via scroll gestures. The test precisely exercises the changed code path. ✅
Recommendations
-
Replace
TapCoordinateswith a stable AutomationId-based tap. Add a staticAutomationIdto the image (e.g.,"FirstMonkeyImage") rather than relying on the data-bound name"Baboon". This decouples the test from the test data and makes the AutomationId reference explicit in source code. -
Optionally add a "resize back" + scroll sub-step. After verifying the enlarged size is preserved, tap again (shrink back to 60) and scroll once more — verifying bidirectional sizing works and the fix didn't introduce a one-way persistence issue.
-
Clarify the
#if TEST_FAILS_ON_CATALYSTintent. Since this is an Android-only fix (PlatformAffected.Android), consider whether the MacCatalyst guard is needed. If the test is intended to only run on Android, the HostApp[Issue]attribute already scopes it. The#ifguard primarily protects against CI flakiness on Catalyst, which is valid — but the comment could note that the test is primarily meaningful on Android.
Note
🔒 Integrity filtering filtered 2 items
Integrity filtering activated and filtered the following items during workflow execution.
This happens when a tool call accesses a resource that does not meet the required integrity or secrecy level of the workflow.
- pr:[Android] Fix CollectionView dynamic item sizing reset after scroll #34882 (
pull_request_read: Resource 'pr:[Android] Fix CollectionView dynamic item sizing reset after scroll #34882' has lower integrity than agent requires. Agent would need to drop integrity tags [unapproved:all approved:all] to trust this resource.) - pr:[Android] Fix CollectionView dynamic item sizing reset after scroll #34882 (
pull_request_read: Resource 'pr:[Android] Fix CollectionView dynamic item sizing reset after scroll #34882' has lower integrity than agent requires. Agent would need to drop integrity tags [approved:all unapproved:all] to trust this resource.)
🧪 Test evaluation by Evaluate PR Tests
🤖 AI Summary📊 Expand Full Review —
|
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #34882 | Preserve View/_selectedTemplate across Recycle(); reconnect native handler in Bind() when Handler is null and template unchanged |
✅ PASSED (Gate) | TemplatedItemViewHolder.cs |
Original PR |
🔧 Fix — Analysis & Comparison
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| 1 | try-fix (claude-opus-4.6) | Lightweight Detach/Reattach - avoid handler disconnection during recycle; add Detach/Reattach to ItemContentView, keep handler alive | PASS | ItemContentView.cs + TemplatedItemViewHolder.cs | Never disconnects handler; modifies more API surface (2 files) |
| 2 | try-fix (claude-sonnet-4.6) | Property Snapshot - static ConditionalWeakTable keyed on binding context, captures non-default layout props on Recycle, restores after fresh view creation | PASS | TemplatedItemViewHolder.cs | More complex (~95 lines added); 2 iterations to compile |
| 3 | try-fix (gpt-5.3-codex) | ItemsView-scoped recycled view cache keyed by (bindingContext, DataTemplate) - keeps View=null behavior but retrieves cached MAUI view in Bind() | PASS | TemplatedItemViewHolder.cs | Interesting but introduces cache memory management complexity |
| 4 | try-fix (gpt-5.4) | Mutation-aware recycle preservation - only preserves views whose request values changed from template baseline; unmutated cells still rebuild normally | PASS | TemplatedItemViewHolder.cs | Good concept but adds baseline-snapshot overhead for every cell |
| PR | PR #34882 | Preserve View/_selectedTemplate across Recycle(); reconnect handler in Bind() when Handler is null | PASSED (Gate) | TemplatedItemViewHolder.cs | Simplest; 1 file, ~12 lines; minimal API change |
Cross-Pollination
| Model | Round | New Ideas? | Details |
|---|---|---|---|
| claude-opus-4.6 | 2 | No | NO NEW IDEAS |
| claude-sonnet-4.6 | 2 | No | NO NEW IDEAS |
Exhausted: Yes
Selected Fix: PR's fix - simplest implementation (1 file, ~12 lines changed), minimal API surface, correct approach that reconnects rather than avoids disconnection, consistent with MAUI's existing handler lifecycle patterns.
📋 Report — Final Recommendation
Final Recommendation: APPROVE
Phase Status
| Phase | Status | Notes |
|---|---|---|
| Pre-Flight | COMPLETE | Issue 34783, Android-only regression from PR 34534 |
| Gate | PASSED | Android - tests FAIL without fix, PASS with fix |
| Try-Fix | COMPLETE | 4 attempts, 4 passing; PR fix selected as best |
| Report | COMPLETE |
Summary
PR 34882 is a targeted Android fix for a regression introduced by PR 34534, where CollectionView items lost dynamically changed sizes (e.g. HeightRequest 60 to 100) after scrolling off-screen and back. The fix is simple, correct, and minimal. Gate passed. All 4 independent try-fix models confirmed the fix direction. The PR fix is the simplest of all candidates and should be approved.
Root Cause
PR 34534 modified TemplatedItemViewHolder.Recycle() to set View = null and _selectedTemplate = null after disconnecting the native handler. This forced Bind() to always take the templateChanging = true path, recreating the MAUI view from DataTemplate on every scroll recycle. Since DataTemplate always initializes with HeightRequest = 60, any runtime property changes were discarded.
Fix Quality
Correct: Keeps View and _selectedTemplate across Recycle() so Bind() detects template unchanged and reuses the existing MAUI view. A Handler is null check reconnects the native platform handler without recreating the view, preserving runtime property changes.
Simple: Only TemplatedItemViewHolder.cs is modified (~12 net lines). No new API surface, no new data structures.
Try-Fix comparison: All 4 alternative approaches passed but were more complex. The PR fix is the clear winner on simplicity.
Minor concerns (non-blocking):
- Test guard: Test uses #if TEST_FAILS_ON_CATALYST instead of #if ANDROID. The fix is Android-only (Items/Android handler) but the test will also compile and attempt to run on iOS/Windows where the HostApp page is registered as PlatformAffected.Android. This may result in test infrastructure handling it correctly or silently, but using #if ANDROID would be cleaner and less ambiguous.
- Redundant null propagation: View?.Handler is null uses the null-conditional operator, but View was already dereferenced on the line above (View.BindingContext = ...) so a NRE would have already occurred if View were null. Style-only issue.
Neither concern blocks merge. Gate confirmed the fix works correctly on Android.
|
|
/azp run maui-pr-uitests |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
/azp run maui-pr-devicetests |
|
No pipelines are associated with this pull request. |
|
Azure Pipelines successfully started running 1 pipeline(s). |
The ImagesKeepSizeAfterScrolling test times out on WinUI because
WaitForNoElement("Baboon") fails — Windows scroll behavior doesn't
push the first item off-screen the same way Android RecyclerView does.
Since the fix only targets Android (TemplatedItemViewHolder), exclude
both MacCatalyst and Windows from this test.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
/azp run maui-pr-uitests, maui-pr-devicetests |
|
Azure Pipelines successfully started running 2 pipeline(s). |
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
After tapping CollectionView images to dynamically resize them, scrolling items off-screen and back causes all images to reset to their original size.
This is a failure on the candidate branch. A PR was previously created against inflight/candidate: #34828. It was closed when the inflight PR was merged into main. A new PR has now been created targeting main.
Regression Details
The regression was introduced by PR #34534.
Root Cause
In PR #34534, TemplatedItemViewHolder.Recycle() set View = null and _selectedTemplate = null, which forced Bind() to recreate the view from the DataTemplate on every scroll recycle. Since the template defines HeightRequest = 60, any runtime size changes made by the user were lost.
Description of Change
Recycle(): Removed View = null and _selectedTemplate = null. Now only _itemContentView.Recycle() is called, which disconnects the native handler while preserving the MAUI view reference.
Bind(): Added a View?.Handler is null check within the existing if (!templateChanging) block. When the handler has been disconnected during recycle and the template has not changed, PropagatePropertyChanged and RealizeContent(View, itemsView) are invoked to reconnect the native handler to the existing MAUI view, preserving runtime property changes without recreating the view.
Issues Fixed
Fixes #34783
Screenshots
34783BeforeFix.mov
34783AfterFix.mov