Skip to content

[Android, iOS] Button: Fix VisualState properties not restored when leaving custom state#33346

Open
BagavathiPerumal wants to merge 7 commits intodotnet:mainfrom
BagavathiPerumal:fix-19690
Open

[Android, iOS] Button: Fix VisualState properties not restored when leaving custom state#33346
BagavathiPerumal wants to merge 7 commits intodotnet:mainfrom
BagavathiPerumal:fix-19690

Conversation

@BagavathiPerumal
Copy link
Copy Markdown
Contributor

@BagavathiPerumal BagavathiPerumal commented Dec 31, 2025

Note

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

Root Cause:

The issue occurs because platform handlers on iOS and Android do not restore button properties to their default values when VisualState setters are removed. In .NET MAUI, when a control transitions from a custom VisualState back to the normal state, property values are set to null to indicate that defaults should be restored. However, the platform handlers interpreted these null values as instructions to take no action, causing previously applied custom values to remain.

Fix Description:

The fix involves updating button-specific extension methods to ensure properties are correctly restored to their platform default values when property values are null.

For iOS, the UpdateBackground extension method now explicitly handles UIButton instances. When the background is null or empty, RemoveBackgroundLayer() is called first to prevent stacking gradient layers, and the background is reset to UIColor.Clear. This restores proper transparency and aligns with the default iOS button appearance. When a valid background is provided, the update continues through the existing view background logic.

The UpdateTextColor method was also improved to restore the system default text color correctly when TextColor is null. If the button is attached to a UIWindow, the handler clears explicit overrides using SetTitleColor(null, …) for the Normal, Highlighted, and Disabled states, allowing iOS to fall back to its natural appearance-proxy behavior. It then restores TintColor using window.TintColor rather than a hardcoded system color. This ensures the app’s global tint is respected and prevents clearing appearance settings during the initial render phase.

For Android, a MaterialButton-specific UpdateTextColor overload was introduced in MauiMaterialButton. The default Material theme ColorStateList is cached as DefaultTextColors during construction, before any MAUI property mapping occurs. When TextColor becomes null, the cached state list is restored directly, preserving all theme-defined states (normal, disabled, etc.). This approach avoids creating temporary controls and guarantees consistent restoration of the original Material theme colors.

Issues Fixed

Fixes #19690

Tested the behaviour in the following platforms

  • Mac
  • Windows
  • iOS
  • Android

Output Screenshot

Platform Before Fix After Fix
Android
ButtonVisualState.Android.-BeforeFix.mov
ButtonVisualState.Android.-AfterFix.mov
iOS
ButtonVisualState.iOS.-BeforeFix.mov
ButtonVisualState.iOS.-AfterFix.mov

@sheiksyedm
Copy link
Copy Markdown
Contributor

/azp run maui-pr-uitests

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@rmarinho rmarinho added s/agent-review-incomplete AI agent could not complete all phases (blocker, timeout, error) s/agent-fix-lose Author adopted the agent's fix and it turned out to be bad s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review) labels Feb 18, 2026
@BagavathiPerumal BagavathiPerumal changed the title [Android, iOS] Fix for Button VisualStates do not work [Android, iOS] Button: Fix VisualState properties not restored when leaving custom state Feb 19, 2026
@kubaflo kubaflo added s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates and removed s/agent-fix-lose Author adopted the agent's fix and it turned out to be bad labels Feb 20, 2026
@BagavathiPerumal
Copy link
Copy Markdown
Contributor Author

🤖 AI Summary

📊 Expand Full Review
🔍 Pre-Flight — Context & Validation
📝 Review Sessionfix-19690-Made code changes to cache DefaultTextColors in MauiMaterialButton and use it in UpdateTextColor for proper VisualState reset. · 7e532c7
Issue: #19690 - Button VisualStates do not work PR: #33346 - [Android, iOS] Fix for Button VisualStates do not work Author: BagavathiPerumal (community contribution, Syncfusion partner) Platforms Affected: iOS, Android, macOS (not Windows - confirmed in original issue) Files Changed: 4 implementation files, 2 test files, 6 snapshot images

Issue Summary

When a Button uses custom VisualState setters (e.g., TextColor=Yellow, BackgroundColor=Purple), transitioning back from the custom state to the Normal state fails to restore the original platform defaults. The properties visually remain in the Custom state.

Root cause: Platform handlers treated null property values (which signal "reset to default") as no-ops rather than restoration triggers.

Files Changed

Fix files:

  • src/Core/src/Handlers/Button/ButtonHandler.iOS.cs (+7/-1) - MapBackground now passes button.Background (Paint) instead of full button (IButton) and adds #else iOS implementation
  • src/Core/src/Platform/iOS/ButtonExtensions.cs (+22/-4) - UpdateTextColor resets to UIColor.SystemBlue when null; new UpdateBackground(UIButton, Paint?) resets to UIColor.Clear
  • src/Core/src/Platform/Android/ButtonExtensions.cs (+16) - New internal UpdateTextColor(MaterialButton, ITextStyle) that restores cached default ColorStateList when null
  • src/Core/src/Platform/Android/MauiMaterialButton.cs (+10) - Caches DefaultTextColors at construction time

Test files:

  • src/Controls/tests/TestCases.HostApp/Issues/Issue19690.cs (+114) - UI test page with custom button toggling states
  • src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue19690.cs (+33) - NUnit screenshot-based test

Snapshot files: 6 PNG snapshots (Android + iOS 3 states)

Fix Candidates

Source Approach Test Result Files Changed Notes

PR PR #33346 iOS: reset to UIColor.SystemBlue for null TextColor, UIColor.Clear for null Background; Android: cache DefaultTextColors in MauiMaterialButton constructor, restore on PENDING (Gate) 4 files Original PR null

Reviewer Disagreements / Edge Cases

No inline review comments found. No prior agent review detected.

Notable concerns from code review:

  • iOS fix hardcodes UIColor.SystemBlue as the default - won't be correct if app uses a custom tint color
  • iOS Disabled state also receives SystemBlue (normally should be grayed out)
  • PR description says "creates a temporary MaterialButton" but actual code uses cached DefaultTextColors (minor inaccuracy in description)

🚦 Gate — Test Verification
📝 Review Sessionfix-19690-Made code changes to cache DefaultTextColors in MauiMaterialButton and use it in UpdateTextColor for proper VisualState reset. · 7e532c7
** FAILEDResult:** Platform: android Mode: Full Verification

  • Tests FAIL without (Tests PASSED - expected to fail)fix
  • Tests PASS with fix

Notes

The verification script correctly ran two test passes (WITHOUT fix then WITH fix). The test ButtonVisualStatesShouldToggleBetweenNormalAndCustom passed in both cases.

Likely cause: The test uses screenshot-based comparison (VerifyScreenshotOrSetException) against baseline images. The stored baselines represent the correct behavior (fix applied). Without the fix, the button should visually stay in the Custom state on the second tap, which should cause the Issue19690_BackToNormalState screenshot comparison to fail.

The test passing without fix could indicate:

  1. The emulator API 30 device produces screenshots that don't differ visually between buggy/fixed states
  2. Build/deployment caching caused the fixed app to be tested in both passes
  3. The tolerance in screenshot comparison is allowing the mismatch

Recommendation: PR author should manually verify that the tests fail without the fix applied by running BuildAndRunHostApp.ps1 -Platform android -TestFilter Issue19690 after reverting the fix files.

The Gate technically failed per automated verification. Proceeding autonomously to Fix and Report phases.

🔧 Fix — Analysis & Comparison
📝 Review Sessionfix-19690-Made code changes to cache DefaultTextColors in MauiMaterialButton and use it in UpdateTextColor for proper VisualState reset. · 7e532c7
Status: ⚠️ PARTIAL (Rate limit blocked attempts 6+) Platform: android Round 1: 5/5 models completed Cross-Pollination: 1 round completed (1 NO NEW IDEAS, 4 NEW IDEAS proposed, attempts 6+ blocked by rate limit)

Fix Candidates

Source Approach Test Result Files Changed Notes

PR PR #33346 Cache DefaultTextColors in MauiMaterialButton constructors + iOS fallback to UIColor.SystemBlue ✅ PASS (Gate: ⚠️ INCONCLUSIVE - env issue) 5 files iOS concern: hardcoded SystemBlue
1 try-fix (claude-sonnet-4.5) Dynamic theme query: GetDefaultTextColorFromTheme() creates temp MaterialButton per call ✅ PASS ButtonExtensions.cs (1 file) Simpler but allocates temp object on each null-color call
2 try-fix (claude-opus-4.6) Handler-level snapshot: _defaultTextColors captured in ConnectHandler ✅ PASS ButtonHandler.Android.cs, ButtonExtensions.cs, ButtonHandler.iOS.cs, ButtonExtensions.iOS.cs (4 files) Clean separation of concerns; zero-allocation restoration
3 try-fix (gpt-5.2) View-level default capture: CapturePlatformDefaultsIfNeeded() + OnAttachedToWindow override ✅ PASS MauiMaterialButton.cs, ButtonExtensions.cs, ButtonHandler.Android.cs, PublicAPI.Unshipped.txt (4 files) Captures more state (background, tints, ripple)
4 try-fix (gpt-5.1-codex) Theme attribute fallback: TextColorPrimary from Android theme in TextViewExtensions.cs ❌ FAIL TextViewExtensions.cs Wrong color - generic theme attr != MaterialButton style attr (~1.93% diff)
5 try-fix (gemini-3-pro-preview) Static WeakReference<ColorStateList> cache in ButtonExtensions ✅ PASS ButtonExtensions.cs (1 file) Lazily creates temp MaterialButton once; simplest approach
6 try-fix (cross-poll) TypedArray via materialButtonStyle attr resolution ⚠️ BLOCKED (rate limit) - Proposed by claude-sonnet-4.5, gpt-5.2, gemini; TypedArray reading materialButtonStyle chain
7 try-fix (cross-poll) VisualStateManager hook to re-apply handler snapshot on Normal state ⚠️ BLOCKED (rate limit) - Proposed by gpt-5.1-codex; genuinely different but complex

Cross-Pollination Round 1

Model Response
claude-sonnet-4.5 NEW IDEA: TypedArray via materialButtonStyletextAppearanceButton → textColor
claude-opus-4.6 NO NEW IDEAS - all major patterns covered
gpt-5.2 NEW IDEA: TypedArray materialButtonStyle chain resolution
gpt-5.1-codex NEW IDEA: VisualStateManager hook to re-apply handler snapshot when returning to Normal
gemini-3-pro-preview NEW IDEA: ObtainStyledAttributes from Widget.MaterialComponents.Button style
Note: Attempts 6-7 blocked by Copilot token rate limit. Cannot determine if TypedArray approach would be better than attempt 4's failure.

Analysis

Root Cause: TextViewExtensions.UpdateTextColor returns early when textColor == null instead of restoring defaults. Same for iOS. VisualState transitions that clear a setter pass null, expecting the platform to reset — but the platform does nothing.

Key Finding: The theme attribute approach (attempt 4) FAILED because TextColorPrimary is too generic — MaterialButton uses Material Design's colorOnPrimary token, not the standard text color. Attempts 1, 2, 3, 5 all PASSED by querying the correct defaults via a real MaterialButton instance (temp or cached).

Attempt 4 failure lesson: Don't use generic Android theme attributes to resolve MaterialButton defaults — the Material Design token system maps to different attributes than the standard Android text style system.

Selected Fix

Exhausted: No (rate limit prevented attempts 6-7)

Selected Fix: #5 (Static WeakRef cache) OR PR's fix — see comparison:

PR's fix Candidate #5
Files changed 5 (including iOS) 1 (ButtonExtensions.cs)
iOS fix ✅ included (hardcoded UIColor.SystemBlue) ❌ Android only
Android approach Cache in constructors Lazy static WeakRef cache
Correctness ✅ correct ✅ correct
iOS concern ⚠️ SystemBlue wrong for custom tint N/A
Recommendation: PR's fix is more complete (includes iOS). However, the iOS fix has a correctness concern (hardcoded UIColor.SystemBlue). If the iOS concern is addressed, PR's fix is the best overall solution. As an Android-only alternative, Candidate #5 (1-file change) is the cleanest.

📋 Report — Final Recommendation
📝 Review Sessionfix-19690-Made code changes to cache DefaultTextColors in MauiMaterialButton and use it in UpdateTextColor for proper VisualState reset. · 7e532c7
Final Recommendation: ⚠️ REQUEST CHANGES

Phase Summary

Phase Status Notes
Pre-Flight ✅ Complete Community PR from Syncfusion, issue #19690, Android+iOS
Gate ⚠️ Inconclusive Tests pass both with/without fix (env issue - app caching or test reliability)
Fix ⚠️ Partial 4/5 attempts PASS; cross-poll attempts 6-7 blocked by rate limit
pr-finalize ✅ Complete Title inaccurate; description has stale content; iOS correctness concern

pr-finalize Results

Title: Needs Update

Current: [Android, iOS] Fix for Button VisualStates do not work

Problems:

  • "Fix for" is redundant/verbose
  • "do not work" is vague - doesn't describe what was fixed

Recommended: [Android, iOS] Button: Restore platform defaults when VisualState setters are unapplied

Description: Needs Update (Stale Content)

Quality Assessment:

  • NOTE block: ✅ Present
  • Root cause: ✅ Good explanation
  • Issues Fixed: ✅ Present
  • Accuracy: ❌ Stale - describes old approach for Android

Critical inaccuracy:

"For Android...it creates a temporary MaterialButton to retrieve and apply the current Material theme's default text colors."

This is wrong. The actual implementation caches DefaultTextColors in MauiMaterialButton constructors — no temporary MaterialButton is created at runtime. This appears to be leftover from an earlier approach.

Suggested description update:

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you!

### Root Cause

When a Button uses VisualState setters (e.g., TextColor=Yellow, BackgroundColor=Purple) and transitions back to Normal state, MAUI sets the property values to null to signal "reset to default." However, the platform handlers treated null as no-op — returning early instead of restoring original defaults. This left the custom visual state values applied permanently.

### Description of Change

**Android:**
- Added `DefaultTextColors` property to `MauiMaterialButton`, cached in all constructors
- Added `internal UpdateTextColor(MaterialButton, ITextStyle)` in `ButtonExtensions.cs` that is preferred over `TextViewExtensions.UpdateTextColor(TextView, ITextStyle)` due to more specific overload resolution
- When TextColor is null, restores the cached `DefaultTextColors` instead of doing nothing

**iOS:**
- `UpdateTextColor` now restores `UIColor.SystemBlue` when TextColor is null
- Added `internal UpdateBackground(UIButton, Paint?)` that resets to `UIColor.Clear` when paint is null
- `ButtonHandler.iOS.cs` `MapBackground` updated to call `UpdateBackground(button.Background)` (the Paint? overload) to enable null-detection

### What NOT to Do (for future agents)

- ❌ **Don't use `TextViewExtensions.UpdateTextColor`** for Button/MaterialButton null-restoration — it's for generic TextViews and has no knowledge of MaterialButton defaults
- ❌ **Don't read `TextColorPrimary` from Android theme** — MaterialButton uses Material Design `colorOnPrimary` token, not the generic text color attribute (~1.93% visual diff in tests)
- ❌ **Don't assume `UIColor.SystemBlue` is the correct iOS default** — this is only correct for apps using default system tint; apps with custom tints will show wrong color after restoration

### Issues Fixed
Fixes #19690

### Platforms Tested
- [x] iOS
- [x] Android

Code Review Findings

🔴 Critical Issues

iOS: Hardcoded UIColor.SystemBlue as TextColor fallback

  • File: src/Core/src/Platform/iOS/ButtonExtensions.cs
  • Code: var color = button.TextColor?.ToPlatform() ?? UIColor.SystemBlue;
  • Problem: UIColor.SystemBlue is only correct if the app uses the default system tint. Apps using UINavigationBar.Appearance.TintColor or other tint customizations will see the wrong color restored after VisualState Normal is applied. The correct fallback should be the button's actual tint color or TintColor.
  • Recommendation: Use platformButton.TintColor as the fallback (which is the platform-appropriate default for buttons) or query the theme for the correct color:
    var color = button.TextColor?.ToPlatform() ?? platformButton.TintColor;

🟡 Suggestions

1. Android: DefaultTextColors in JNI constructor may be unreliable

  • File: src/Core/src/Platform/Android/MauiMaterialButton.cs
  • Code: protected MauiMaterialButton(nint javaReference, JniHandleOwnership transfer) : base(javaReference, transfer) { DefaultTextColors = TextColors; }
  • Issue: When reconstructed via JNI marshaling, the TextColors may reflect custom values already applied, not the platform defaults. Consider only setting DefaultTextColors if it hasn't been set yet, or skipping the JNI constructor.

2. Android: UpdateButtonBackground description The existing UpdateButtonBackground still creates a temporary MaterialButton for background tint querying (inside the lambda). Now that DefaultBackgroundTintList could be cached (as Attempt #3 showed), this could be optimized, but it's not a blocker.

3. iOS: MapBackground for MacCatalyst

  • File: src/Core/src/Handlers/Button/ButtonHandler.iOS.cs
  • The #else block adds internal static void MapBackground for MacCatalyst with a TODO. The TODO says "Make this public in .NET 11" but doesn't reference the issue that tracks this. Consider adding a GitHub issue reference.

✅ Looks Good

  • Android internal UpdateTextColor(MaterialButton, ITextStyle) correctly uses overload resolution (MaterialButton is more specific than TextView) to be preferred without explicitly calling it
  • The DefaultTextColors caching approach in constructors is correct and zero-allocation at runtime
  • Test structure is solid: 3 screenshots (Initial, Custom, BackToNormal) with VerifyScreenshotOrSetException pattern

Fix Candidates Summary

Source Approach Result Files

PR PR #33346 Cache defaults in MauiMaterialButton + iOS SystemBlue fallback ✅ Gate (⚠️ inconclusive) 5 files
1 try-fix Dynamic temp MaterialButton per-call ✅ PASS 1 file
2 try-fix Handler-level snapshot in ConnectHandler ✅ PASS 4 files
3 try-fix View-level CapturePlatformDefaults + OnAttachedToWindow ✅ PASS 4 files
4 try-fix Android TextColorPrimary theme attr ❌ FAIL 1 file
5 try-fix Static WeakRef lazy cache ✅ PASS 1 file
Note: Gate failed due to environment issue (tests pass both with and without fix). Try-fix "Pass" results may be similarly inconclusive. All approaches are architecturally sound based on code analysis.

Final Recommendation

⚠️ REQUEST CHANGES - The PR has the right approach but needs two fixes before merge:

  1. 🔴 MUST FIX: iOS UIColor.SystemBlue hardcode should be replaced with platformButton.TintColor to correctly handle apps with custom tint colors
  2. 🟡 SHOULD FIX: PR description is stale (describes old "temporary MaterialButton" approach; actual code uses constructor caching)

If the iOS concern is addressed, the Android approach (constructor caching of DefaultTextColors) is correct and robust. Alternative Candidate #5 (1-file change, static WeakRef cache) is simpler but Android-only — the PR's approach is more complete since it also fixes iOS.

Selected Fix: PR's fix (once iOS concern is addressed)

📋 Expand PR Finalization Review

I’ve updated the changes based on the review comments. Specifically:

  • Replaced the hardcoded UIColor.SystemBlue fallback by clearing explicit overrides with SetTitleColor(null, …) and restoring the default using window.TintColor, ensuring the app’s global tint and native disabled-state behavior are preserved
  • Added a clarifying comment in the Android JNI constructor to document that TextColors is captured after the native MaterialButton is fully themed, making the DefaultTextColors caching behavior explicit

These updates ensure the fix aligns with native platform behavior and remains safe and consistent within dotnet/maui.

@sheiksyedm sheiksyedm marked this pull request as ready for review February 25, 2026 12:23
Copilot AI review requested due to automatic review settings February 25, 2026 12:23
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a critical bug where Button VisualState properties were not being properly restored when transitioning from custom states back to normal state on iOS and Android. The root cause was that platform handlers were treating null property values as a "no-op" instead of as an instruction to restore default values.

Changes:

  • iOS: Updated UpdateTextColor to clear explicit overrides and restore window tint color; added button-specific UpdateBackground to handle null values by resetting to UIColor.Clear
  • Android: Introduced MaterialButton-specific UpdateTextColor overload that caches and restores the original Material theme ColorStateList
  • Tests: Added comprehensive UI tests with screenshot verification across all platforms

Reviewed changes

Copilot reviewed 7 out of 19 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/Core/src/Platform/iOS/ButtonExtensions.cs Added null handling for UpdateTextColor (clears explicit overrides, restores window tint) and new internal UpdateBackground method for UIButton
src/Core/src/Platform/Android/ButtonExtensions.cs Added MaterialButton-specific UpdateTextColor overload that restores cached default ColorStateList
src/Core/src/Platform/Android/MauiMaterialButton.cs Added DefaultTextColors property to cache original Material theme colors at construction time
src/Core/src/Handlers/Button/ButtonHandler.iOS.cs Updated MapBackground to call new button-specific UpdateBackground method with Paint parameter
src/Core/src/PublicAPI/net-android/PublicAPI.Unshipped.txt Added public API entry for new UpdateTextColor extension method
src/Controls/tests/TestCases.HostApp/Issues/Issue19690.cs Created test page with custom button that toggles between Normal and Custom VisualStates
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue19690.cs Added NUnit UI test with three-state screenshot verification
src/Controls/tests/TestCases.*.Tests/snapshots/*/Issue19690_*.png Screenshot baselines for Windows and Mac platforms (3 states each)

@sheiksyedm
Copy link
Copy Markdown
Contributor

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

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 2 pipeline(s).

@dotnet dotnet deleted a comment from rmarinho Mar 18, 2026
@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented Mar 28, 2026

🚦 Gate - Test Before and After Fix

📊 Expand Full Gate8042200 · fix-19690-Made code changes to modify the android fix and updated the testcase.

Gate Result: ✅ PASSED

Platform: ANDROID · Base: main · Merge base: 794a9fa6

Test Without Fix (expect FAIL) With Fix (expect PASS)
🖥️ Issue19690 Issue19690 ✅ FAIL — 781s ✅ PASS — 1326s
🔴 Without fix — 🖥️ Issue19690: FAIL ✅ · 781s
  Determining projects to restore...
  Restored /home/vsts/work/1/s/src/Graphics/src/Graphics/Graphics.csproj (in 569 ms).
  Restored /home/vsts/work/1/s/src/Essentials/src/Essentials.csproj (in 4.43 sec).
  Restored /home/vsts/work/1/s/src/Core/src/Core.csproj (in 5.71 sec).
  Restored /home/vsts/work/1/s/src/Core/maps/src/Maps.csproj (in 2.3 sec).
  Restored /home/vsts/work/1/s/src/Controls/src/Xaml/Controls.Xaml.csproj (in 48 ms).
  Restored /home/vsts/work/1/s/src/Controls/src/Core/Controls.Core.csproj (in 37 ms).
  Restored /home/vsts/work/1/s/src/Controls/Maps/src/Controls.Maps.csproj (in 34 ms).
  Restored /home/vsts/work/1/s/src/Controls/Foldable/src/Controls.Foldable.csproj (in 55 ms).
  Restored /home/vsts/work/1/s/src/BlazorWebView/src/Maui/Microsoft.AspNetCore.Components.WebView.Maui.csproj (in 643 ms).
  Restored /home/vsts/work/1/s/src/Controls/tests/TestCases.HostApp/Controls.TestCases.HostApp.csproj (in 1.34 sec).
  1 of 11 projects are up-to-date for restore.
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0-android36.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0-android36.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  Core -> /home/vsts/work/1/s/artifacts/bin/Core/Debug/net10.0-android36.0/Microsoft.Maui.dll
  Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  Maps -> /home/vsts/work/1/s/artifacts/bin/Maps/Debug/net10.0-android36.0/Microsoft.Maui.Maps.dll
  Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.Core/Debug/net10.0-android36.0/Microsoft.Maui.Controls.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  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
  Controls.Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.Maps/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Maps.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.60-ci+azdo.13750574
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  Core -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.dll
  Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Maps.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  Microsoft.AspNetCore.Components.WebView.Maui -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.AspNetCore.Components.WebView.Maui.dll
  Controls.Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Maps.dll
  Controls.Foldable -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Foldable.dll
  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:08:21.27
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/UITest.NUnit/UITest.NUnit.csproj (in 2.26 sec).
  Restored /home/vsts/work/1/s/src/TestUtils/src/UITest.Core/UITest.Core.csproj (in 6 ms).
  Restored /home/vsts/work/1/s/src/TestUtils/src/UITest.Appium/UITest.Appium.csproj (in 1.66 sec).
  Restored /home/vsts/work/1/s/src/TestUtils/src/UITest.Analyzers/UITest.Analyzers.csproj (in 3.04 sec).
  Restored /home/vsts/work/1/s/src/TestUtils/src/VisualTestUtils/VisualTestUtils.csproj (in 4 ms).
  Restored /home/vsts/work/1/s/src/TestUtils/src/VisualTestUtils.MagickNet/VisualTestUtils.MagickNet.csproj (in 7.92 sec).
  Restored /home/vsts/work/1/s/src/Controls/tests/CustomAttributes/Controls.CustomAttributes.csproj (in 12 ms).
  Restored /home/vsts/work/1/s/src/Controls/tests/TestCases.Android.Tests/Controls.TestCases.Android.Tests.csproj (in 1.86 sec).
  5 of 13 projects are up-to-date for restore.
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  Controls.CustomAttributes -> /home/vsts/work/1/s/artifacts/bin/Controls.CustomAttributes/Debug/net10.0/Controls.CustomAttributes.dll
  Core -> /home/vsts/work/1/s/artifacts/bin/Core/Debug/net10.0/Microsoft.Maui.dll
  Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
  UITest.Core -> /home/vsts/work/1/s/artifacts/bin/UITest.Core/Debug/net10.0/UITest.Core.dll
  UITest.Appium -> /home/vsts/work/1/s/artifacts/bin/UITest.Appium/Debug/net10.0/UITest.Appium.dll
  UITest.NUnit -> /home/vsts/work/1/s/artifacts/bin/UITest.NUnit/Debug/net10.0/UITest.NUnit.dll
  VisualTestUtils -> /home/vsts/work/1/s/artifacts/bin/VisualTestUtils/Debug/netstandard2.0/VisualTestUtils.dll
  VisualTestUtils.MagickNet -> /home/vsts/work/1/s/artifacts/bin/VisualTestUtils.MagickNet/Debug/netstandard2.0/VisualTestUtils.MagickNet.dll
  UITest.Analyzers -> /home/vsts/work/1/s/artifacts/bin/UITest.Analyzers/Debug/netstandard2.0/UITest.Analyzers.dll
  Controls.TestCases.Android.Tests -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll
Test run for /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll (.NETCoreApp,Version=v10.0)
VSTest version 18.0.1 (x64)

Starting test execution, please wait...
A total of 1 test files matched the specified pattern.
/home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll
[xUnit.net 00:00:00.00] xUnit.net VSTest Adapter v2.8.2+699d445a1a (64-bit .NET 10.0.0)
[xUnit.net 00:00:00.15]   Discovering: Controls.TestCases.Android.Tests
[xUnit.net 00:00:00.53]   Discovered:  Controls.TestCases.Android.Tests
NUnit Adapter 4.5.0.0: Test execution started
Running selected tests in /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll
   NUnit3TestExecutor discovered 1 of 1 NUnit test cases using Current Discovery mode, Non-Explicit run
>>>>> 04/05/2026 22:17:40 FixtureSetup for Issue19690(Android)
>>>>> 04/05/2026 22:17:43 ButtonVisualStatesShouldToggleBetweenNormalAndCustom Start
>>>>> 04/05/2026 22:17:53 ButtonVisualStatesShouldToggleBetweenNormalAndCustom Stop
>>>>> 04/05/2026 22:17:53 Log types: logcat, bugreport, server
  Failed ButtonVisualStatesShouldToggleBetweenNormalAndCustom [11 s]
  Error Message:
   VisualTestUtils.VisualTestFailedException : 
Snapshot different than baseline: Issue19690_BackToNormalState.png (1.19% 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.Issue19690.ButtonVisualStatesShouldToggleBetweenNormalAndCustom() in /_/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue19690.cs:line 30
   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.5102 Minutes

🟢 With fix — 🖥️ Issue19690: PASS ✅ · 1326s

(truncated to last 15,000 chars)

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:11:10.45
* daemon not running; starting now at tcp:5037
* daemon started successfully
  Determining projects to restore...
  All projects are up-to-date for restore.
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0-android36.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0-android36.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  Core -> /home/vsts/work/1/s/artifacts/bin/Core/Debug/net10.0-android36.0/Microsoft.Maui.dll
  Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  Maps -> /home/vsts/work/1/s/artifacts/bin/Maps/Debug/net10.0-android36.0/Microsoft.Maui.Maps.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.Core/Debug/net10.0-android36.0/Microsoft.Maui.Controls.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  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.60-ci+azdo.13750574
  Controls.Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.Maps/Debug/net10.0-android36.0/Microsoft.Maui.Controls.Maps.dll
  Controls.TestCases.HostApp -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Controls.TestCases.HostApp.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  Core -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.dll
  Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Maps.dll
  Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  Controls.Xaml -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Xaml.dll
  Controls.Maps -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Maps.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.Foldable -> /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.HostApp/Debug/net10.0-android/Microsoft.Maui.Controls.Foldable.dll

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

Time Elapsed 00:08:33.60
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.60-ci+azdo.13750574
  Graphics -> /home/vsts/work/1/s/artifacts/bin/Graphics/Debug/net10.0/Microsoft.Maui.Graphics.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  Essentials -> /home/vsts/work/1/s/artifacts/bin/Essentials/Debug/net10.0/Microsoft.Maui.Essentials.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  Core -> /home/vsts/work/1/s/artifacts/bin/Core/Debug/net10.0/Microsoft.Maui.dll
  Controls.BindingSourceGen -> /home/vsts/work/1/s/artifacts/bin/Controls.BindingSourceGen/Debug/netstandard2.0/Microsoft.Maui.Controls.BindingSourceGen.dll
  ##vso[build.updatebuildnumber]10.0.60-ci+azdo.13750574
  Controls.Core -> /home/vsts/work/1/s/artifacts/bin/Controls.Core/Debug/net10.0/Microsoft.Maui.Controls.dll
  UITest.Core -> /home/vsts/work/1/s/artifacts/bin/UITest.Core/Debug/net10.0/UITest.Core.dll
  UITest.NUnit -> /home/vsts/work/1/s/artifacts/bin/UITest.NUnit/Debug/net10.0/UITest.NUnit.dll
  VisualTestUtils -> /home/vsts/work/1/s/artifacts/bin/VisualTestUtils/Debug/netstandard2.0/VisualTestUtils.dll
  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.17]   Discovering: Controls.TestCases.Android.Tests
[xUnit.net 00:00:00.58]   Discovered:  Controls.TestCases.Android.Tests
NUnit Adapter 4.5.0.0: Test execution started
Running selected tests in /home/vsts/work/1/s/artifacts/bin/Controls.TestCases.Android.Tests/Debug/net10.0/Controls.TestCases.Android.Tests.dll
   NUnit3TestExecutor discovered 1 of 1 NUnit test cases using Current Discovery mode, Non-Explicit run
>>>>> 04/05/2026 22:39:53 FixtureSetup for Issue19690(Android)
>>>>> 04/05/2026 22:39:56 ButtonVisualStatesShouldToggleBetweenNormalAndCustom Start
>>>>> 04/05/2026 22:40:03 ButtonVisualStatesShouldToggleBetweenNormalAndCustom Stop
  Passed ButtonVisualStatesShouldToggleBetweenNormalAndCustom [7 s]
NUnit Adapter 4.5.0.0: Test execution complete

Test Run Successful.
Total tests: 1
     Passed: 1
 Total time: 26.9903 Seconds

📁 Fix files reverted (4 files)
  • eng/pipelines/ci-copilot.yml
  • src/Core/src/Handlers/Button/ButtonHandler.Android.cs
  • src/Core/src/Handlers/Button/ButtonHandler.iOS.cs
  • src/Core/src/Platform/iOS/ButtonExtensions.cs

@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented Mar 28, 2026

🤖 AI Summary

📊 Expand Full Review8042200 · fix-19690-Made code changes to modify the android fix and updated the testcase.
🔍 Pre-Flight — Context & Validation

Issue: #19690 - Button VisualStates do not work
PR: #33346 - [Android, iOS] Button: Fix VisualState properties not restored when leaving custom state
Platforms Affected: Android, iOS (macOS also affected per issue; PR focuses on Android + iOS; has snapshot images for Mac too)
Files Changed: 3 implementation files, 2 test files, 12 snapshot images (3×Android, 3×iOS, 3×iOS-26, 3×Mac + Windows snapshots added)

Key Findings

  • Root cause: When a Button transitions from a custom VisualState back to the Normal state, MAUI sets property values to null to signal "restore defaults." Both the Android and iOS handlers previously treated null as a no-op, leaving custom colors/backgrounds stuck on the button.
  • Android fix: ButtonHandler.Android.cs captures _defaultTextColors from platformView.TextColors in ConnectHandler (before base.ConnectHandler / MAUI mapping runs). MapTextColor restores this cached ColorStateList when button.TextColor is null. The fix bypasses ButtonExtensions.UpdateTextColor entirely for the null case.
  • iOS fix: ButtonExtensions.UpdateTextColor now, when TextColor is null AND the button is window-attached, calls SetTitleColor(null, …) for Normal/Highlighted/Disabled states and restores TintColor = window.TintColor. A new internal UpdateBackground(UIButton, Paint?) overload handles null background by calling RemoveBackgroundLayer() + resetting BackgroundColor = UIColor.Clear. ButtonHandler.iOS.cs MapBackground now passes button.Background (a Paint) directly rather than the full IButton.
  • Gate: ✅ PASSED — Tests FAIL without the fix and PASS with it on Android.
  • Prior reviews: An earlier review (Feb 25) flagged hardcoded UIColor.SystemBlue for iOS. The current PR has since fixed this using window.TintColor to respect the app's tint.
  • PublicAPI.Unshipped.txt: No new public API is declared. The iOS UpdateBackground overload is internal. PublicAPI issue noted in a prior review has been resolved.
  • Snapshot images: Android, iOS, iOS-26, Mac, and Windows snapshots are all included.
  • Unrelated file: src/Core/src/Handlers/HybridWebView/HybridWebView.js appears in the squashed commit but has no diff — likely a no-op inclusion from a merge.

Fix Candidates

# Source Approach Test Result Files Changed Notes
PR PR #33346 Cache _defaultTextColors in ButtonHandler; restore on null TextColor (Android). iOS: window-guard null-clear + window.TintColor restore; new internal UpdateBackground for null Background. ✅ PASSED (Gate) 3 impl files Current PR approach

🔧 Fix — Analysis & Comparison

Fix Candidates

# Source Approach Test Result Files Changed Notes
1 try-fix (claude-opus-4.6) Platform-layer fix: new UpdateTextColor(MaterialButton, ITextStyle) in ButtonExtensions.cs that creates a temp MaterialButton on-demand to get fresh default ColorStateList ✅ PASS 2 files Stateless; follows existing UpdateButtonBackground pattern; small allocation overhead
2 try-fix (claude-sonnet-4.6) Cache default TextColors in MauiMaterialButton constructor; expose RestoreDefaultTextColors() internal method; handler calls it when TextColor is null ✅ PASS 2 files View owns its own defaults; clean OOP; no repeated allocation
3 try-fix (gpt-5.3-codex) Re-apply TextAppearanceButton from theme via ResolveAttribute in MapTextColor when TextColor is null ❌ FAIL 2 files Visual diff on initial state (1.80%); theme appearance restore approach incorrect
4 try-fix (gpt-5.4) ButtonExtensions.cs-only fix: MaterialButton-specific UpdateTextColor overload that restores ColorStateList from Resource.Style.MauiMaterialButton style ✅ PASS 1 file No handler/MauiMaterialButton changes needed; depends on internal style resource name
PR PR #33346 Cache _defaultTextColors field on ButtonHandler in ConnectHandler (before base call); restore directly via SetTextColor on null TextColor ✅ PASSED (Gate) 3 impl files Handler-level caching with proper lifecycle management

Cross-Pollination

Model Round New Ideas? Details
claude-opus-4.6 2 No "NO NEW IDEAS — solution space exhausted. All approaches reduce to cache-and-restore vs reconstruct-from-source."

Exhausted: Yes
Selected Fix: PR #33346 — Passed the Gate, has proper lifecycle management (null in DisconnectHandler), no allocation overhead vs Attempt 1/4, and is simpler than Attempt 2 (no MauiMaterialButton changes needed). Attempt 4 is the most minimal (1 file), but depends on an internal style resource name that could be fragile.


📋 Report — Final Recommendation

✅ Final Recommendation: APPROVE

Phase Status

Phase Status Notes
Pre-Flight ✅ COMPLETE Issue #19690, Android + iOS platforms
Gate ✅ PASSED Android — tests FAIL without fix, PASS with fix
Try-Fix ✅ COMPLETE 4 attempts, 3 passing; solution space exhausted
Report ✅ COMPLETE

Summary

PR #33346 fixes a real, verified bug where Button VisualState properties (TextColor, Background) fail to restore when transitioning back from a custom state to Normal on Android and iOS. The fix is minimal, correct, passes the Gate, and multiple independent try-fix explorations confirmed the approach is sound. The PR is ready to merge with minor notes.

Root Cause

When MAUI unapplies a VisualState setter, it signals "restore defaults" by setting the property to null. Both the Android and iOS handlers treated null as a no-op (if (button.TextColor is null) return;), so custom colors set by the VisualState persisted indefinitely. The fix correctly handles the null case as "restore platform defaults."

Fix Quality

Android fix (ButtonHandler.Android.cs): Captures _defaultTextColors (the Material theme ColorStateList) in ConnectHandler before base.ConnectHandler runs (i.e., before MAUI's property mapping). When MapTextColor receives null, it restores the cached list directly. Good lifecycle management: _defaultTextColors is nulled in DisconnectHandler. This approach is identical in strategy to Attempt 2 (the best alternative found), just placing the cache at the handler level rather than in MauiMaterialButton — both are correct design choices.

iOS fix (ButtonExtensions.cs, ButtonHandler.iOS.cs): UpdateTextColor null-path clears title color overrides and restores window.TintColor. New internal UpdateBackground(UIButton, Paint?) resets to UIColor.Clear on null background. Both changes guarded by // TODO: Make this public in .NET 11 comments, appropriate for a main branch bugfix.

Tests: Screenshot-based UI test with 3 states (Initial/Custom/BackToNormal). Uses VerifyScreenshotOrSetException pattern correctly — collects all screenshot failures before throwing. Snapshots provided for Android, iOS, iOS-26, Mac, and Windows.

Try-Fix Comparison

3 of 4 alternative approaches passed. The PR's fix is comparable in quality to the best alternatives:

  • Attempt 2 (cache in MauiMaterialButton) is equally clean architecturally
  • Attempt 4 (ButtonExtensions.cs-only, 1 file) is more minimal but relies on an internal style resource name
  • The PR's approach has the advantage of clear lifecycle management and follows handler patterns already established in the codebase

Selected Fix: PR #33346

Minor Notes (Non-blocking)

  1. PR description inaccuracy: The description says "a MaterialButton-specific UpdateTextColor overload was introduced in MauiMaterialButton" — but the actual fix is in ButtonHandler.Android.cs directly, not in MauiMaterialButton. Minor documentation issue, not a code problem.

  2. iOS window-attachment guard: The null-path in UpdateTextColor only fires when platformButton.Window is UIWindow window. Edge case: if a VisualState is unapplied before the button attaches to a window, the color won't be restored. Low risk in practice since VisualState changes occur on visible, attached controls.

  3. iOS internal MapBackground: The #else (iOS-only) MapBackground overload is marked internal with // TODO: Make this public in .NET 11. This is appropriate for main branch since we're in bug-fix territory, but anyone who overrides the iOS button's background mapper would be affected. The comment is clear about the intent.


@MauiBot MauiBot added s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-fix-win AI found a better alternative fix than the PR and removed s/agent-review-incomplete AI agent could not complete all phases (blocker, timeout, error) s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates labels Mar 29, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 31, 2026

🚀 Dogfood this PR with:

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

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

Or

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

@BagavathiPerumal
Copy link
Copy Markdown
Contributor Author

🤖 AI Summary

📊 Expand Full Reviewbaa52de · fix-19690-Changes committed.
🔍 Pre-Flight — Context & Validation
Issue: #19690 - Button VisualStates do not work PR: #33346 - [Android, iOS] Button: Fix VisualState properties not restored when leaving custom state Platforms Affected: Android, iOS (macOS also affected per issue, but PR focuses on Android+iOS) Files Changed: 4 implementation files, 2 test files, 6 snapshot images (3×Android, 3×iOS), 1 PublicAPI file

Key Findings

  • Root cause: When a Button transitions from a custom VisualState back to Normal, MAUI passes null as the property values (TextColor=null, Background=null) to signal "restore defaults." The platform handlers previously did nothing on null, leaving custom visuals stuck.
  • Android fix: New internal UpdateTextColor(MaterialButton, ITextStyle) overload in ButtonExtensions.cs; DefaultTextColors cached at MauiMaterialButton construction time and restored when TextColor is null.
  • iOS fix: UpdateTextColor now clears SetTitleColor(null, ...) overrides and restores window.TintColor when null (window-attached-only guard). New internal UpdateBackground(UIButton, Paint?) overload resets to UIColor.Clear on null background. ButtonHandler.iOS.cs MapBackground now passes button.Background (Paint) instead of the full IButton.
  • Gate FAILED both ways: Tests PASS without the fix (tests don't catch the bug) AND tests FAIL with the fix applied (regression or build error from the fix).
  • 🔴 Critical bug: src/Core/src/PublicAPI/net-android/PublicAPI.Unshipped.txt declares UpdateTextColor as a public API, but the actual method is marked internal. This causes RS0017 build error with TreatWarningsAsErrors=true. This likely explains why tests fail with the fix applied (build fails).
  • Prior agent review: A prior AI review (Feb 25, 2026) flagged the iOS UIColor.SystemBlue hardcoding; the current PR has addressed this with window.TintColor. The prior review also found alternative approaches via try-fix that all passed.
  • Snapshot files: Only 3 Android + 3 iOS snapshots added (no Mac or Windows).
  • eng/pipelines/ci-copilot.yml listed as fix file in gate — unexpected file, may have been accidentally modified.

Fix Candidates

Source Approach Test Result Files Changed Notes

PR PR #33346 Cache DefaultTextColors in MauiMaterialButton constructors + iOS restore via window.TintColor ❌ FAIL (Gate: tests fail WITH fix) 4 impl files + PublicAPI internal method wrongly listed in PublicAPI.Unshipped.txt
🔧 Fix — Analysis & Comparison

Fix Candidates

Source Approach Test Result Files Changed Notes

PR PR #33346 Cache DefaultTextColors in MauiMaterialButton constructors; new internal UpdateTextColor overload in ButtonExtensions.cs ❌ FAIL (Gate: RS0017 build error — internal method in PublicAPI.Unshipped.txt) 4 impl files + PublicAPI Critical bug: internal method listed as public API
1 try-fix (claude-opus-4.6) Handler-level snapshot: _defaultTextColors in ButtonHandler.Android.cs, captured in ConnectHandler, restored in MapTextColor on null ✅ PASS 1 file (ButtonHandler.Android.cs) Clean separation; no extension method changes
2 try-fix (claude-sonnet-4.6) ConditionalWeakTable<MaterialButton, ColorStateList> lazy cache in ButtonExtensions.cs — captures on first non-null SetTextColor call ✅ PASS 1 file (ButtonExtensions.cs) Zero handler changes; no MauiMaterialButton changes
3 try-fix (gpt-5.3-codex) Modified TextViewExtensions.UpdateTextColor to create temp MaterialButton on each null-reset call for on-demand theme defaults ✅ PASS 2 files (TextViewExtensions.cs, ButtonExtensions.cs) No caching; allocates per reset call
4 try-fix (gpt-5.4) Static Lazy<ColorStateList> in ButtonExtensions.cs — creates one temp MaterialButton once (app context), shared across all instances ✅ PASS 1 file (ButtonExtensions.cs) Minimal; no per-instance state

Cross-Pollination

Model Round New Ideas? Details
claude-opus-4.6 2 No "NO NEW IDEAS — 4 attempts cover the meaningful design space"
Exhausted: Yes — all 4 models explored different strategies (handler-level, WeakTable, on-demand theme lookup, static lazy singleton); cross-poll confirmed no new ideas.

Selected Fix: Candidate #1 (handler-level snapshot in ButtonHandler.Android.cs) — Reason:

  • Single-file change, minimal surface area
  • Most consistent with MAUI's handler ownership pattern (handlers own platform state)
  • Zero PublicAPI changes
  • No dependency on MauiMaterialButton implementation details
  • No allocation overhead (captured once at ConnectHandler, no temp buttons created)
  • Attempt 1 by claude-opus-4.6

PR's fix vs. Best candidate:

PR Fix Candidate #1
Files changed 4 impl + 1 PublicAPI 1 (ButtonHandler.Android.cs)
PublicAPI concern ❌ RS0017 build error (internal as public) ✅ No API changes
MauiMaterialButton changes ❌ 4 constructors modified ✅ None
iOS fix ✅ Included (window.TintColor restore) ❌ Android only
Correctness ✅ Correct logic (but build fails) ✅ Correct
Complexity Higher Lower
📋 Report — Final Recommendation

⚠️ Final Recommendation: REQUEST CHANGES

Phase Status

Phase Status Notes
Pre-Flight ✅ COMPLETE Community PR (Syncfusion partner), issue #19690, Android + iOS
Gate ❌ FAILED Android — tests PASS without fix (screenshot test unreliable) AND FAIL with fix (RS0017 build error)
Try-Fix ✅ COMPLETE 4 attempts, 4 passing; cross-poll exhausted
Report ✅ COMPLETE

Summary

PR #33346 addresses a real, confirmed bug: Button VisualState properties (TextColor, BackgroundColor) are not restored when transitioning from a custom state back to Normal on Android and iOS. The fix logic is conceptually sound, but the PR has a critical build-breaking issue on Android and a test reliability problem.

Root Cause

When MAUI transitions a Button out of a custom VisualState, it passes null for properties to signal "restore defaults." The Android and iOS platform handlers treated null as a no-op (early return), leaving the custom visual state permanently applied.

Fix Quality

Blocking Issues:

  1. 🔴 RS0017 build error (Android): src/Core/src/PublicAPI/net-android/PublicAPI.Unshipped.txt declares static Microsoft.Maui.Platform.ButtonExtensions.UpdateTextColor(...) as a public API, but the actual method is internal. This contradicts the // TODO: Make this public in .NET 11 comment and causes a build failure when the fix is applied — confirmed by Gate: tests FAIL WITH fix (173s, consistent with early build abort). Fix: Remove the entry from PublicAPI.Unshipped.txt. It should only be added when the method is made public.
  2. 🔴 Tests don't catch the bug (Android): The screenshot-based test (VerifyScreenshotOrSetException) passes both with and without the fix. The baseline PNGs represent the correct "fixed" behavior, but the emulator screenshot comparison can't detect the visual difference at the current tolerance. Gate confirms: tests PASS without fix. This makes CI unable to regression-test the fix.

Suggested Improvements:

  1. 🟡 Better Android fix approach: Try-Fix explored 4 alternatives; Candidate [Draft] Readme WIP #1 (handler-level snapshot in ButtonHandler.Android.cs) is simpler and cleaner — single-file change, no MauiMaterialButton constructor modifications, no extension method API surface, no PublicAPI changes.
  2. 🟡 iOS fix correctness: The current PR correctly uses window.TintColor (improved from the prior review's concern about UIColor.SystemBlue). However, the UpdateTextColor guard if (platformButton.Window is UIWindow window) means the reset is silently skipped during initial render — acceptable, but should be documented.
  3. 🟡 Android JNI constructor: protected MauiMaterialButton(nint javaReference, JniHandleOwnership transfer) caches DefaultTextColors = TextColors but at JNI reconstruction time, TextColors may already reflect custom values. Consider skipping this constructor or guarding with DefaultTextColors ??= TextColors.
  4. 🟡 Test reliability: The screenshot test needs improvement to actually catch the bug. Consider adding a non-screenshot assertion (e.g., check a label text that changes with the state) or use retryTimeout to stabilize screenshots.

Alternative Fix (from Try-Fix)

Candidate #1 (single-file, handler-level) is recommended as a simpler Android fix:

  • In ButtonHandler.Android.cs: add ColorStateList? _defaultTextColors field; capture in ConnectHandler; clear in DisconnectHandler; restore in MapTextColor when button.TextColor is null.
  • No changes to MauiMaterialButton, ButtonExtensions.cs, or PublicAPI.Unshipped.txt.
  • iOS fix from the PR is separate and can be kept as-is (or merged independently).

I’ve updated the changes based on the AI summary. Please find the details below:

  • Updated the code changes for the Android testcase, which was previously passing even without the fix.
  • Removed the unwanted entry from PublicAPI.Unshipped.txt.
  • Updated the code changes based on the Candidate 1 fix, and they work correctly with only minimal adjustments needed.

@sheiksyedm
Copy link
Copy Markdown
Contributor

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

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 2 pipeline(s).

@MauiBot MauiBot added s/agent-approved AI agent recommends approval - PR fix is correct and optimal s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates and removed s/agent-changes-requested AI agent recommends changes - found a better alternative or issues s/agent-fix-win AI found a better alternative fix than the PR labels Apr 5, 2026
@sheiksyedm
Copy link
Copy Markdown
Contributor

/azp run maui-pr-uitests

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-controls-button Button, ImageButton community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration platform/android platform/ios s/agent-approved AI agent recommends approval - PR fix is correct and optimal s/agent-fix-pr-picked AI could not beat the PR fix - PR is the best among all candidates s/agent-reviewed PR was reviewed by AI agent workflow (full 4-phase review)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Button VisualStates do not work

7 participants