From f76b75a5faf025ccda4474b5339582465dad1905 Mon Sep 17 00:00:00 2001 From: leticiars Date: Fri, 29 Jul 2022 15:03:27 -0400 Subject: [PATCH] [Checkbox] Fix pre-21 issue where a child of the layer drawable (the button and/or the icon drawables) may not have its constant state set up properly. PiperOrigin-RevId: 464128801 (cherry picked from commit 079371fd1069daf578cb6812335a5c018db0a1da) --- .../material/checkbox/MaterialCheckBox.java | 4 +-- .../material/internal/DrawableUtils.java | 32 +++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/lib/java/com/google/android/material/checkbox/MaterialCheckBox.java b/lib/java/com/google/android/material/checkbox/MaterialCheckBox.java index 0efea75d3a9..f0320fda1cd 100644 --- a/lib/java/com/google/android/material/checkbox/MaterialCheckBox.java +++ b/lib/java/com/google/android/material/checkbox/MaterialCheckBox.java @@ -541,10 +541,10 @@ public boolean isCenterIfNoTextEnabled() { private void refreshButtonDrawable() { buttonDrawable = - DrawableUtils.createTintableDrawableIfNeeded( + DrawableUtils.createTintableMutatedDrawableIfNeeded( buttonDrawable, buttonTintList, CompoundButtonCompat.getButtonTintMode(this)); buttonIconDrawable = - DrawableUtils.createTintableDrawableIfNeeded( + DrawableUtils.createTintableMutatedDrawableIfNeeded( buttonIconDrawable, buttonIconTintList, buttonIconTintMode); setUpDefaultButtonDrawableAnimationIfNeeded(); diff --git a/lib/java/com/google/android/material/internal/DrawableUtils.java b/lib/java/com/google/android/material/internal/DrawableUtils.java index d4717f694fe..f6883f49ada 100644 --- a/lib/java/com/google/android/material/internal/DrawableUtils.java +++ b/lib/java/com/google/android/material/internal/DrawableUtils.java @@ -41,9 +41,39 @@ public class DrawableUtils { private DrawableUtils() {} + /** + * Wraps and mutates the passed in drawable so that it may be used for tinting if a tintList is + * present. Also applies the tintMode if present. + */ @Nullable public static Drawable createTintableDrawableIfNeeded( @Nullable Drawable drawable, @Nullable ColorStateList tintList, @Nullable Mode tintMode) { + return createTintableMutatedDrawableIfNeeded( + drawable, tintList, tintMode, /* forceMutate= */ false); + } + + /** + * Wraps and mutates the passed in drawable so that it may be used for tinting if a tintList is + * present. Also applies the tintMode if present. If there's not a tintList and the API level is < + * 21, it'll still mutate the drawable. + * + *

Use this method instead of the above if the passed in drawable will be a child of a {@link + * LayerDrawable} in APIs < 21, its tintList may be null, and it may be mutated, in order to + * prevent issue where the drawable may not have its constant state set up properly. + */ + @Nullable + public static Drawable createTintableMutatedDrawableIfNeeded( + @Nullable Drawable drawable, @Nullable ColorStateList tintList, @Nullable Mode tintMode) { + return createTintableMutatedDrawableIfNeeded( + drawable, tintList, tintMode, VERSION.SDK_INT < VERSION_CODES.LOLLIPOP); + } + + @Nullable + private static Drawable createTintableMutatedDrawableIfNeeded( + @Nullable Drawable drawable, + @Nullable ColorStateList tintList, + @Nullable Mode tintMode, + boolean forceMutate) { if (drawable == null) { return null; } @@ -52,6 +82,8 @@ public static Drawable createTintableDrawableIfNeeded( if (tintMode != null) { DrawableCompat.setTintMode(drawable, tintMode); } + } else if (forceMutate) { + drawable.mutate(); } return drawable; }