Skip to content

Commit

Permalink
[Checkbox] Fixed issue where AppCompatCheckBox would not display its …
Browse files Browse the repository at this point in the history
…drawable when a Material theme was being used.

Instead of nulling android:button and buttonCompat in the Material style, we now check if the legacy drawable is being used, and override that if so.

PiperOrigin-RevId: 463643386
  • Loading branch information
leticiarossi authored and drchen committed Jul 28, 2022
1 parent bca0f2e commit 9ca8a80
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 12 deletions.
Expand Up @@ -20,8 +20,10 @@

import static com.google.android.material.theme.overlay.MaterialThemeOverlay.wrap;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.PorterDuff;
import android.graphics.PorterDuff.Mode;
Expand Down Expand Up @@ -81,6 +83,11 @@ public class MaterialCheckBox extends AppCompatCheckBox {
new int[] {-android.R.attr.state_enabled, android.R.attr.state_checked}, // [3]
new int[] {-android.R.attr.state_enabled, -android.R.attr.state_checked} // [4]
};

@SuppressLint("DiscouragedApi")
private static final int FRAMEWORK_BUTTON_DRAWABLE_RES_ID =
Resources.getSystem().getIdentifier("btn_check_material_anim", "drawable", "android");

@NonNull private final LinkedHashSet<OnErrorChangedListener> onErrorChangedListeners =
new LinkedHashSet<>();
@Nullable private ColorStateList materialThemeColorsTintList;
Expand All @@ -91,7 +98,7 @@ public class MaterialCheckBox extends AppCompatCheckBox {

@Nullable private Drawable buttonDrawable;
@Nullable private Drawable buttonIconDrawable;
private boolean usingDefaultButtonDrawable;
private boolean usingMaterialButtonDrawable;

@Nullable ColorStateList buttonTintList;
@Nullable ColorStateList buttonIconTintList;
Expand Down Expand Up @@ -165,10 +172,13 @@ public MaterialCheckBox(Context context, @Nullable AttributeSet attrs, int defSt
context, attrs, R.styleable.MaterialCheckBox, defStyleAttr, DEF_STYLE_RES);

buttonIconDrawable = attributes.getDrawable(R.styleable.MaterialCheckBox_buttonIcon);
// If there's not a custom drawable set, we set our own.
if (buttonDrawable == null) {
// If there's not a custom drawable set, we override the default legacy one and set our own.
if (buttonDrawable != null
&& ThemeEnforcement.isMaterial3Theme(context)
&& isButtonDrawableLegacy(attributes)) {
super.setButtonDrawable(null);
buttonDrawable = AppCompatResources.getDrawable(context, R.drawable.mtrl_checkbox_button);
usingDefaultButtonDrawable = true;
usingMaterialButtonDrawable = true;
if (buttonIconDrawable == null) {
buttonIconDrawable =
AppCompatResources.getDrawable(context, R.drawable.mtrl_checkbox_button_icon);
Expand Down Expand Up @@ -366,7 +376,7 @@ public void setButtonDrawable(@DrawableRes int resId) {
@Override
public void setButtonDrawable(@Nullable Drawable drawable) {
buttonDrawable = drawable;
usingDefaultButtonDrawable = false;
usingMaterialButtonDrawable = false;
refreshButtonDrawable();
}

Expand Down Expand Up @@ -559,7 +569,7 @@ public void jumpDrawablesToCurrentState() {
* the color change between states.
*/
private void setUpDefaultButtonDrawableAnimationIfNeeded() {
if (!usingDefaultButtonDrawable) {
if (!usingMaterialButtonDrawable) {
return;
}

Expand Down Expand Up @@ -601,6 +611,18 @@ private ColorStateList getSuperButtonTintList() {
return ((TintableCompoundButton) this).getSupportButtonTintList();
}

private boolean isButtonDrawableLegacy(TintTypedArray attributes) {
int buttonResourceId = attributes.getResourceId(R.styleable.MaterialCheckBox_android_button, 0);
int buttonCompatResourceId =
attributes.getResourceId(R.styleable.MaterialCheckBox_buttonCompat, 0);
if (VERSION.SDK_INT < 21) {
return buttonResourceId == R.drawable.abc_btn_check_material
&& buttonCompatResourceId == R.drawable.abc_btn_check_material_anim;
} else {
return buttonResourceId == FRAMEWORK_BUTTON_DRAWABLE_RES_ID && buttonCompatResourceId == 0;
}
}

private ColorStateList getMaterialThemeColorsTintList() {
if (materialThemeColorsTintList == null) {
int[] checkBoxColorsList = new int[CHECKBOX_STATES.length];
Expand Down
Expand Up @@ -16,6 +16,8 @@
-->
<resources>
<declare-styleable name="MaterialCheckBox">
<attr name="android:button"/>
<attr name="buttonCompat"/>
<!-- When set to true, MaterialCheckBox will tint itself according to
Material Theme colors. When set to false, Material Theme colors will
be ignored. This value should be set to false when using custom drawables
Expand Down
Expand Up @@ -29,12 +29,9 @@
<item name="errorAccessibilityLabel">@string/error_a11y_label</item>
<item name="buttonTint">@color/m3_checkbox_button_tint</item>
<item name="buttonIconTint">@color/m3_checkbox_button_icon_tint</item>
<!-- We null the button and icon here to preserve pre-existing behaviors of
when the checkbox didn't have the concept of an icon drawable separate
from the button drawable. Both default drawables will be set in
MaterialCheckBox. -->
<item name="buttonCompat">@null</item>
<item name="android:button">@null</item>
<!-- We null the icon here to preserve pre-existing behaviors of when the
didn't have the concept of an icon drawable separate from the button
drawable. The default icon drawable will be set in MaterialCheckBox. -->
<item name="buttonIcon">@null</item>
</style>

Expand Down
Expand Up @@ -31,6 +31,7 @@
import androidx.annotation.RestrictTo;
import androidx.annotation.StyleRes;
import androidx.annotation.StyleableRes;
import com.google.android.material.resources.MaterialAttributes;

/**
* Utility methods to check Theme compatibility with components.
Expand Down Expand Up @@ -223,6 +224,11 @@ public static boolean isMaterialTheme(@NonNull Context context) {
return isTheme(context, MATERIAL_CHECK_ATTRS);
}

public static boolean isMaterial3Theme(@NonNull Context context) {
return MaterialAttributes
.resolveBoolean(context, R.attr.isMaterial3Theme, false);
}

private static boolean isTheme(@NonNull Context context, @NonNull int[] themeAttributes) {
TypedArray a = context.obtainStyledAttributes(themeAttributes);
for (int i = 0; i < themeAttributes.length; i++) {
Expand Down

0 comments on commit 9ca8a80

Please sign in to comment.