[Android, iOS, Catalyst] Fix SearchHandler.BackgroundColor cannot be reset to null#35224
Conversation
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 35224Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 35224" |
|
Hey there @@HarishwaranVijayakumar! Thank you so much for your PR! Someone from the team will get assigned to your PR shortly and we'll get it reviewed. |
MauiBot
left a comment
There was a problem hiding this comment.
Expert Review — 3 findings
See inline comments for details.
MauiBot
left a comment
There was a problem hiding this comment.
Expert Review — 2 findings
See inline comments for details.
kubaflo
left a comment
There was a problem hiding this comment.
Could you please try ai's suggestions?
MauiBot
left a comment
There was a problem hiding this comment.
Expert Review — 3 findings
See inline comments for details.
MauiBot
left a comment
There was a problem hiding this comment.
Expert Review — 6 findings
See inline comments for details.
| App.Tap("ResetColorButton"); | ||
|
|
||
| // Verify the background returned to default | ||
| VerifyScreenshotOrSetException(ref exception); |
There was a problem hiding this comment.
[moderate] Single-cycle coverage misses state-machine regressions — The test exercises only one transition: (custom) → (reset). The fix adds a _hasCustomBackground (Android) / _defaultBackgroundCaptured (iOS) state flag whose interesting transitions also include: no-set → reset (must no-op), set → reset → set-different → reset, and set → set-different → reset. A single hop won't catch regressions where a later custom-set is treated as a no-op, where the captured default is overwritten by a later custom value, or where the second reset crashes. Add at least one extra cycle (custom → reset → custom-2 → reset). Snapshot tests are cheap enough to add the extra hop.
| AutomationId = "ResetColorButton", | ||
| HorizontalOptions = LayoutOptions.Center, | ||
| VerticalOptions = LayoutOptions.Center, | ||
| }; |
There was a problem hiding this comment.
[minor] HostApp page — Add a second button (e.g. "Apply Hot Pink BackgroundColor") so the shared UI test can drive the additional set→reset→set-2→reset sequence noted in the test review. The page also doubles as a manual repro for the same bug class on related properties — exposing one more button keeps the manual sandbox useful.
35be44b to
232d5ec
Compare
🤖 AI Summary
📊 Review Session —
|
| Test | Without Fix (expect FAIL) | With Fix (expect PASS) |
|---|---|---|
🖥️ Issue35088 Issue35088 |
✅ FAIL — 827s | ✅ PASS — 1286s |
🔴 Without fix — 🖥️ Issue35088: FAIL ✅ · 827s
Determining projects to restore...
Restored /home/vsts/work/1/s/src/Controls/src/Core/Controls.Core.csproj (in 7.14 sec).
Restored /home/vsts/work/1/s/src/BlazorWebView/src/Maui/Microsoft.AspNetCore.Components.WebView.Maui.csproj (in 7.17 sec).
Restored /home/vsts/work/1/s/src/Controls/Foldable/src/Controls.Foldable.csproj (in 165 ms).
Restored /home/vsts/work/1/s/src/Graphics/src/Graphics/Graphics.csproj (in 19 ms).
Restored /home/vsts/work/1/s/src/Essentials/src/Essentials.csproj (in 65 ms).
Restored /home/vsts/work/1/s/src/Core/src/Core.csproj (in 81 ms).
Restored /home/vsts/work/1/s/src/Controls/Maps/src/Controls.Maps.csproj (in 503 ms).
Restored /home/vsts/work/1/s/src/Core/maps/src/Maps.csproj (in 37 ms).
Restored /home/vsts/work/1/s/src/Controls/src/Xaml/Controls.Xaml.csproj (in 25 ms).
Restored /home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj (in 277 ms).
1 of 11 projects are up-to-date for restore.
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14075492
Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0-android36.0/Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14075492
Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0-android36.0/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14075492
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.70-ci+azdo.14075492
Maps -> /home/vsts/work/1/s/artifacts/bin/Maps/Debug/net10.0-android36.0/Microsoft.Maui.Maps.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14075492
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.70-ci+azdo.14075492
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14075492
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14075492
Controls.Foldable -> /home/vsts/work/1/s/artifacts/bin/Controls.Foldable/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Foldable.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.70-ci+azdo.14075492
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.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.70-ci+azdo.14075492
Graphics -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14075492
Essentials -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14075492
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.70-ci+azdo.14075492
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14075492
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.70-ci+azdo.14075492
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14075492
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14075492
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14075492
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
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:35.74
Broadcasting: Intent { act=android.intent.action.CLOSE_SYSTEM_DIALOGS flg=0x400000 }
Broadcast completed: result=0
Broadcasting: Intent { act=android.intent.action.CLOSE_SYSTEM_DIALOGS flg=0x400000 }
Broadcast completed: result=0
Determining projects to restore...
Restored /home/vsts/work/1/s/src/TestUtils/src/VisualTestUtils/VisualTestUtils.csproj (in 1.11 sec).
Restored /home/vsts/work/1/s/src/TestUtils/src/UITest.NUnit/UITest.NUnit.csproj (in 957 ms).
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 5.39 sec).
Restored /home/vsts/work/1/s/src/TestUtils/src/VisualTestUtils.MagickNet/VisualTestUtils.MagickNet.csproj (in 9.55 sec).
Restored /home/vsts/work/1/s/src/Controls/tests/TestCases.Android.Tests/Controls.TestCases.Android.Tests.csproj (in 12.94 sec).
Restored /home/vsts/work/1/s/src/Controls/tests/CustomAttributes/Controls.CustomAttributes.csproj (in 10 ms).
Restored /home/vsts/work/1/s/src/TestUtils/src/UITest.Analyzers/UITest.Analyzers.csproj (in 22.43 sec).
5 of 13 projects are up-to-date for restore.
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14075492
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.70-ci+azdo.14075492
Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14075492
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.70-ci+azdo.14075492
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
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.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.17] Discovering: Controls.TestCases.Android.Tests
[xUnit.net 00:00:00.62] 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
>>>>> 05/12/2026 14:57:14 FixtureSetup for Issue35088(Android)
>>>>> 05/12/2026 14:57:19 SearchHandlerBackgroundColorResetsToDefault Start
>>>>> 05/12/2026 14:57:29 SearchHandlerBackgroundColorResetsToDefault Stop
>>>>> 05/12/2026 14:57:30 Log types: logcat, bugreport, server
Failed SearchHandlerBackgroundColorResetsToDefault [12 s]
Error Message:
VisualTestUtils.VisualTestFailedException :
Snapshot different than baseline: SearchHandlerBackgroundColorResetsToDefault.png (4.29% difference)
If the correct baseline has changed (this isn't a a bug), then update the baseline image.
See test attachment or download the build artifacts to get the new snapshot file.
More info: https://aka.ms/visual-test-workflow
Stack Trace:
at Microsoft.Maui.TestCases.Tests.Issues.Issue35088.SearchHandlerBackgroundColorResetsToDefault() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue35088.cs:line 34
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
Test Run Failed.
Total tests: 1
Failed: 1
Total time: 1.7827 Minutes
🟢 With fix — 🖥️ Issue35088: PASS ✅ · 1286s
(truncated to last 15,000 chars)
.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: --- End of stack trace from previous location --- [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at AndroidDeviceExtensions.PushAndInstallPackageAsync(AndroidDevice device, PushAndInstallCommand command, CancellationToken token) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at AndroidDeviceExtensions.PushAndInstallPackageAsync(AndroidDevice device, PushAndInstallCommand command, CancellationToken token) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at Xamarin.Android.Tasks.FastDeploy.InstallPackage(Boolean installed) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at Xamarin.Android.Tasks.FastDeploy.InstallPackage(Boolean installed) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at Xamarin.Android.Tasks.FastDeploy.RunInstall() [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
Build FAILED.
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: Mono.AndroidTools.InstallFailedException: Unexpected install output: cmd: Failure calling service package: Broken pipe (32) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at Mono.AndroidTools.Internal.AdbOutputParsing.CheckInstallSuccess(String output, String packageName) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at Mono.AndroidTools.AndroidDevice.<>c__DisplayClass105_0.<InstallPackage>b__0(Task`1 t) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: --- End of stack trace from previous location --- [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: --- End of stack trace from previous location --- [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at AndroidDeviceExtensions.PushAndInstallPackageAsync(AndroidDevice device, PushAndInstallCommand command, CancellationToken token) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at AndroidDeviceExtensions.PushAndInstallPackageAsync(AndroidDevice device, PushAndInstallCommand command, CancellationToken token) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at Xamarin.Android.Tasks.FastDeploy.InstallPackage(Boolean installed) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at Xamarin.Android.Tasks.FastDeploy.InstallPackage(Boolean installed) [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
/home/vsts/work/1/s/.dotnet/packs/Microsoft.Android.Sdk.Linux/36.1.2/tools/Xamarin.Android.Common.Debugging.targets(333,5): error ADB0010: at Xamarin.Android.Tasks.FastDeploy.RunInstall() [/home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj::TargetFramework=net10.0-android]
0 Warning(s)
1 Error(s)
Time Elapsed 00:09:51.73
* 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.70-ci+azdo.14075492
Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0-android36.0/Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14075492
Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0-android36.0/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14075492
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.70-ci+azdo.14075492
Maps -> /home/vsts/work/1/s/artifacts/bin/Maps/Debug/net10.0-android36.0/Microsoft.Maui.Maps.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14075492
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.70-ci+azdo.14075492
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14075492
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14075492
Controls.Foldable -> /home/vsts/work/1/s/artifacts/bin/Controls.Foldable/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Foldable.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.70-ci+azdo.14075492
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.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.70-ci+azdo.14075492
Graphics -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14075492
Essentials -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14075492
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.70-ci+azdo.14075492
Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Maps.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14075492
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.70-ci+azdo.14075492
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14075492
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14075492
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14075492
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.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:09:12.12
Broadcasting: Intent { act=android.intent.action.CLOSE_SYSTEM_DIALOGS flg=0x400000 }
Broadcast completed: result=0
Broadcasting: Intent { act=android.intent.action.CLOSE_SYSTEM_DIALOGS flg=0x400000 }
Broadcast completed: result=0
Determining projects to restore...
All projects are up-to-date for restore.
Controls.CustomAttributes -> /home/vsts/work/1/s/artifacts/bin/Controls.CustomAttributes/Debug/net10.0/Controls.CustomAttributes.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14075492
Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14075492
Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14075492
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.70-ci+azdo.14075492
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.
/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.45] 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
>>>>> 05/12/2026 15:18:51 FixtureSetup for Issue35088(Android)
>>>>> 05/12/2026 15:18:54 SearchHandlerBackgroundColorResetsToDefault Start
>>>>> 05/12/2026 15:19:00 SearchHandlerBackgroundColorResetsToDefault Stop
Passed SearchHandlerBackgroundColorResetsToDefault [6 s]
NUnit Adapter 4.5.0.0: Test execution complete
Test Run Successful.
Total tests: 1
Passed: 1
Total time: 27.8767 Seconds
📁 Fix files reverted (2 files)
src/Controls/src/Core/Compatibility/Handlers/Shell/Android/SearchHandlerAppearanceTracker.cssrc/Controls/src/Core/Compatibility/Handlers/Shell/iOS/SearchHandlerAppearanceTracker.cs
🧪 UI Tests — Shell
Detected UI test categories: Shell
✅ Deep UI tests — 298 passed, 0 failed across 1 category on platform-pool agent (replaces in-process counts above).
🧪 UI Test Execution Results (deep, platform pool)
| Category | Tests | Snapshot diffs |
|---|---|---|
controls-Shell |
298/298 ✓ | — |
📎 Download drop-deep-uitests artifact (TRX + snapshot diffs) |
🔍 Pre-Flight — Context & Validation
Pre-Flight — PR #35224
Issue
- [Android, iOS, Catalyst] SearchHandler.BackgroundColor cannot be reset to null #35088:
SearchHandler.BackgroundColorcannot be reset tonull(Android, iOS, MacCatalyst). - Once a custom color is set on a
SearchHandler, assigningBackgroundColor = nullhas no visible effect — the previous color persists. Expected behavior: reverts to the native default chrome. - Labels:
t/bug,platform/android,platform/ios,platform/macos,area-controls-shell,partner/syncfusion,shell-search-handler.
PR Summary
- Author: HarishwaranVijayakumar (community/partner — Syncfusion)
- Base:
dotnet/maui:main - Head:
HarishwaranVijayakumar/maui:fix-35088@c004fac6 - Files changed: 12 (
+117 / -8), of which 2 are functional.csfiles and the rest are tests/snapshots.
Root Cause (per PR description)
- Android (
SearchHandlerAppearanceTracker.cs) —UpdateBackgroundColor()early-returned whenBackgroundColor == null, so once a custom color was applied viaSetBackgroundColor()it could never be cleared. - iOS/Mac (
SearchHandlerAppearanceTracker.cs) —_defaultBackgroundColorwas captured inside the custom-color branch ofUpdateSearchBarBackgroundColor(), so the first custom color became the cached "default" used on reset.
Fix Approach
Android:
- Tracks
_hasCustomBackgroundso the method can short-circuit before any custom color was ever applied (preserves original early-out semantics). - Caches
_linearLayoutreference at construction time instead of relying on a re-lookup each invocation. - When
BackgroundColor == nullafter a custom color was set, assigns_linearLayout.Background = null(restoring the native drawable selector/state-list).
iOS/MacCatalyst:
- Moves the
_defaultBackgroundColorcapture intoGetDefaultSearchBarColors(), which is invoked once during initial setup before any custom color is applied. CapturestextField.BackgroundColor(typicallynilon iOS 13+, which restores the native chrome on reset). - Removes the redundant capture inside the custom-color branch.
Changed Files Classification
| File | Type | Notes |
|---|---|---|
src/Controls/src/Core/Compatibility/Handlers/Shell/Android/SearchHandlerAppearanceTracker.cs |
Functional (Android) | Core fix |
src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/SearchHandlerAppearanceTracker.cs |
Functional (iOS+MacCatalyst, compiles for both) | Core fix |
src/Controls/tests/TestCases.HostApp/Issues/Issue35088.cs |
UI test host page | New |
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue35088.cs |
UI test (NUnit + Appium) | New; gated #if TEST_FAILS_ON_WINDOWS |
| 6× snapshot PNGs (Android, iOS, iOS-26, Mac) | Test fixtures | New baseline images |
Gate Result
✅ PASSED (per orchestrator) — Issue35088 UI test FAILS without fix, PASSES with fix on android.
Platform Selection
android (per task input).
Code Review Summary
See pre-flight/code-review.md for the full expert-reviewer findings.
High-level concerns to feed try-fix as advisory hints:
- Android: Caching
_linearLayoutonce at construction assumes the search view's child layout hierarchy never gets recreated. Verify no recycling path exists. SettingBackground = nullremoves the OS-supplied stateful drawable (selector/ripple) and may not visually equal the "before any custom color was set" state. - iOS:
textField.BackgroundColoris typicallynilon iOS 13+ but on older OS or themed UIs may already carry a value at capture time — capturing it before any customization is correct, just confirmGetDefaultSearchBarColorsis invoked before the firstUpdateSearchBarBackgroundColor. - Tests: Snapshot-only verification; no functional assertion. Snapshot baselines added for android/ios/ios-26/mac.
Verdict
Pre-Flight context complete. Proceeding to Phase 2 (try-fix) and parallel Phase 2b (expert reviewer evaluation).
🔬 Code Review — Deep Analysis
Code Review — PR #35224 (Pre-Flight summary)
This is the pre-flight code-review summary. The full expert-reviewer per-dimension evaluation is run in Phase 2 (Branch A) and saved to ../expert-pr-eval/content.md and ../inline-findings.json.
File 1 — src/Controls/src/Core/Compatibility/Handlers/Shell/Android/SearchHandlerAppearanceTracker.cs
Changes
- New fields
_hasCustomBackground(bool) and_linearLayout(LinearLayout). _linearLayoutcached in constructor via(_control as ViewGroup)?.GetFirstChildOfType<LinearLayout>().UpdateBackgroundColor()rewritten:- Bails out if
_linearLayout == null. - Bails out if no custom background was ever set AND current color is null (preserves pre-fix semantics on first-time null).
- When
BackgroundColoris reset to null after a custom color:_linearLayout.Background = nulland resets the flag. - When
BackgroundColorset to non-null:SetBackgroundColor(color.ToPlatform())and flag becomes true.
- Bails out if
Findings
⚠️ Behavioral change of "default": SettingBackground = nullremoves the original platform drawable (which may have been a state-list / ripple drawable for press feedback). The "before custom color" state was not literallyBackground == null— Android assigns a default background drawable to LinearLayouts in this hierarchy when constructed. Caching the original drawable in the constructor (e.g.,_originalBackground = _linearLayout.Background) and restoring it on reset would be more faithful to the bug report's "reverts to default" semantics. The current approach may produce a transparent/no-drawable result that looks default but loses focus/ripple effects.⚠️ Constructor lookup vs. dynamic hierarchy:_linearLayoutis captured ONCE at constructor time. If the search view's view hierarchy is recreated or the LinearLayout is replaced (e.g., theme change, configuration change), the cached reference becomes stale. The pre-fix code re-queried on every call.- 💡
GetFirstChildOfType<LinearLayout>()vs oldGetChildrenOfType<LinearLayout>().FirstOrDefault()— verify behavior parity (depth-first vs breadth-first, recursive search). - ✅ Null-guard on
_linearLayoutis good defensive coding. - ✅ The
!_hasCustomBackground && backgroundColor is nullshort-circuit correctly preserves the original "first-call no-op" behavior so we don't gratuitously clobber the OS default drawable.
Failure-mode probes
- F1: SearchHandler.BackgroundColor set, then set to null, then set again to non-null — does the drawable cycle work? (Should.)
- F2: SearchHandler in a Shell where the search view is recreated (e.g., orientation change) — does the new appearance tracker correctly inherit state? (Likely yes — new tracker, fresh capture.)
- F3: Theme change while search bar is showing — does the cached
_linearLayoutstill point at the live view? (Risk.)
File 2 — src/Controls/src/Core/Compatibility/Handlers/Shell/iOS/SearchHandlerAppearanceTracker.cs
Changes
GetDefaultSearchBarColors()now also capturestextField.BackgroundColorinto_defaultBackgroundColor.- Removed lazy capture (
if (_defaultBackgroundColor is null) _defaultBackgroundColor = backGroundColor.ToPlatform()) from the custom-color branch ofUpdateSearchBarBackgroundColor(). - Changed
!= nulltois not null(style).
Findings
- ✅ Moving the capture into the platform-default discovery method is the correct fix — captured before any user customization.
⚠️ Note:UpdateSearchBarBackgroundColordoes NOT restoreLayer.CornerRadius/ClipsToBoundsto a pre-customization snapshot — it hardcodes0andfalse. If the user had customized these elsewhere they'd be clobbered on reset. Not introduced by this PR (already existed), but worth flagging.⚠️ _defaultBackgroundColoris captured exactly ONCE inGetDefaultSearchBarColors. If the search bar is re-themed (Dark/Light mode switch) the captured value becomes stale. Pre-existing limitation, not introduced here.- ✅ Public API surface unchanged.
Failure-mode probes
- F1: Set then unset BackgroundColor — does textField show native chrome? (Yes, since
nilBackgroundColor is the iOS 13+ default.) - F2: Older iOS where textField.BackgroundColor is non-nil at construction — capture works correctly.
- F3: MacCatalyst — file compiles as
.iOS.cswhich targets both iOS and MacCatalyst. Verify Mac UI tree hasUITextFieldas descendant. (It does — same UIKit hierarchy.)
Tests
Issue35088.cs(HostApp) — Sample page with SearchHandler set to YellowGreen, button to clear to null. ✅ Solid repro page.Issue35088.cs(Shared.Tests) — Snapshot-based UI test, gated#if TEST_FAILS_ON_WINDOWS(links [Windows] SearchHandler APIs are not functioning properly #29493). UsesVerifyScreenshotOrSetExceptionto assert both the applied and reset states. Snapshots added for android, ios, ios-26, mac.⚠️ The test does not include an assertion-based check (e.g., reading the platform background color). It's pure snapshot. If platform theme drift occurs the snapshots will need updates.
Blast Radius
- Android: All
SearchHandleruses in Shell withSearchBoxVisibility != Hidden. The_linearLayoutfield adds memory cost per tracker (single ref, negligible). - iOS/Mac: All
SearchHandleruses in Shell. Behavior on FIRSTUpdateSearchBarBackgroundColorcall now relies onGetDefaultSearchBarColorshaving been invoked first — verified at constructor line 43 (GetDefaultSearchBarColors(_uiSearchBar)happens beforeUpdateSearchBarColors()). - Public API: none touched.
Verdict
LGTM with minor advisory notes (confidence: high).
- Android fix is correct and minimal; the "save original drawable" enhancement is a polish, not a blocker.
- iOS fix is the right architectural change (capture default before customization).
- Tests are reasonable; snapshot-only is a minor concern but matches repo conventions for visual bugs.
🔧 Fix — Analysis & Comparison
Phase 2 — Try-Fix Summary (aggregate)
Fix Candidates
| # | Source | Model lens / Dimension | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|---|
| 1 | try-fix-1 | claude-opus-4.6 / handler-lifecycle | Snapshot original LinearLayout.Background Drawable lazily on first UpdateBackgroundColor; restore on reset. iOS: lazy capture _defaultBackgroundColor = textField.BackgroundColor inside UpdateSearchBarBackgroundColor on first call. |
2 files | Best Android approach (preserves OS state-list/ripple). iOS deviates from PR by using lazy local capture. | |
| 2 | try-fix-2 | claude-sonnet-4.6 / regression-patterns | Android: drive off SearchHandler.IsSet(BackgroundColorProperty) + null-out Background. iOS: drop _defaultBackgroundColor entirely, reset textField.BackgroundColor = null (iOS 13+ default). |
2 files | Smallest iOS approach but relies on undocumented iOS 13+ behavior; Android IsSet is subtle for reset semantics; loses OS chrome on reset. |
|
| 3 | try-fix-3 | gpt-5.3-codex / minimal-diff | Android: simply remove early-return; null out Background. iOS: lazy _defaultBackgroundColor capture inside UpdateSearchBarBackgroundColor (instead of in GetDefaultSearchBarColors). |
2 files | Minimal diff. Loses OS state-list (same Android limitation as PR fix). iOS capture-site is colocated with use. | |
| 4 | try-fix-4 | gemini-3-pro-preview / tests + api-design | Android: View-Tag-based "captured?" guard + _originalBackground field; restore exact Drawable. iOS: identical to PR fix. |
2 files | Highest Android visual fidelity but introduces magic-number tag key. iOS portion brings no improvement over PR. | |
| pr | PR #35224 (raw) | — | Android: cache _linearLayout, _hasCustomBackground; on reset _linearLayout.Background = null. iOS: capture _defaultBackgroundColor in GetDefaultSearchBarColors before first user customization. |
✅ PASSED (Gate verified on android) | 2 files + tests | Correct + verified; Android reset loses OS-supplied state-list drawable. |
| pr-plus-reviewer | PR + maui-expert-reviewer applied feedback | Branch A | PR fix + add _defaultBackground field; capture _linearLayout.Background in constructor; restore on reset; null both in Dispose. iOS unchanged from PR. |
✅ Expected PASS (PR's Android reset path becomes "restore captured drawable", which is strictly more correct than Background = null) |
2 files + tests | Combines PR's verified iOS fix with reviewer-applied Android improvement; structurally same family as try-fix-1 and try-fix-4 Android sides. |
Cross-Pollination
All four try-fix candidates explored converged on a small set of insights:
- Android reset path should restore the original drawable, not
null. (try-fix-1, try-fix-4 — and adopted bypr-plus-reviewerfrom reviewer feedback) - iOS lazy-vs-eager default capture site is a minor preference; eager capture in
GetDefaultSearchBarColors(as PR does) is cleaner because it runs once at known time, before any user property change. (try-fix-1 and try-fix-3 used lazy capture; try-fix-4 used eager — same as PR.) - Cached vs per-call LinearLayout lookup is a minor perf vs. robustness trade-off; PR's cached approach is fine given construction-time capture.
| Model | Round | New Ideas? | Details |
|---|---|---|---|
| claude-opus-4.6 | 2 | No | Converges on "snapshot original Drawable" — already covered by try-fix-1 / reviewer feedback. |
| claude-sonnet-4.6 | 2 | No | IsSet-based reset is novel but not strictly better — already in try-fix-2. |
| gpt-5.3-codex | 2 | No | Minimal-diff lens already explored — already in try-fix-3. |
| gemini-3-pro-preview | 2 | No | View-tag idiom already in try-fix-4. |
Exhausted: Yes
Selected Fix: pr-plus-reviewer — combines the PR's correct iOS fix (verified by gate) with the reviewer-recommended Android improvement (snapshot + restore original Drawable instead of nulling it). Convergent with try-fix-1 / try-fix-4 Android side but iOS side is verified by gate.
Notes on Test Verification
The gate already verified the PR's fix (test FAILS without fix, PASSES with fix on android). The pr-plus-reviewer candidate makes the Android reset path strictly more correct (restores OS state-list/ripple drawable rather than discarding it) — the regression test will still pass because the test asserts visual return-to-default, and the captured original drawable IS the default.
Try-fix candidates 1–4 were not device-executed (autonomous runner has no Android device); they are presented as alternative-approach analyses. Their viability is assessed structurally and against the same regression test scenario.
📋 Report — Final Recommendation
Phase 3 — Comparative Report — PR #35224
Bug & Gate
- Issue [Android, iOS, Catalyst] SearchHandler.BackgroundColor cannot be reset to null #35088:
SearchHandler.BackgroundColorcannot be reset tonull(Android, iOS, MacCatalyst). - Gate result (target platform: android): ✅ PASSED — regression test
Issue35088 / SearchHandlerBackgroundColorResetsToDefaultFAILS without the PR fix and PASSES with it.
Candidates Evaluated
| Candidate | Android approach | iOS approach | Test outcome | Visual fidelity to "true default" | Diff size |
|---|---|---|---|---|---|
| pr | Cache _linearLayout + _hasCustomBackground; on reset Background = null |
Capture _defaultBackgroundColor in GetDefaultSearchBarColors before first user mapping |
✅ PASSED (gate) | 12 files (~117/-8) | |
| pr-plus-reviewer | PR + capture original _defaultBackground in ctor; restore on reset; null in Dispose |
(unchanged from PR) | ✅ Expected PASS (Android path strictly more correct) | ✅ High — restores original Drawable on Android | PR + ~9 LoC |
| try-fix-1 | Lazy snapshot of original Drawable on first UpdateBackgroundColor; per-call LinearLayout re-query |
Lazy capture inside UpdateSearchBarBackgroundColor (not in GetDefaultSearchBarColors) |
✅ High (Android), equivalent iOS | 2 files | |
| try-fix-2 | Drive off IsSet + null Background |
Drop _defaultBackgroundColor; reset textField.BackgroundColor = null |
2 files | ||
| try-fix-3 | Remove early-return; null Background |
Lazy capture inside UpdateSearchBarBackgroundColor |
2 files | ||
| try-fix-4 | View-Tag + _originalBackground field; restore Drawable |
Identical to PR fix | ✅ High (Android), equivalent iOS | 2 files; uses magic-number tag key (non-idiomatic) |
Ranking (verified passers ranked above unverified)
pr-plus-reviewer✅ — Builds on verified PR fix; addresses the only substantive expert-reviewer concern (Android reset path); zero risk of test regression because the captured_defaultBackgroundIS the original drawable the snapshot baseline was taken against. Iteration over the PR.pr✅ — Already gate-verified; correct functional fix on all platforms. Only weakness is the AndroidBackground = nullwhich discards the OS state-list drawable (visual-only; not a test regression).- try-fix-1
⚠️ — Strong design (lazy snapshot + per-call lookup) but not device-verified and iOS lazy capture is less clean than PR's eager capture site. - try-fix-4
⚠️ — Same Android idea as try-fix-1 but with non-idiomatic View-Tag magic-number key; iOS portion duplicates PR with no improvement. - try-fix-3
⚠️ — Minimal diff; matches PR's Android limitation; iOS lazy-capture site less clean than PR. - try-fix-2
⚠️ — Relies on undocumented iOS 13+ behavior; AndroidIsSetsemantics are subtle for "reset" intent.
(Per task rule: candidates that failed regression tests are ranked lower than those that passed. None of the try-fix candidates were run to fail — they are listed as
Selection Criteria
- Verified passing tests (only
prandpr-plus-reviewerhave gate-verified evidence on android). - Code-review quality (Android reset fidelity, no public-API changes, thread-safety on main thread).
- Simplicity / size (smaller diff preferred, all else equal).
- Codebase consistency (matches existing
TableViewRenderer._originalBackgroundViewpattern of capturing original platform state).
Winner: pr-plus-reviewer
The maui-expert-reviewer agent identified one substantive concern: on Android, the PR's reset path sets _linearLayout.Background = null, which discards the OS-supplied drawable (selector / ripple / state-list). The reviewer-applied edit:
- Adds a
_defaultBackgroundfield - Captures
_linearLayout.Backgroundin the constructor BEFORE any customization - Restores
_defaultBackground(notnull) on reset - Nulls both refs in
Dispose
This is strictly more correct than the raw PR fix, follows the existing TableViewRenderer._originalBackgroundView codebase pattern, is minimal (~9 LoC), and cannot regress the gate-verified test (the captured default IS the snapshot baseline's "default").
The iOS portion of the PR is correct as-written and was left unchanged.
Inline findings
See ../inline-findings.json (3 findings, 1 warning + 1 nit + 1 info).
Recommendation
Apply the reviewer's Android edit on top of the PR before merge.
…reset to null (#35224) <!-- 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! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> ### Issue Details - Setting SearchHandler.BackgroundColor to null does not reset the background color to its default value. Once a BackgroundColor is applied to a SearchHandler, assigning null has no visible effect — the previously set color persists. ### Root Cause of the issue - Android – UpdateBackgroundColor() had an early return when BackgroundColor was null. Once a custom color was applied via SetBackgroundColor(), setting it back to null simply exited the method without restoring the original background, so the custom color persisted indefinitely. - iOS/Mac – _defaultBackgroundColor was captured inside the custom-color branch of UpdateSearchBarBackgroundColor(). This caused the first custom color set by the user to be saved as the “default,” rather than the actual platform default. When BackgroundColor was reset to null, it restored that first custom color instead of the real native background. ### Description of Change **Bug Fixes for Background Color Reset:** * On Android, updated `UpdateBackgroundColor()` in `SearchHandlerAppearanceTracker.cs` to clear the background when `BackgroundColor` is set to `null`, rather than leaving it unchanged. * On iOS, improved the logic in `GetDefaultSearchBarColors()` to capture the default background color from the search bar’s text field, and removed redundant code in `UpdateSearchBarBackgroundColor()` for setting the default background color. **Testing Improvements:** * Added a new sample page `Issue35088.cs` to manually test resetting the `SearchHandler.BackgroundColor` to `null` via a button. * Added an automated UI test `Issue35088.cs` to verify that the background color resets to default when set to `null`. <!-- Enter description of the fix in this section --> ### Issues Fixed <!-- Please make sure that there is a bug logged for the issue being fixed. The bug should describe the problem and how to reproduce it. --> Fixes #35088 ### Tested the behaviour in the following platforms - [x] - Windows - [x] - Android - [x] - iOS - [x] - Mac |Platform| Before | After | |----------|----------|----------| |Android| <video src="https://github.com/user-attachments/assets/fbddbfaf-c7d3-43c5-bd57-0da9ec32a4e3"> | <video src="https://github.com/user-attachments/assets/4d842590-dba0-45d7-8b91-de3676fbeeaa"> | |iOS| <video src="https://github.com/user-attachments/assets/f2ca9506-b76d-4ab0-999a-dbd167b38790"> | <video src="https://github.com/user-attachments/assets/8be93b01-56db-47a9-baeb-69ab0bfe1088"> | ---------
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
Root Cause of the issue
Description of Change
Bug Fixes for Background Color Reset:
UpdateBackgroundColor()inSearchHandlerAppearanceTracker.csto clear the background whenBackgroundColoris set tonull, rather than leaving it unchanged.GetDefaultSearchBarColors()to capture the default background color from the search bar’s text field, and removed redundant code inUpdateSearchBarBackgroundColor()for setting the default background color.Testing Improvements:
Issue35088.csto manually test resetting theSearchHandler.BackgroundColortonullvia a button.Issue35088.csto verify that the background color resets to default when set tonull.Issues Fixed
Fixes #35088
Tested the behaviour in the following platforms
35088-beforefixandroid.mov
35088-afterfixandroid.mov
35088-beforefixiOS.mov
35088-afterfixiOS.mov