Skip to content

Comments

[Android] Implement material3 support for CheckBox#33339

Merged
PureWeen merged 6 commits intodotnet:inflight/currentfrom
HarishwaranVijayakumar:material3-checkbox
Jan 6, 2026
Merged

[Android] Implement material3 support for CheckBox#33339
PureWeen merged 6 commits intodotnet:inflight/currentfrom
HarishwaranVijayakumar:material3-checkbox

Conversation

@HarishwaranVijayakumar
Copy link
Contributor

Description of Change

This pull request updates the way checkbox tint colors are handled on Android, improving compatibility with both Material 2 and Material 3 themes. The main focus is on ensuring that the correct default or accent color is used for checkbox foregrounds depending on the Material version in use.

Theme-aware checkbox tinting:

  • Introduced a static field _defaultButtonTintList in CheckBoxExtensions to cache the default button tint for Material 3 themes, ensuring consistent appearance and avoiding unnecessary recomputation.
  • Updated the GetColorStateList method to:
    • Use the default theme's button tint when Material 3 is enabled, falling back to the cached _defaultButtonTintList if available.
    • Continue using the accent color for Material 2 themes, preserving existing behavior.

Issues Fixed

Fixes #33338

Screenshots

Material Design Spec - CheckBox

Material 2 Material 3

@dotnet-policy-service dotnet-policy-service bot added community ✨ Community Contribution partner/syncfusion Issues / PR's with Syncfusion collaboration labels Dec 30, 2025
@sheiksyedm sheiksyedm marked this pull request as ready for review December 30, 2025 14:39
Copilot AI review requested due to automatic review settings December 30, 2025 14:39
Copy link
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 implements Material 3 support for CheckBox on Android by introducing theme-aware checkbox tinting. The implementation caches the default Material 3 button tint and uses it when no custom foreground is specified, while preserving the accent color behavior for Material 2.

Key Changes:

  • Added static caching of default Material 3 button tint list to avoid recomputation
  • Updated color state list logic to differentiate between Material 2 and Material 3 themes
  • Reorganized return statements to handle Material 3 and Material 2 code paths separately


if (RuntimeFeature.IsMaterial3Enabled)
{
// Save the default button tint list
Copy link

Copilot AI Dec 30, 2025

Choose a reason for hiding this comment

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

The comment "Save the default button tint list" is misleading because this code doesn't just save the value - it uses null-coalescing to save it only if it hasn't been saved before. The comment would be more accurate as "Cache the default button tint list if not already cached" or "Initialize the default button tint list cache".

Suggested change
// Save the default button tint list
// Cache the default button tint list if not already cached

Copilot uses AI. Check for mistakes.
Comment on lines 52 to 58
_defaultButtonTintList ??= platformCheckBox.ButtonTintList;

// Material 3: Use the default theme's buttonTint
if (_defaultButtonTintList is not null)
{
return _defaultButtonTintList;
}
Copy link

Copilot AI Dec 30, 2025

Choose a reason for hiding this comment

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

The logic on line 52 caches platformCheckBox.ButtonTintList from the first CheckBox instance created. However, if the first CheckBox's ButtonTintList is null (which can happen in certain scenarios), the cache will be set to null and then the check on line 55 will fail, causing fallthrough to the Material 2 logic even when Material 3 is enabled.

This creates an inconsistent state where Material 3 is enabled but Material 2 accent colors are used. Consider checking if ButtonTintList is null before caching it, or handle the null case differently.

Copilot uses AI. Check for mistakes.
{
public static class CheckBoxExtensions
{
static ColorStateList? _defaultButtonTintList;
Copy link

Copilot AI Dec 30, 2025

Choose a reason for hiding this comment

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

The static field _defaultButtonTintList creates a global cache that is shared across all CheckBox instances in the application. This approach has several problems:

  1. Per-Activity theming: Different Activities in the same application can use different themes. By caching the first CheckBox's ButtonTintList globally, all subsequent CheckBoxes will use this cached value regardless of their Activity's theme.

  2. Theme switching: If the app's theme changes at runtime (e.g., dark mode toggle, Material 2/3 toggle), this cached value won't be updated, causing CheckBoxes to retain the old theme's colors.

  3. Thread safety: The null-coalescing assignment operator ??= on line 52 is not thread-safe, which could lead to race conditions if multiple CheckBoxes are created simultaneously on different threads.

Consider either:

  • Removing the cache and always reading platformCheckBox.ButtonTintList when Material 3 is enabled and no foreground is set
  • Implementing a per-Context or per-Activity cache if performance is critical
  • Using a thread-safe caching mechanism if needed

Copilot uses AI. Check for mistakes.
}
else
{

Copy link

Copilot AI Dec 30, 2025

Choose a reason for hiding this comment

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

There's an unnecessary empty line here. This should be removed to maintain code consistency.

Suggested change

Copilot uses AI. Check for mistakes.
@sheiksyedm
Copy link
Contributor

/azp run maui-pr-uitests

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

HarishwaranVijayakumar and others added 2 commits January 2, 2026 10:15
Address review feedback on PR dotnet#33339:

1. Replace static ColorStateList cache with per-instance ConditionalWeakTable
   - Fixes per-Activity theming (different Activities can have different themes)
   - Fixes theme switching at runtime (dark mode, Material2/3 toggle)
   - Provides thread safety (no shared mutable state)

2. Improve code structure
   - Remove unnecessary else block for cleaner flow
   - Add descriptive comments explaining the caching strategy

The original static cache would capture the first checkbox's theme tint and
reuse it for all subsequent checkboxes, causing incorrect colors when themes
differ across Activities or change at runtime.
@StephaneDelcroix
Copy link
Contributor

I've pushed a commit that addresses the review feedback about static caching:

Changes Made

  1. Replaced static ColorStateList? cache with per-instance ConditionalWeakTable<AppCompatCheckBox, ColorStateList>

    • Fixes per-Activity theming (different Activities can have different themes)
    • Fixes theme switching at runtime (dark mode, Material2/3 toggle)
    • Provides thread safety (no shared mutable state)
    • Memory efficient (weak references, no leaks)
  2. Improved code structure

    • Removed unnecessary else block for cleaner control flow
    • Added descriptive comments explaining the caching strategy

Why This Matters

The original static cache would capture the first checkbox's theme tint and reuse it for all subsequent checkboxes, causing incorrect colors when:

  • Different Activities use different themes
  • Theme changes at runtime (e.g., dark mode toggle)
  • Multiple threads create checkboxes simultaneously

Validation

  • ✅ Build succeeded for net10.0-android36.0
  • ✅ All 13 CheckBox unit tests pass
  • ✅ All 5,428 Controls.Core.UnitTests pass (0 failures)

Copy link
Contributor

@StephaneDelcroix StephaneDelcroix left a comment

Choose a reason for hiding this comment

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

LGTM!

The Material3 checkbox support looks good. The per-instance caching approach using ConditionalWeakTable properly handles:

  • Per-Activity theming
  • Runtime theme switching
  • Thread safety

The fix correctly preserves the original theme's ButtonTintList for each checkbox instance before modification, ensuring Material3 checkboxes use the proper theme colors.

Tested:

  • ✅ All CheckBox unit tests pass
  • ✅ Full Controls.Core.UnitTests suite passes (5,428 tests)

@PureWeen PureWeen changed the base branch from main to inflight/current January 6, 2026 21:30
@PureWeen PureWeen merged commit e92d839 into dotnet:inflight/current Jan 6, 2026
2 of 12 checks passed
PureWeen pushed a commit that referenced this pull request Jan 9, 2026
<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

### Description of Change

This pull request updates the way checkbox tint colors are handled on
Android, improving compatibility with both Material 2 and Material 3
themes. The main focus is on ensuring that the correct default or accent
color is used for checkbox foregrounds depending on the Material version
in use.

**Theme-aware checkbox tinting:**

* Introduced a static field `_defaultButtonTintList` in
`CheckBoxExtensions` to cache the default button tint for Material 3
themes, ensuring consistent appearance and avoiding unnecessary
recomputation.
* Updated the `GetColorStateList` method to:
- Use the default theme's button tint when Material 3 is enabled,
falling back to the cached `_defaultButtonTintList` if available.
- Continue using the accent color for Material 2 themes, preserving
existing behavior.

### 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 #33338

### Screenshots

Material Design Spec -
[CheckBox](https://m3.material.io/components/checkbox/specs)

| Material 2 | Material 3 |
|----------|----------|
| <img
src="https://github.com/user-attachments/assets/8bce9689-a698-49af-862f-24e56ec4f3cb">
| <img
src="https://github.com/user-attachments/assets/978b27eb-0e67-451c-8a3b-927434d6389a">
|

---------

Co-authored-by: Stephane Delcroix <stephane@delcroix.org>
PureWeen pushed a commit that referenced this pull request Jan 13, 2026
<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

### Description of Change

This pull request updates the way checkbox tint colors are handled on
Android, improving compatibility with both Material 2 and Material 3
themes. The main focus is on ensuring that the correct default or accent
color is used for checkbox foregrounds depending on the Material version
in use.

**Theme-aware checkbox tinting:**

* Introduced a static field `_defaultButtonTintList` in
`CheckBoxExtensions` to cache the default button tint for Material 3
themes, ensuring consistent appearance and avoiding unnecessary
recomputation.
* Updated the `GetColorStateList` method to:
- Use the default theme's button tint when Material 3 is enabled,
falling back to the cached `_defaultButtonTintList` if available.
- Continue using the accent color for Material 2 themes, preserving
existing behavior.

### 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 #33338

### Screenshots

Material Design Spec -
[CheckBox](https://m3.material.io/components/checkbox/specs)

| Material 2 | Material 3 |
|----------|----------|
| <img
src="https://github.com/user-attachments/assets/8bce9689-a698-49af-862f-24e56ec4f3cb">
| <img
src="https://github.com/user-attachments/assets/978b27eb-0e67-451c-8a3b-927434d6389a">
|

---------

Co-authored-by: Stephane Delcroix <stephane@delcroix.org>
github-actions bot pushed a commit that referenced this pull request Jan 16, 2026
<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

### Description of Change

This pull request updates the way checkbox tint colors are handled on
Android, improving compatibility with both Material 2 and Material 3
themes. The main focus is on ensuring that the correct default or accent
color is used for checkbox foregrounds depending on the Material version
in use.

**Theme-aware checkbox tinting:**

* Introduced a static field `_defaultButtonTintList` in
`CheckBoxExtensions` to cache the default button tint for Material 3
themes, ensuring consistent appearance and avoiding unnecessary
recomputation.
* Updated the `GetColorStateList` method to:
- Use the default theme's button tint when Material 3 is enabled,
falling back to the cached `_defaultButtonTintList` if available.
- Continue using the accent color for Material 2 themes, preserving
existing behavior.

### 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 #33338

### Screenshots

Material Design Spec -
[CheckBox](https://m3.material.io/components/checkbox/specs)

| Material 2 | Material 3 |
|----------|----------|
| <img
src="https://github.com/user-attachments/assets/8bce9689-a698-49af-862f-24e56ec4f3cb">
| <img
src="https://github.com/user-attachments/assets/978b27eb-0e67-451c-8a3b-927434d6389a">
|

---------

Co-authored-by: Stephane Delcroix <stephane@delcroix.org>
github-actions bot pushed a commit that referenced this pull request Jan 20, 2026
<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

### Description of Change

This pull request updates the way checkbox tint colors are handled on
Android, improving compatibility with both Material 2 and Material 3
themes. The main focus is on ensuring that the correct default or accent
color is used for checkbox foregrounds depending on the Material version
in use.

**Theme-aware checkbox tinting:**

* Introduced a static field `_defaultButtonTintList` in
`CheckBoxExtensions` to cache the default button tint for Material 3
themes, ensuring consistent appearance and avoiding unnecessary
recomputation.
* Updated the `GetColorStateList` method to:
- Use the default theme's button tint when Material 3 is enabled,
falling back to the cached `_defaultButtonTintList` if available.
- Continue using the accent color for Material 2 themes, preserving
existing behavior.

### 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 #33338

### Screenshots

Material Design Spec -
[CheckBox](https://m3.material.io/components/checkbox/specs)

| Material 2 | Material 3 |
|----------|----------|
| <img
src="https://github.com/user-attachments/assets/8bce9689-a698-49af-862f-24e56ec4f3cb">
| <img
src="https://github.com/user-attachments/assets/978b27eb-0e67-451c-8a3b-927434d6389a">
|

---------

Co-authored-by: Stephane Delcroix <stephane@delcroix.org>
github-actions bot pushed a commit that referenced this pull request Jan 21, 2026
<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

### Description of Change

This pull request updates the way checkbox tint colors are handled on
Android, improving compatibility with both Material 2 and Material 3
themes. The main focus is on ensuring that the correct default or accent
color is used for checkbox foregrounds depending on the Material version
in use.

**Theme-aware checkbox tinting:**

* Introduced a static field `_defaultButtonTintList` in
`CheckBoxExtensions` to cache the default button tint for Material 3
themes, ensuring consistent appearance and avoiding unnecessary
recomputation.
* Updated the `GetColorStateList` method to:
- Use the default theme's button tint when Material 3 is enabled,
falling back to the cached `_defaultButtonTintList` if available.
- Continue using the accent color for Material 2 themes, preserving
existing behavior.

### 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 #33338

### Screenshots

Material Design Spec -
[CheckBox](https://m3.material.io/components/checkbox/specs)

| Material 2 | Material 3 |
|----------|----------|
| <img
src="https://github.com/user-attachments/assets/8bce9689-a698-49af-862f-24e56ec4f3cb">
| <img
src="https://github.com/user-attachments/assets/978b27eb-0e67-451c-8a3b-927434d6389a">
|

---------

Co-authored-by: Stephane Delcroix <stephane@delcroix.org>
github-actions bot pushed a commit that referenced this pull request Jan 23, 2026
<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

### Description of Change

This pull request updates the way checkbox tint colors are handled on
Android, improving compatibility with both Material 2 and Material 3
themes. The main focus is on ensuring that the correct default or accent
color is used for checkbox foregrounds depending on the Material version
in use.

**Theme-aware checkbox tinting:**

* Introduced a static field `_defaultButtonTintList` in
`CheckBoxExtensions` to cache the default button tint for Material 3
themes, ensuring consistent appearance and avoiding unnecessary
recomputation.
* Updated the `GetColorStateList` method to:
- Use the default theme's button tint when Material 3 is enabled,
falling back to the cached `_defaultButtonTintList` if available.
- Continue using the accent color for Material 2 themes, preserving
existing behavior.

### 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 #33338

### Screenshots

Material Design Spec -
[CheckBox](https://m3.material.io/components/checkbox/specs)

| Material 2 | Material 3 |
|----------|----------|
| <img
src="https://github.com/user-attachments/assets/8bce9689-a698-49af-862f-24e56ec4f3cb">
| <img
src="https://github.com/user-attachments/assets/978b27eb-0e67-451c-8a3b-927434d6389a">
|

---------

Co-authored-by: Stephane Delcroix <stephane@delcroix.org>
PureWeen pushed a commit that referenced this pull request Jan 23, 2026
<!--
!!!!!!! MAIN IS THE ONLY ACTIVE BRANCH. MAKE SURE THIS PR IS TARGETING
MAIN. !!!!!!!
-->

### Description of Change

This pull request updates the way checkbox tint colors are handled on
Android, improving compatibility with both Material 2 and Material 3
themes. The main focus is on ensuring that the correct default or accent
color is used for checkbox foregrounds depending on the Material version
in use.

**Theme-aware checkbox tinting:**

* Introduced a static field `_defaultButtonTintList` in
`CheckBoxExtensions` to cache the default button tint for Material 3
themes, ensuring consistent appearance and avoiding unnecessary
recomputation.
* Updated the `GetColorStateList` method to:
- Use the default theme's button tint when Material 3 is enabled,
falling back to the cached `_defaultButtonTintList` if available.
- Continue using the accent color for Material 2 themes, preserving
existing behavior.

### 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 #33338

### Screenshots

Material Design Spec -
[CheckBox](https://m3.material.io/components/checkbox/specs)

| Material 2 | Material 3 |
|----------|----------|
| <img
src="https://github.com/user-attachments/assets/8bce9689-a698-49af-862f-24e56ec4f3cb">
| <img
src="https://github.com/user-attachments/assets/978b27eb-0e67-451c-8a3b-927434d6389a">
|

---------

Co-authored-by: Stephane Delcroix <stephane@delcroix.org>
PureWeen added a commit that referenced this pull request Jan 25, 2026
## What's Coming

.NET MAUI inflight/candidate introduces significant improvements across
all platforms with focus on quality, performance, and developer
experience. This release includes 16 commits with various improvements,
bug fixes, and enhancements.


## Checkbox
- [Android] Implement material3 support for CheckBox by
@HarishwaranVijayakumar in #33339
  <details>
  <summary>🔧 Fixes</summary>

- [Implement Material3 Support for
CheckBox](#33338)
  </details>

## CollectionView
- [Android] Fixed EmptyView doesn’t display when CollectionView is
placed inside a VerticalStackLayout by @NanthiniMahalingam in
#33134
  <details>
  <summary>🔧 Fixes</summary>

- [CollectionView does not show an EmptyView template with an empty
collection](#32932)
  </details>

## Essentials
- [Windows]Fix NullReferenceException in OpenReadAsync for FileResult
created with full path by @devanathan-vaithiyanathan in
#28238
  <details>
  <summary>🔧 Fixes</summary>

- [[Windows] FileResult(string fullPath) not initialized
properly](#26858)
  </details>

## Image
- Fix Glide IllegalArgumentException in MauiCustomTarget.clear() for
destroyed activities by @jfversluis via @Copilot in
#29780
  <details>
  <summary>🔧 Fixes</summary>

- [java.lang.IllegalArgumentException: You cannot start a load for a
destroyed activity - glide](#29699)
  </details>

## Label
- [Android] Fix for Label WordWrap width issue causing HorizontalOptions
misalignment by @praveenkumarkarunanithi in
#33281
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] Unexpected Line Breaks in Android, Label with WordWrap Mode
Due to Trailing Space.](#31782)
- [Label not sized correctly on
Android](#27614)
  </details>

- Fix to Improve Flyout Accessibility by Adjusting UITableViewController
Labels by @SuthiYuvaraj in #31619
  <details>
  <summary>🔧 Fixes</summary>

- [Navigation section present under hamburger are programmatically
define as table :A11y_.NET maui_User can get all the insights of
Dashboard_Devtools](#30894)
  </details>

## Mediapicker
- [Regression][iOS] Fix MediaPicker PickPhotosAsync getting file name in
contentType property by @devanathan-vaithiyanathan in
#33390
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS] MediaPicker PickPhotosAsync getting file name in contentType
property](#33348)
  </details>

## Navigation
- Fix handler not disconnected when removing non visible pages using
RemovePage() by @Vignesh-SF3580 in
#32289
  <details>
  <summary>🔧 Fixes</summary>

- [NavigationPage.Navigation.RemovePage() fails to disconnect handlers
when removing pages, unlike
ContentPage.Navigation.RemovePage()](#32239)
  </details>

## Picker
- [Android] Fix Picker IsOpen not reset when picker is dismissed by
@devanathan-vaithiyanathan in #33332
  <details>
  <summary>🔧 Fixes</summary>

- [[Android] Picker IsOpen not reset when picker is
dismissed](#33331)
  </details>

## Shell
- [iOS & Catalyst ] Fixed IsEnabled property should work on Tabs by
@SubhikshaSf4851 in #33369
  <details>
  <summary>🔧 Fixes</summary>

- [[Catalyst] TabBarBackgroundColor, TabBarUnselectedColor, and
IsEnabled Not Working as Expected in
Shell](#33158)
  </details>

- [iOS,Windows] Fix navigation bar colors not resetting when switching
ShellContent by @Vignesh-SF3580 in
#33228
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS, Windows] Shell Navigation bar colors are not updated correctly
when switching
ShellContent](#33227)
  </details>

- [iOS] Fixed Shell navigation on search handler suggestion selection by
@SubhikshaSf4851 in #33406
  <details>
  <summary>🔧 Fixes</summary>

- [[iOS] Clicking on search suggestions fails to navigate to detail page
correctly](#33356)
  </details>

## Templates
- Fix VoiceOver doesnot announces the State of the ComboBox by
@SuthiYuvaraj in #32286

## Xaml
- [XSG][BindingSourceGen] Add support for CommunityToolkit.Mvvm
ObservablePropertyAttribute by @simonrozsival via @Copilot in
#33028
  <details>
  <summary>🔧 Fixes</summary>

- [[XSG] Add heuristic to support bindable properties generated by other
source generators](#32597)
  </details>


<details>
<summary>📦 Other (2)</summary>

- [XSG] Improve diagnostic reporting during binding compilation by
@simonrozsival via @Copilot in #32905
- [Testing] Fixed Test case failure in PR 33574 - [01/19/2026] Candidate
- 1 by @TamilarasanSF4853 in #33602

</details>
**Full Changelog**:
main...inflight/candidate
@github-actions github-actions bot locked and limited conversation to collaborators Feb 6, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-controls-checkbox CheckBox community ✨ Community Contribution material3 partner/syncfusion Issues / PR's with Syncfusion collaboration platform/android

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement Material3 Support for CheckBox

5 participants