[Android] Fix LinearGradientBrush rendering as opaque black box#35299
Conversation
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 35299Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 35299" |
|
Hey there @@SubhikshaSf4851! Thank you so much for your PR! Someone from the team will get assigned to your PR shortly and we'll get it reviewed. |
|
/azp run maui-pr-uitests , maui-pr-devicetests |
|
Azure Pipelines successfully started running 2 pipeline(s). |
There was a problem hiding this comment.
Pull request overview
This PR fixes Android gradient rendering in the Core drawable path by preserving per-stop alpha when MAUI builds Java-backed gradient data, and adds a UI regression scenario for issue #35280. The PR title and description are consistent with the implementation.
Changes:
- Replaces
GetGradientData(1.0f)withGetGradientData(null)for Android linear/radial background and border gradients inMauiDrawable. - Adds a HostApp issue page that reproduces the transparent-stop linear gradient rendering bug.
- Adds a screenshot-based UI test covering the linear background regression scenario.
Reviewed changes
Copilot reviewed 3 out of 5 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
src/Core/src/Graphics/MauiDrawable.Android.cs |
Preserves original alpha values for Android gradient background/border rendering. |
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue35280.cs |
Adds screenshot regression coverage for the new issue scenario. |
src/Controls/tests/TestCases.HostApp/Issues/Issue35280.cs |
Adds the HostApp repro page used by the UI test. |
🤖 AI Summary
📊 Review Session —
|
| Test | Without Fix (expect FAIL) | With Fix (expect PASS) |
|---|---|---|
🖥️ Issue35280 Issue35280 |
✅ FAIL — 1051s | ✅ PASS — 868s |
🔴 Without fix — 🖥️ Issue35280: FAIL ✅ · 1051s
(truncated to last 15,000 chars)
rceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14019808
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14019808
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.70-ci+azdo.14019808
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14019808
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14019808
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14019808
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.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
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.14019808
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.14019808
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.14019808
Core -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14019808
Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Maps.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.14019808
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.14019808
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14019808
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14019808
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.70-ci+azdo.14019808
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:09:31.89
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/Controls/tests/CustomAttributes/Controls.CustomAttributes.csproj (in 1.65 sec).
Restored /home/vsts/work/1/s/src/TestUtils/src/VisualTestUtils/VisualTestUtils.csproj (in 8 ms).
Restored /home/vsts/work/1/s/src/TestUtils/src/VisualTestUtils.MagickNet/VisualTestUtils.MagickNet.csproj (in 6.5 sec).
Restored /home/vsts/work/1/s/src/Controls/tests/TestCases.Android.Tests/Controls.TestCases.Android.Tests.csproj (in 8.43 sec).
Restored /home/vsts/work/1/s/src/TestUtils/src/UITest.Core/UITest.Core.csproj (in 12 ms).
Restored /home/vsts/work/1/s/src/TestUtils/src/UITest.Appium/UITest.Appium.csproj (in 4 ms).
Restored /home/vsts/work/1/s/src/TestUtils/src/UITest.NUnit/UITest.NUnit.csproj (in 590 ms).
Restored /home/vsts/work/1/s/src/TestUtils/src/UITest.Analyzers/UITest.Analyzers.csproj (in 3.16 sec).
5 of 13 projects are up-to-date for restore.
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14019808
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.14019808
Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14019808
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.14019808
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
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.
/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.19] Discovering: Controls.TestCases.Android.Tests
[xUnit.net 00:00:00.64] 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
�[38;5;60m[d019cf41]�[0m�[38;5;160m[Logcat]�[0m Logcat terminated with code 1, signal null
�[38;5;196m[0dc974cf]�[0m�[38;5;160m[Logcat]�[0m Logcat terminated with code 1, signal null
�[38;5;116m[e1cfbf7b]�[0m�[38;5;160m[Logcat]�[0m Logcat terminated with code 1, signal null
�[38;5;119m[7762cbe9]�[0m�[38;5;160m[Logcat]�[0m Logcat terminated with code 1, signal null
�[38;5;220m[0a7a0a00]�[0m�[38;5;160m[Logcat]�[0m Logcat terminated with code 1, signal null
�[38;5;135m[0e1aa966]�[0m�[38;5;160m[Logcat]�[0m Logcat terminated with code 1, signal null
�[38;5;189m[da2e475a]�[0m�[38;5;160m[Logcat]�[0m Logcat terminated with code 1, signal null
�[38;5;55m[787a51f6]�[0m�[38;5;160m[Logcat]�[0m Logcat terminated with code 1, signal null
�[38;5;65m[a4ad35e2]�[0m�[38;5;160m[Logcat]�[0m Logcat terminated with code 1, signal null
�[38;5;48m[50a37e25]�[0m�[38;5;160m[Logcat]�[0m Logcat terminated with code 1, signal null
>>>>> 05/05/2026 19:13:22 The SaveDeviceDiagnosticInfo threw an exception during Issue35280(Android).
Exception details: System.InvalidOperationException: Call InitialSetup before accessing the App property.
at UITest.Appium.NUnit.UITestContextBase.get_App() in /_/src/TestUtils/src/UITest.NUnit/UITestContextBase.cs:line 32
at UITest.Appium.NUnit.UITestBase.SaveDeviceDiagnosticInfo(String note, Boolean storeForReattachment) in /_/src/TestUtils/src/UITest.NUnit/UITestBase.cs:line 255
TearDown failed for test fixture Microsoft.Maui.TestCases.Tests.Issues.Issue35280(Android)
OpenQA.Selenium.UnknownErrorException : An unknown server-side error occurred while processing the command. Original error: Error executing adbExec. Original error: 'Command '/usr/local/lib/android/sdk/platform-tools/adb -P 5037 -s emulator-5554 install -r --no-incremental /home/vsts/work/1/s/.appium/node_modules/appium-uiautomator2-driver/node_modules/appium-uiautomator2-server/apks/appium-uiautomator2-server-v7.4.1.apk' timed out after 20000ms'. Try to increase the 20000ms adb execution timeout represented by 'uiautomator2ServerInstallTimeout' capability
TearDown : System.InvalidOperationException : Call InitialSetup before accessing the App property.
StackTrace: at OpenQA.Selenium.WebDriver.UnpackAndThrowOnError(Response errorResponse, String commandToExecute)
at OpenQA.Selenium.WebDriver.ExecuteAsync(String driverCommandToExecute, Dictionary`2 parameters)
at OpenQA.Selenium.WebDriver.Execute(String driverCommandToExecute, Dictionary`2 parameters)
at OpenQA.Selenium.Appium.AppiumDriver.Execute(String driverCommandToExecute, Dictionary`2 parameters)
at OpenQA.Selenium.WebDriver.StartSession(ICapabilities capabilities)
at OpenQA.Selenium.WebDriver..ctor(ICommandExecutor executor, ICapabilities capabilities)
at OpenQA.Selenium.Appium.AppiumDriver..ctor(ICommandExecutor commandExecutor, ICapabilities appiumOptions)
at OpenQA.Selenium.Appium.AppiumDriver..ctor(Uri remoteAddress, ICapabilities appiumOptions, TimeSpan commandTimeout, AppiumClientConfig clientConfig)
at OpenQA.Selenium.Appium.AppiumDriver..ctor(Uri remoteAddress, ICapabilities appiumOptions, TimeSpan commandTimeout)
at OpenQA.Selenium.Appium.AppiumDriver..ctor(Uri remoteAddress, ICapabilities appiumOptions)
at OpenQA.Selenium.Appium.Android.AndroidDriver..ctor(Uri remoteAddress, DriverOptions driverOptions)
at UITest.Appium.AppiumAndroidApp..ctor(Uri remoteAddress, IConfig config) in /_/src/TestUtils/src/UITest.Appium/AppiumAndroidApp.cs:line 11
at UITest.Appium.AppiumAndroidApp.CreateAndroidApp(Uri remoteAddress, IConfig config) in /_/src/TestUtils/src/UITest.Appium/AppiumAndroidApp.cs:line 41
at UITest.Appium.AppiumServerContext.CreateUIClientContext(IConfig config) in /_/src/TestUtils/src/UITest.Appium/AppiumServerContext.cs:line 42
at UITest.Appium.NUnit.UITestContextBase.InitialSetup(IServerContext context, Boolean reset) in /_/src/TestUtils/src/UITest.NUnit/UITestContextBase.cs:line 77
at UITest.Appium.NUnit.UITestContextBase.InitialSetup(IServerContext context) in /_/src/TestUtils/src/UITest.NUnit/UITestContextBase.cs:line 55
at UITest.Appium.NUnit.UITestBase.OneTimeSetup() in /_/src/TestUtils/src/UITest.NUnit/UITestBase.cs:line 215
at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
--TearDown
at UITest.Appium.NUnit.UITestContextBase.get_App() in /_/src/TestUtils/src/UITest.NUnit/UITestContextBase.cs:line 32
at UITest.Appium.NUnit.UITestBase.OneTimeTearDown() in /_/src/TestUtils/src/UITest.NUnit/UITestBase.cs:line 244
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
Failed LinearGradientBrushTransparentStopsShouldNotBeOpaque [4 m 30 s]
Error Message:
OneTimeSetUp: OpenQA.Selenium.UnknownErrorException : An unknown server-side error occurred while processing the command. Original error: Error executing adbExec. Original error: 'Command '/usr/local/lib/android/sdk/platform-tools/adb -P 5037 -s emulator-5554 install -r --no-incremental /home/vsts/work/1/s/.appium/node_modules/appium-uiautomator2-driver/node_modules/appium-uiautomator2-server/apks/appium-uiautomator2-server-v7.4.1.apk' timed out after 20000ms'. Try to increase the 20000ms adb execution timeout represented by 'uiautomator2ServerInstallTimeout' capability
Stack Trace:
at OpenQA.Selenium.WebDriver.UnpackAndThrowOnError(Response errorResponse, String commandToExecute)
at OpenQA.Selenium.WebDriver.ExecuteAsync(String driverCommandToExecute, Dictionary`2 parameters)
at OpenQA.Selenium.WebDriver.Execute(String driverCommandToExecute, Dictionary`2 parameters)
at OpenQA.Selenium.Appium.AppiumDriver.Execute(String driverCommandToExecute, Dictionary`2 parameters)
at OpenQA.Selenium.WebDriver.StartSession(ICapabilities capabilities)
at OpenQA.Selenium.WebDriver..ctor(ICommandExecutor executor, ICapabilities capabilities)
at OpenQA.Selenium.Appium.AppiumDriver..ctor(ICommandExecutor commandExecutor, ICapabilities appiumOptions)
at OpenQA.Selenium.Appium.AppiumDriver..ctor(Uri remoteAddress, ICapabilities appiumOptions, TimeSpan commandTimeout, AppiumClientConfig clientConfig)
at OpenQA.Selenium.Appium.AppiumDriver..ctor(Uri remoteAddress, ICapabilities appiumOptions, TimeSpan commandTimeout)
at OpenQA.Selenium.Appium.AppiumDriver..ctor(Uri remoteAddress, ICapabilities appiumOptions)
at OpenQA.Selenium.Appium.Android.AndroidDriver..ctor(Uri remoteAddress, DriverOptions driverOptions)
at UITest.Appium.AppiumAndroidApp..ctor(Uri remoteAddress, IConfig config) in /_/src/TestUtils/src/UITest.Appium/AppiumAndroidApp.cs:line 11
at UITest.Appium.AppiumAndroidApp.CreateAndroidApp(Uri remoteAddress, IConfig config) in /_/src/TestUtils/src/UITest.Appium/AppiumAndroidApp.cs:line 41
at UITest.Appium.AppiumServerContext.CreateUIClientContext(IConfig config) in /_/src/TestUtils/src/UITest.Appium/AppiumServerContext.cs:line 42
at UITest.Appium.NUnit.UITestContextBase.InitialSetup(IServerContext context, Boolean reset) in /_/src/TestUtils/src/UITest.NUnit/UITestContextBase.cs:line 77
at UITest.Appium.NUnit.UITestContextBase.InitialSetup(IServerContext context) in /_/src/TestUtils/src/UITest.NUnit/UITestContextBase.cs:line 55
at UITest.Appium.NUnit.UITestBase.OneTimeSetup() in /_/src/TestUtils/src/UITest.NUnit/UITestBase.cs:line 215
at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
Total tests: 1
Failed: 1
Test Run Failed.
Total time: 4.6587 Minutes
🟢 With fix — 🖥️ Issue35280: PASS ✅ · 868s
Determining projects to restore...
All projects are up-to-date for restore.
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14019808
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.14019808
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.14019808
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.14019808
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.14019808
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.14019808
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14019808
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14019808
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.Foldable -> /home/vsts/work/1/s/artifacts/bin/Controls.Foldable/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Foldable.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.70-ci+azdo.14019808
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.70-ci+azdo.14019808
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.14019808
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.14019808
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.14019808
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14019808
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.14019808
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14019808
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14019808
Microsoft.AspNetCore.Components.WebView.Maui -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.AspNetCore.Components.WebView.Maui.dll
Controls.Foldable -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Foldable.dll
Controls.Xaml -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Xaml.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14019808
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:11:55.73
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.70-ci+azdo.14019808
Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14019808
Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
##vso[build.updatebuildnumber]10.0.70-ci+azdo.14019808
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.70-ci+azdo.14019808
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
UITest.Appium -> /home/vsts/work/1/s/artifacts/bin/UITest.Appium/Debug/net10.0/UITest.Appium.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.50] 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/05/2026 19:27:38 FixtureSetup for Issue35280(Android)
>>>>> 05/05/2026 19:27:41 LinearGradientBrushTransparentStopsShouldNotBeOpaque Start
>>>>> 05/05/2026 19:27:45 LinearGradientBrushTransparentStopsShouldNotBeOpaque Stop
Passed LinearGradientBrushTransparentStopsShouldNotBeOpaque [4 s]
NUnit Adapter 4.5.0.0: Test execution complete
Test Run Successful.
Total tests: 1
Passed: 1
Total time: 26.9699 Seconds
📁 Fix files reverted (5 files)
.config/dotnet-tools.jsoneng/Version.Details.xmleng/Versions.propseng/pipelines/ci-copilot.ymlsrc/Core/src/Graphics/MauiDrawable.Android.cs
🧪 UI Tests — Category Detection
Detected UI test categories: Brush
🔍 Regression Cross-Reference
🔍 Regression Cross-Reference
🟢 No regression risks detected. No labeled bug-fix PRs in the last 6 months touched the modified files.
🔍 Pre-Flight — Context & Validation
Issue: #35280 - [Regression] LinearGradientBrush broken on Android in 10.0.60
PR: #35299 - [Android] Fix LinearGradientBrush rendering as opaque black box
Platforms Affected: Android (regression from 10.0.50 → 10.0.60)
Files Changed: 1 implementation, 2 test (+ 2 binary snapshots)
Key Findings
- Root Cause: PR Android drawable perf #31567 (Android drawable perf refactor) introduced
GetGradientData(1.0f)inMauiDrawable.Android.cs, forcing all gradient stop alpha values to fully opaque (255). This overrides any transparent/semi-transparent stops defined by the developer. - Regression: Confirmed regression — worked in 10.0.50, broken in 10.0.60.
- Fix: 4 one-line changes in
MauiDrawable.Android.cs:GetGradientData(1.0f)→GetGradientData(null), preserving per-stop alpha values. - Scope: Affects all 4 gradient paths:
SetBackground(LinearGradientPaint),SetBackground(RadialGradientPaint),SetBorderBrush(LinearGradientPaint),SetBorderBrush(RadialGradientPaint). - Reviewer feedback (Copilot inline):
- Radial gradient transparent-stop coverage is not tested by new test
- Border gradient path (
SetBorderBrush) is not tested (test usesStroke = Transparent, so border path isn't exercised) - Test comment references "red backdrop" but HostApp renders
dotnet_bot.pngimage
Code Review Summary
Verdict: NEEDS_CHANGES
Confidence: high
Errors: 1 | Warnings: 1 | Suggestions: 1
Key code review findings:
- ❌
TestCases.Shared.Tests/Tests/Issues/Issue35280.cs—VerifyScreenshot()runs on all platforms but only Android and iOS snapshots are provided; missing Windows/macOS snapshots cause confirmed CI failures. Fix: add[Platform(TestDevice.Android)]attribute or commit all platform snapshots. ⚠️ TestCases.Shared.Tests/Tests/Issues/Issue35280.cs:22— Test comment says "red background shows through" but HostApp usesdotnet_bot.pngimage — no red background exists. Inaccurate comment should be corrected.- 💡
TestCases.HostApp/Issues/Issue35280.cs— Missing trailing newline at end of file.
Impacted UI Test Categories
- Brush — PR directly modifies gradient brush rendering on Android
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| PR | PR #35299 | Change GetGradientData(1.0f) → GetGradientData(null) in all 4 gradient paths |
✅ PASSED (Gate) | MauiDrawable.Android.cs |
Original PR — minimal surgical fix |
🔬 Code Review — Deep Analysis
Code Review — PR #35299
Independent Assessment
What this changes: Four call sites in MauiDrawable.Android.cs that build gradient data for background and border rendering are changed from GetGradientData(1.0f) to GetGradientData(null). A new UI test page (Issue35280.cs) and screenshot test (Issue35280.cs) are added, along with Android and iOS reference snapshots.
Inferred motivation: Something introduced a hardcoded alpha override that forces every gradient stop to fully opaque, breaking any gradient that uses semi-transparent or transparent stops. The fix removes that override so stops render with their declared alpha values.
Reconciliation with PR Narrative
Author claims: Regression introduced by #31567 (Android drawable perf rewrite). The perf PR changed MauiDrawable.Android.cs to delegate to Java-side PlatformDrawable and wrote GetGradientData(1.0f) in that pass — 1.0f forces every stop's alpha to fully opaque, killing any transparency in gradients.
Agreement: This is entirely consistent with the code. GetGradientData(float? alphaOverride) at PaintExtensions.Android.cs:93–94 only applies the override when non-null. All other non-shadow callers in the codebase (lines 152, 158, 176, 187) already pass null. The shadow path in WrapperView.cs:90,94 correctly continues to pass shadowOpacity since shadow blending does require an explicit alpha override. The four changed call sites are the only remaining outliers — the fix is correct and the approach is sound.
Findings
❌ Error — Missing reference snapshots for Windows and macOS cause confirmed CI failures
VerifyScreenshot() in Issue35280.cs is a screenshot comparison test that runs on all platforms unless filtered. The PR provides snapshots only for Android (TestCases.Android.Tests/snapshots/android/) and iOS (TestCases.iOS.Tests/snapshots/ios/). Neither TestCases.WinUI.Tests/snapshots/windows/ nor TestCases.Mac.Tests/snapshots/mac/ contain a LinearGradientBrushTransparentStopsShouldNotBeOpaque.png.
CI confirms this: all five maui-pr-uitests (Border,BoxView,Brush,Button) jobs are failing — Android, Android CoreClr, WinUI, iOS, and macOS.
Two valid remedies:
Option A — Restrict the test to Android (matches PlatformAffected.Android on the host page, and the root cause is Android-specific):
[Test]
[Category(UITestCategories.Brush)]
[Platform(TestDevice.Android)]
public void LinearGradientBrushTransparentStopsShouldNotBeOpaque()Option B — Capture and commit Windows and macOS reference snapshots so the test can validate the cross-platform rendering.
⚠️ Warning — Test comment describes a "red background" that doesn't exist
Issue35280.cs (shared test), line 22:
// With the fix (GetGradientData(null)), per-stop alpha is preserved → red background shows through.The HostApp page sets a dotnet_bot.png image as the background — there is no red background anywhere. This comment is misleading and will confuse future readers trying to understand what the test is verifying.
💡 Suggestion — Missing newline at end of HostApp file
src/Controls/tests/TestCases.HostApp/Issues/Issue35280.cs is missing a trailing newline (\ No newline at end of file in the diff). Not a functional issue, but inconsistent with the rest of the codebase.
Devil's Advocate
On the core fix: Could null ever cause unintended rendering on Android? No — non-transparent stops are unaffected: color.WithAlpha(null) is never called (the guard is if (alphaOverride.HasValue)), so their natural alpha is preserved, rendering them as fully opaque exactly as before. The fix is narrowly correct.
On the missing snapshots: Could the Android/iOS CI jobs be failing for unrelated reasons? Possible — those jobs run many brush tests, and pre-existing flakes exist in the Brush category. However, WinUI and macOS failures are directly attributable to the missing snapshots; the PR author acknowledged only testing on Android.
On PlatformAffected.Android: This attribute is on the HostApp class only — it does not propagate to the test runner to auto-skip non-Android platforms. _IssuesUITest has no such filtering logic. The test will run everywhere.
Verdict: NEEDS_CHANGES
Confidence: high
Summary: The core fix (GetGradientData(null)) is correct, minimal, and consistent with every other non-shadow call site in the codebase. The problem is the test: it runs on all platforms but only provides Android and iOS snapshots, directly causing the five CI failures visible in maui-pr-uitests. The ❌ error (missing snapshots / missing platform filter) must be resolved before merge. The inaccurate comment is a
🔧 Fix — Analysis & Comparison
Fix Candidates
| # | Source | Approach | Test Result | Files Changed | Notes |
|---|---|---|---|---|---|
| 1 | try-fix (claude-opus-4.6) | Alpha Multiplier: change GetGradientData semantics so 1.0f multiplies (preserves) alpha instead of replacing it |
✅ PASS | PaintExtensions.Android.cs, MauiDrawable.Android.cs, Issue35280.cs |
Fixes semantics at source; adds platform guard |
| 2 | try-fix (claude-sonnet-4.6) | Parameterless Overloads: add GetGradientData() overloads that always pass null — unambiguous call-site API |
✅ PASS | PaintExtensions.Android.cs, MauiDrawable.Android.cs, Issue35280.cs |
New first-class API; runtime guard for Mac/Windows |
| 3 | try-fix (gpt-5.3-codex) | Split Pipelines: separate background/border gradient path (no alpha override) from shadow gradient path (shadow-specific helpers) | ✅ PASS | PaintExtensions.Android.cs, MauiDrawable.Android.cs, WrapperView.cs, Issue35280.cs |
Cleanest API design; most invasive; separates concerns |
| 4 | try-fix (claude-opus-4.6 #2) | Test-Quality Minimal Fix: same GetGradientData(null) impl + platform guard #if ANDROID || IOS on test + unit test for regression coverage |
✅ PASS | MauiDrawable.Android.cs, Issue35280.cs |
Minimal impl change; adds unit test as regression guard |
| PR | PR #35299 | Change GetGradientData(1.0f) → GetGradientData(null) at 4 call sites in MauiDrawable.Android.cs |
✅ PASSED (Gate) | MauiDrawable.Android.cs |
Original PR — minimal fix; test missing platform guard |
Cross-Pollination
| Model | Round | New Ideas? | Details |
|---|---|---|---|
| claude-opus-4.6 | 2 | NO NEW IDEAS | Attempts 1-4 cover multiplication, parameterless API, split pipelines, and minimal+test-quality approaches |
| claude-sonnet-4.6 | 2 | NO NEW IDEAS | All viable approaches explored |
| gpt-5.3-codex | 2 | NO NEW IDEAS | All root cause hypotheses exhausted |
| gemini-3-pro-preview | 2 | NO NEW IDEAS | Minimal and architectural approaches covered |
Exhausted: Yes
Selected Fix: try-fix-4 — Minimal implementation change (same as PR) + platform guard fixes CI failures + unit test prevents regression. Balances correctness, minimal invasiveness, and test coverage.
📋 Report — Final Recommendation
⚠️ Final Recommendation: REQUEST CHANGES
Phase Status
| Phase | Status | Notes |
|---|---|---|
| Pre-Flight | ✅ COMPLETE | Issue #35280, Android regression, 1 impl file + 2 test files |
| Code Review | NEEDS_CHANGES (high) | 1 error, 1 warning, 2 suggestions |
| Gate | ✅ PASSED | android |
| Try-Fix | ✅ COMPLETE | 4 attempts, 4 passing |
| Report | ✅ COMPLETE |
Code Review Impact on Try-Fix
The code review's ❌ Error (missing Windows/Mac snapshot baselines causing CI failures on all platforms) directly shaped all 4 try-fix attempts — every model added a platform guard to the test as part of their fix. The failure-mode probe about PlatformAffected.Android not being enforced by the test runner was addressed by attempts 1–4. Attempt 4 (test-quality minimal fix) was closest to the code review's recommended remediation: keep the proven GetGradientData(null) impl and add #if ANDROID || IOS guard.
Summary
The PR's core 4-line implementation fix (changing GetGradientData(1.0f) → GetGradientData(null) in MauiDrawable.Android.cs) is correct and complete — it restores per-stop alpha values for all four gradient paths (linear/radial background/border). Gate passed. However, the test as submitted causes CI failures on Windows and macOS because VerifyScreenshot() runs on all platforms but only Android and iOS reference snapshots were committed. The PR requires test fixes before merge.
Winner selected: pr-plus-reviewer — The PR's implementation approach is the best: minimal, surgical, consistent with all other non-shadow GetGradientData callers. With the expert reviewer's feedback applied (platform guard #if ANDROID || IOS + comment correction), the PR becomes complete and correct. No alternative fix approach (API redesign, parameterless overloads, split pipelines) is warranted for this narrowly scoped bug fix.
Root Cause
PR #31567 (Android drawable perf) refactored MauiDrawable.Android.cs to use a Java-side PlatformDrawable. In that refactor, GetGradientData(1.0f) was written at 4 call sites. The alphaOverride parameter in PaintExtensions.Android.cs replaces each stop's alpha when non-null — so 1.0f forces all stops to full opacity, destroying any transparency. All other non-shadow callers already passed null; only MauiDrawable's paths were affected.
Fix Quality
Implementation: ✅ Correct and complete. The 4-line fix aligns MauiDrawable with the rest of the codebase. Shadow rendering in WrapperView.cs (which legitimately overrides alpha for shadow blending) is unaffected.
Test:
- ❌ [Blocking]
VerifyScreenshot()runs on all platforms; only Android and iOS snapshots provided → Windows and macOS CI fail. Fix: add#if ANDROID || IOS(or equivalent runtime guard). ⚠️ Test comment at line 22 says "red background shows through" but HostApp usesdotnet_bot.png— no red background exists. Update comment to describe the dotnet_bot image.
Candidate Comparison
| Candidate | Implementation | Test Issue Fixed | Invasiveness | Verdict |
|---|---|---|---|---|
pr |
✅ Correct | ❌ Missing platform guard | Minimal (4 lines) | Needs test fix |
pr-plus-reviewer |
✅ Correct | ✅ #if ANDROID || IOS + comment fix |
Minimal (4 impl + 3 test lines) | Winner |
try-fix-1 |
✅ Alpha multiplier (semantic change) | ✅ | Moderate (API semantics changed) | Over-engineered for this bug |
try-fix-2 |
✅ Parameterless overloads | ✅ | Moderate (new public API surface) | Over-engineered |
try-fix-3 |
✅ Split pipelines | ✅ | High (4 files, WrapperView refactored) | Too invasive for a regression fix |
try-fix-4 |
✅ Same as PR + unit test | ✅ | Low (= pr-plus-reviewer + unit test) | Good alternative; unit test is bonus |
Selected Fix: PR's fix approach (pr-plus-reviewer) — The implementation is correct. The only required changes are in the test file. Try-fix alternatives improve API design but are over-engineered for a targeted regression fix to main.
|
/backport to release/10.0.1xx-sr7 |
|
Started backporting to |
… opaque black box (#35424) Backport of #35299 to release/10.0.1xx-sr7 /cc @kubaflo @SubhikshaSf4851 --------- Co-authored-by: Subhiksha Chandrasekaran <subhiksha.c@syncfusion.com> Co-authored-by: Dhivya-SF4094 <127717131+Dhivya-SF4094@users.noreply.github.com>
<!-- Please keep the note below for people who 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 whether this change resolves your issue. Thank you! <!-- !!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING MAIN. !!!!!!! --> This pull request fixes a regression where LinearGradientBrush with transparent stops rendered as opaque black boxes on Android starting in 10.0.60. The fix preserves per-stop alpha values so gradients render correctly. ### Root Cause : - Introduced by #31567 (Android drawable perf), which rewrote MauiDrawable.Android.cs to use a Java-side PlatformDrawable. - In that refactor, calls to GetGradientData were written as GetGradientData(1.0f), which forces every gradient stop's alpha to fully opaque (255), overriding any Transparent stop colors defined by the developer. ### Description of Change **Bug fix: Gradient transparency on Android** * Updated `MauiDrawable.Android.cs` so that both linear and radial gradient paints now call `GetGradientData(null)` instead of `GetGradientData(1.0f)`, preserving per-stop alpha values for backgrounds and borders. This prevents gradients with transparent stops from rendering as solid black. [[1]](diffhunk://#diff-9962b2ab4d4a0eb4922307e668bfe7d868c4fac7919a9463a3cba1859a6de86fL115-R115) [[2]](diffhunk://#diff-9962b2ab4d4a0eb4922307e668bfe7d868c4fac7919a9463a3cba1859a6de86fL129-R129) [[3]](diffhunk://#diff-9962b2ab4d4a0eb4922307e668bfe7d868c4fac7919a9463a3cba1859a6de86fL250-R250) [[4]](diffhunk://#diff-9962b2ab4d4a0eb4922307e668bfe7d868c4fac7919a9463a3cba1859a6de86fL264-R264) **Testing: New test case and UI test** * Added a new issue test page `Issue35280` that displays an image with a linear gradient overlay fading from black to transparent, to visually confirm the fix. * Introduced a corresponding UI test in `Issue35280.cs` to verify that the gradient overlay is rendered correctly and not as an opaque black box. <!-- 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 #35280 ### Tested the behavior in the following platforms - [ ] Windows - [x] Android - [ ] iOS - [ ] Mac | Before Issue Fix | After Issue Fix | |----------|----------| | <img width="1080" height="1920" alt="Screenshot_1777904296" src="https://github.com/user-attachments/assets/a3ed29f1-9f85-44e7-9d4a-14e343aa8bda" /> | <img width="1080" height="1920" alt="Screenshot_1777904172" src="https://github.com/user-attachments/assets/c1f4be01-7af1-4e68-a36b-766ef167062f" /> | <!-- Are you targeting main? All PRs should target the main branch unless otherwise noted. -->
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 whether this change resolves your issue. Thank you!
This pull request fixes a regression where LinearGradientBrush with transparent stops rendered as opaque black boxes on Android starting in 10.0.60. The fix preserves per-stop alpha values so gradients render correctly.
Root Cause :
Description of Change
Bug fix: Gradient transparency on Android
MauiDrawable.Android.csso that both linear and radial gradient paints now callGetGradientData(null)instead ofGetGradientData(1.0f), preserving per-stop alpha values for backgrounds and borders. This prevents gradients with transparent stops from rendering as solid black. [1] [2] [3] [4]Testing: New test case and UI test
Issue35280that displays an image with a linear gradient overlay fading from black to transparent, to visually confirm the fix.Issue35280.csto verify that the gradient overlay is rendered correctly and not as an opaque black box.Issues Fixed
Fixes #35280
Fixes #35354
Tested the behavior in the following platforms