material-components / material-components/material-components-android
[MaterialSwitch] thumb icon drawable is not properly tinted in light themes with certain characteristics
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 17.4k
- Forks
- 3.2k
- PR merge metrics
- No merged PRs in 30d
Description
Let's a consider a MaterialSwitch with a check mark thumb icon drawable specified with app:thumIcon="@drawable/material_switch_check_selector":
material_switch_check_selector.xml
<selector
xmlns:android="http://schemas.android.com/apk/res/android"
android:constantSize="true">
<item
android:state_checked="true"
android:drawable="@drawable/material_switch_check" />
</selector>
material_switch_check.xml
<vector android:height="16dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="16dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"/>
</vector>
This usually works fine and the Switch will show the check drawable when it is checked.
However, if a light theme has a dark color for colorPrimaryContainer and a light color for colorOnPrimaryContainer,
the check drawable tinting does not work properly, ending up in the check mark drawable being invisible.
This situation does not seem to happen with dynamic Material You themes but can happen if you generate a theme with the color library.
For example a theme generated with SchemeContent or SchemeExpressive with seed color #5c76aa (a darker blue) produces a dark colorPrimaryContainer and a light (white actually) colorOnPrimaryContainer, resulting in the Switch check mark not being visible when the switch is checked. SchemeMonochrome results in a check mark barely visible (white on light gray background). All other schemes are unaffected as they produce a light colorPrimaryContainer and dark colorOnPrimaryContainer.
Here's the code that generate both colors. I wonder if for SchemeContent or SchemeExpressive it should not generate (for a light theme) a light colorPrimaryContainer and dark colorOnPrimaryContainer like for other schemes ?:
@NonNull
public DynamicColor primaryContainer() {
return new DynamicColor(
/* name= */ "primary_container",
/* palette= */ (s) -> s.primaryPalette,
/* tone= */ (s) -> {
if (isFidelity(s)) {
return performAlbers(s.sourceColorHct, s);
}
if (isMonochrome(s)) {
return s.isDark ? 85.0 : 25.0;
}
return s.isDark ? 30.0 : 90.0;
},
/* isBackground= */ true,
/* background= */ this::highestSurface,
/* secondBackground= */ null,
/* contrastCurve= */ new ContrastCurve(1.0, 1.0, 3.0, 7.0),
/* toneDeltaPair= */ (s) ->
new ToneDeltaPair(primaryContainer(), primary(), 15.0, TonePolarity.NEARER, false));
}
@NonNull
public DynamicColor onPrimaryContainer() {
return new DynamicColor(
/* name= */ "on_primary_container",
/* palette= */ (s) -> s.primaryPalette,
/* tone= */ (s) -> {
if (isFidelity(s)) {
return DynamicColor.foregroundTone(primaryContainer().tone.apply(s), 4.5);
}
if (isMonochrome(s)) {
return s.isDark ? 0.0 : 100.0;
}
return s.isDark ? 90.0 : 10.0;
},
/* isBackground= */ false,
/* background= */ (s) -> primaryContainer(),
/* secondBackground= */ null,
/* contrastCurve= */ new ContrastCurve(4.5, 7.0, 11.0, 21.0),
/* toneDeltaPair= */ null);
}
The easiest way to reproduce this issue is to have a MaterialSwitch with app:thumIcon="@drawable/material_switch_check_selector"and a light theme with:
<item name="colorPrimaryContainer">#5a74a8</item>
<item name="colorOnPrimaryContainer">#ffffff</item>
Which are the colors generated by SchemeContent for seed color #5c76aa.
More broadly, does M3 requires that in a light theme , colorPrimaryContainer must always be a light color and colorOnPrimaryContainer a dark one ? If that's the case, the colors returned by SchemeContent and SchemeFidelity are not always compliant.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the MaterialSwitch case with material_switch_check_selector, material_switch_check, and the specified colorPrimaryContainer and colorOnPrimaryContainer values. Then inspect the thumb icon tinting behavior alongside the SchemeContent, SchemeExpressive, SchemeMonochrome, and SchemeFidelity color generation paths. Done means the reported checked-state visibility issue is resolved or the expected M3 color-role behavior is established.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- android, java
- Domain
- design, mobile
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100