diff --git a/lib/java/com/google/android/material/button/MaterialButtonHelper.java b/lib/java/com/google/android/material/button/MaterialButtonHelper.java index 4bbb99027ea..69709576e86 100644 --- a/lib/java/com/google/android/material/button/MaterialButtonHelper.java +++ b/lib/java/com/google/android/material/button/MaterialButtonHelper.java @@ -16,10 +16,6 @@ package com.google.android.material.button; -import com.google.android.material.R; - -import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; - import android.content.Context; import android.content.res.ColorStateList; import android.content.res.TypedArray; @@ -31,12 +27,15 @@ import android.graphics.drawable.RippleDrawable; import android.os.Build.VERSION; import android.os.Build.VERSION_CODES; -import androidx.core.graphics.drawable.DrawableCompat; -import androidx.core.view.ViewCompat; + import androidx.annotation.Dimension; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.RestrictTo; +import androidx.core.graphics.drawable.DrawableCompat; +import androidx.core.view.ViewCompat; + +import com.google.android.material.R; import com.google.android.material.color.MaterialColors; import com.google.android.material.internal.ViewUtils; import com.google.android.material.resources.MaterialResources; @@ -46,11 +45,15 @@ import com.google.android.material.shape.ShapeAppearanceModel; import com.google.android.material.shape.Shapeable; +import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; + /** @hide */ @RestrictTo(LIBRARY_GROUP) class MaterialButtonHelper { - private static final boolean IS_LOLLIPOP = VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP; + private static final boolean IS_MIN_LOLLIPOP = VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP; + private static final boolean IS_LOLLIPOP = VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP && + VERSION.SDK_INT <= VERSION_CODES.LOLLIPOP_MR1; private final MaterialButton materialButton; @NonNull private ShapeAppearanceModel shapeAppearanceModel; @@ -218,7 +221,7 @@ private Drawable createBackground() { ? MaterialColors.getColor(materialButton, R.attr.colorSurface) : Color.TRANSPARENT); - if (IS_LOLLIPOP) { + if (IS_MIN_LOLLIPOP) { maskDrawable = new MaterialShapeDrawable(shapeAppearanceModel); DrawableCompat.setTint(maskDrawable, Color.WHITE); rippleDrawable = @@ -255,10 +258,10 @@ void setBackgroundColor(int color) { void setRippleColor(@Nullable ColorStateList rippleColor) { if (this.rippleColor != rippleColor) { this.rippleColor = rippleColor; - if (IS_LOLLIPOP && materialButton.getBackground() instanceof RippleDrawable) { + if (IS_MIN_LOLLIPOP && materialButton.getBackground() instanceof RippleDrawable) { ((RippleDrawable) materialButton.getBackground()) .setColor(RippleUtils.sanitizeRippleDrawableColor(rippleColor)); - } else if (!IS_LOLLIPOP && materialButton.getBackground() instanceof RippleDrawableCompat) { + } else if (!IS_MIN_LOLLIPOP && materialButton.getBackground() instanceof RippleDrawableCompat) { ((RippleDrawableCompat) materialButton.getBackground()).setTintList( RippleUtils.sanitizeRippleDrawableColor(rippleColor)); } @@ -326,7 +329,7 @@ int getCornerRadius() { @Nullable private MaterialShapeDrawable getMaterialShapeDrawable(boolean getSurfaceColorStrokeDrawable) { if (rippleDrawable != null && rippleDrawable.getNumberOfLayers() > 0) { - if (IS_LOLLIPOP) { + if (IS_MIN_LOLLIPOP) { InsetDrawable insetDrawable = (InsetDrawable) rippleDrawable.getDrawable(0); LayerDrawable layerDrawable = (LayerDrawable) insetDrawable.getDrawable(); return (MaterialShapeDrawable) @@ -359,14 +362,20 @@ private MaterialShapeDrawable getSurfaceColorStrokeDrawable() { } private void updateButtonShape(@NonNull ShapeAppearanceModel shapeAppearanceModel) { - if (getMaterialShapeDrawable() != null) { - getMaterialShapeDrawable().setShapeAppearanceModel(shapeAppearanceModel); - } - if (getSurfaceColorStrokeDrawable() != null) { - getSurfaceColorStrokeDrawable().setShapeAppearanceModel(shapeAppearanceModel); - } - if (getMaskDrawable() != null) { - getMaskDrawable().setShapeAppearanceModel(shapeAppearanceModel); + if (IS_LOLLIPOP) { + // There seems to be a bug to drawables that is affecting Lollipop, since invalidation is not + // changing an existing drawable shape. This is a fallback + updateBackground(); + } else { + if (getMaterialShapeDrawable() != null) { + getMaterialShapeDrawable().setShapeAppearanceModel(shapeAppearanceModel); + } + if (getSurfaceColorStrokeDrawable() != null) { + getSurfaceColorStrokeDrawable().setShapeAppearanceModel(shapeAppearanceModel); + } + if (getMaskDrawable() != null) { + getMaskDrawable().setShapeAppearanceModel(shapeAppearanceModel); + } } } diff --git a/lib/javatests/com/google/android/material/button/MaterialButtonTest.java b/lib/javatests/com/google/android/material/button/MaterialButtonTest.java index 3ef9d4fab0d..4c4de1f2e16 100644 --- a/lib/javatests/com/google/android/material/button/MaterialButtonTest.java +++ b/lib/javatests/com/google/android/material/button/MaterialButtonTest.java @@ -22,6 +22,8 @@ import android.content.Context; import android.graphics.drawable.Drawable; import androidx.core.graphics.drawable.DrawableCompat; + +import android.os.Build; import android.view.View.MeasureSpec; import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; @@ -64,9 +66,23 @@ public void testSetShapeAppearanceModel_setCornerRadius() { ShapeAppearanceModel newShapeAppearanceModel = materialButton.getShapeAppearanceModel(); + assertThat(shapeAppearanceModel).isSameInstanceAs(newShapeAppearanceModel); assertThatCornerSizesMatch(shapeAppearanceModel, newShapeAppearanceModel); } + @Test + @Config(sdk = Build.VERSION_CODES.LOLLIPOP) + public void testShapeRippleDrawableInLollipop() { + MaterialButton materialButton = new MaterialButton(context); + ShapeAppearanceModel shapeAppearanceModel = materialButton.getShapeAppearanceModel(); + + materialButton.setCornerRadius((int) LARGE_CORNER_SIZE); + ShapeAppearanceModel newShapeAppearanceModel = materialButton.getShapeAppearanceModel(); + assertThat(shapeAppearanceModel).isNotSameInstanceAs(newShapeAppearanceModel); + assertThat(shapeAppearanceModel).isNotEqualTo(newShapeAppearanceModel); + } + + @Test public void testSetShapeAppearanceModel() { MaterialButton materialButton = new MaterialButton(context);