diff --git a/lib/java/com/google/android/material/appbar/AppBarLayout.java b/lib/java/com/google/android/material/appbar/AppBarLayout.java
index 332aa6e0641..1087eff4f3a 100644
--- a/lib/java/com/google/android/material/appbar/AppBarLayout.java
+++ b/lib/java/com/google/android/material/appbar/AppBarLayout.java
@@ -34,7 +34,6 @@
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.ColorStateListDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.os.Build;
@@ -53,7 +52,6 @@
import android.widget.ScrollView;
import androidx.annotation.ColorInt;
import androidx.annotation.Dimension;
-import androidx.annotation.DoNotInline;
import androidx.annotation.DrawableRes;
import androidx.annotation.IdRes;
import androidx.annotation.IntDef;
@@ -77,6 +75,7 @@
import com.google.android.material.animation.AnimationUtils;
import com.google.android.material.animation.ArgbEvaluatorCompat;
import com.google.android.material.appbar.AppBarLayout.BaseBehavior.SavedState;
+import com.google.android.material.drawable.DrawableUtils;
import com.google.android.material.internal.ThemeEnforcement;
import com.google.android.material.motion.MotionUtils;
import com.google.android.material.resources.MaterialResources;
@@ -262,7 +261,7 @@ public AppBarLayout(@NonNull Context context, @Nullable AttributeSet attrs, int
MaterialResources.getColorStateList(
context, a, R.styleable.AppBarLayout_liftOnScrollColor);
- ColorStateList backgroundCSL = getBackgroundCSL();
+ ColorStateList backgroundCSL = DrawableUtils.getColorStateListOrNull(getBackground());
if (backgroundCSL != null) {
MaterialShapeDrawable materialShapeDrawable = new MaterialShapeDrawable();
materialShapeDrawable.setFillColor(backgroundCSL);
@@ -326,17 +325,6 @@ public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets)
});
}
- @Nullable
- private ColorStateList getBackgroundCSL() {
- Drawable background = getBackground();
- if (background instanceof ColorDrawable) {
- return ColorStateList.valueOf(((ColorDrawable) background).getColor());
- } else if (VERSION.SDK_INT >= VERSION_CODES.Q) {
- return DrawableHelperV29.maybeGetBackgroundCSL(background);
- }
- return null;
- }
-
private void initializeLiftOnScrollWithColor(MaterialShapeDrawable background) {
MaterialShapeDrawable liftBackground = new MaterialShapeDrawable();
liftBackground.setFillColor(liftOnScrollColor);
@@ -2612,16 +2600,4 @@ public void onOffsetChanged(
}
}
}
-
- @RequiresApi(VERSION_CODES.Q)
- private static class DrawableHelperV29 {
- @DoNotInline
- @Nullable
- private static ColorStateList maybeGetBackgroundCSL(@Nullable Drawable background) {
- if (background instanceof ColorStateListDrawable) {
- return ((ColorStateListDrawable) background).getColorStateList();
- }
- return null;
- }
- }
}
diff --git a/lib/java/com/google/android/material/appbar/MaterialToolbar.java b/lib/java/com/google/android/material/appbar/MaterialToolbar.java
index c77abda68c0..3c5e4a2cb6f 100644
--- a/lib/java/com/google/android/material/appbar/MaterialToolbar.java
+++ b/lib/java/com/google/android/material/appbar/MaterialToolbar.java
@@ -25,7 +25,6 @@
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Color;
-import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build.VERSION_CODES;
import androidx.appcompat.view.menu.MenuBuilder;
@@ -34,7 +33,6 @@
import android.util.Pair;
import android.view.Menu;
import android.view.View;
-import android.view.View.MeasureSpec;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.ColorInt;
@@ -43,6 +41,8 @@
import androidx.annotation.RequiresApi;
import androidx.core.graphics.drawable.DrawableCompat;
import androidx.core.view.ViewCompat;
+
+import com.google.android.material.drawable.DrawableUtils;
import com.google.android.material.internal.ThemeEnforcement;
import com.google.android.material.internal.ToolbarUtils;
import com.google.android.material.shape.MaterialShapeDrawable;
@@ -378,16 +378,17 @@ public boolean isSubtitleCentered() {
private void initBackground(Context context) {
Drawable background = getBackground();
- if (background != null && !(background instanceof ColorDrawable)) {
- return;
+ ColorStateList backgroundCSL = background != null
+ ? DrawableUtils.getColorStateListOrNull(background)
+ : ColorStateList.valueOf(Color.TRANSPARENT);
+
+ if (backgroundCSL != null) {
+ MaterialShapeDrawable materialShapeDrawable = new MaterialShapeDrawable();
+ materialShapeDrawable.setFillColor(backgroundCSL);
+ materialShapeDrawable.initializeElevationOverlay(context);
+ materialShapeDrawable.setElevation(ViewCompat.getElevation(this));
+ ViewCompat.setBackground(this, materialShapeDrawable);
}
- MaterialShapeDrawable materialShapeDrawable = new MaterialShapeDrawable();
- int backgroundColor =
- background != null ? ((ColorDrawable) background).getColor() : Color.TRANSPARENT;
- materialShapeDrawable.setFillColor(ColorStateList.valueOf(backgroundColor));
- materialShapeDrawable.initializeElevationOverlay(context);
- materialShapeDrawable.setElevation(ViewCompat.getElevation(this));
- ViewCompat.setBackground(this, materialShapeDrawable);
}
@Nullable
diff --git a/lib/java/com/google/android/material/bottomsheet/BottomSheetDialog.java b/lib/java/com/google/android/material/bottomsheet/BottomSheetDialog.java
index 7dd4a867d05..fc4ee356b8c 100644
--- a/lib/java/com/google/android/material/bottomsheet/BottomSheetDialog.java
+++ b/lib/java/com/google/android/material/bottomsheet/BottomSheetDialog.java
@@ -24,7 +24,6 @@
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.Color;
-import android.graphics.drawable.ColorDrawable;
import android.os.Build;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
@@ -49,7 +48,9 @@
import androidx.core.view.WindowInsetsCompat;
import androidx.core.view.WindowInsetsControllerCompat;
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
+
import com.google.android.material.internal.EdgeToEdgeUtils;
+import com.google.android.material.internal.ViewUtils;
import com.google.android.material.motion.MaterialBackOrchestrator;
import com.google.android.material.shape.MaterialShapeDrawable;
@@ -467,12 +468,15 @@ private EdgeToEdgeCallback(
if (backgroundTint != null) {
// First check for a tint
lightBottomSheet = isColorLight(backgroundTint.getDefaultColor());
- } else if (bottomSheet.getBackground() instanceof ColorDrawable) {
- // Then check for the background color
- lightBottomSheet = isColorLight(((ColorDrawable) bottomSheet.getBackground()).getColor());
} else {
- // Otherwise don't change the status bar color
- lightBottomSheet = null;
+ Integer backgroundColor = ViewUtils.getBackgroundColor(bottomSheet);
+ if (backgroundColor != null) {
+ // Then check for the background color
+ lightBottomSheet = isColorLight(backgroundColor);
+ } else {
+ // Otherwise don't change the status bar color
+ lightBottomSheet = null;
+ }
}
}
diff --git a/lib/java/com/google/android/material/drawable/DrawableUtils.java b/lib/java/com/google/android/material/drawable/DrawableUtils.java
index 9a4df314859..7f444da18e2 100644
--- a/lib/java/com/google/android/material/drawable/DrawableUtils.java
+++ b/lib/java/com/google/android/material/drawable/DrawableUtils.java
@@ -29,6 +29,8 @@
import android.graphics.PorterDuff;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffColorFilter;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.ColorStateListDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.graphics.drawable.RippleDrawable;
@@ -369,4 +371,35 @@ public static void setOutlineToPath(@NonNull final Outline outline, @NonNull fin
outline.setConvexPath(path);
}
}
+
+ /**
+ * Returns the {@link ColorStateList} if it can be retrieved from the {@code drawable}, or null
+ * otherwise.
+ *
+ * In particular:
+ *
+ * - If the {@code drawable} is a {@link ColorStateListDrawable}, the method will
+ * return the {@code drawable}'s {@link ColorStateList}.
+ * - If the {@code drawable} is a {@link ColorDrawable}, the method will return a
+ * {@link ColorStateList} containing the {@code drawable}'s color.
+ *
+ */
+ @Nullable
+ public static ColorStateList getColorStateListOrNull(@Nullable final Drawable drawable) {
+ if (drawable == null) {
+ return null;
+ }
+
+ if (drawable instanceof ColorDrawable) {
+ return ColorStateList.valueOf(((ColorDrawable) drawable).getColor());
+ }
+
+ if (VERSION.SDK_INT >= VERSION_CODES.Q) {
+ if (drawable instanceof ColorStateListDrawable) {
+ return ((ColorStateListDrawable) drawable).getColorStateList();
+ }
+ }
+
+ return null;
+ }
}
diff --git a/lib/java/com/google/android/material/internal/ViewUtils.java b/lib/java/com/google/android/material/internal/ViewUtils.java
index 9200d80f4e7..a542ce5e6c9 100644
--- a/lib/java/com/google/android/material/internal/ViewUtils.java
+++ b/lib/java/com/google/android/material/internal/ViewUtils.java
@@ -17,16 +17,19 @@
package com.google.android.material.internal;
import com.google.android.material.R;
+import com.google.android.material.drawable.DrawableUtils;
import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP;
import static androidx.core.content.ContextCompat.getSystemService;
import android.content.Context;
+import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.ColorStateListDrawable;
import android.os.Build;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
@@ -40,6 +43,7 @@
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.WindowInsets;
import android.view.inputmethod.InputMethodManager;
+
import androidx.annotation.Dimension;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -436,13 +440,22 @@ public static void removeOnGlobalLayoutListener(
}
/**
- * Returns the provided view's background color, if it has ColorDrawable as its background, or
- * {@code null} if the background has a different drawable type.
+ * Returns the color if it can be retrieved from the {@code view}'s background drawable, or null
+ * otherwise.
+ *
+ * In particular:
+ *
+ * - If the {@code view}'s background drawable is a {@link ColorDrawable}, the method will
+ * return the drawable's color.
+ * - If the {@code view}'s background drawable is a {@link ColorStateListDrawable}, the method
+ * will return the default color of the drawable's {@link ColorStateList}.
+ *
*/
@Nullable
public static Integer getBackgroundColor(@NonNull View view) {
- return view.getBackground() instanceof ColorDrawable
- ? ((ColorDrawable) view.getBackground()).getColor()
+ final ColorStateList backgroundCSL = DrawableUtils.getColorStateListOrNull(view.getBackground());
+ return backgroundCSL != null
+ ? backgroundCSL.getDefaultColor()
: null;
}
}
diff --git a/lib/java/com/google/android/material/navigation/NavigationBarView.java b/lib/java/com/google/android/material/navigation/NavigationBarView.java
index 6caba244106..f59cf1db643 100644
--- a/lib/java/com/google/android/material/navigation/NavigationBarView.java
+++ b/lib/java/com/google/android/material/navigation/NavigationBarView.java
@@ -25,7 +25,7 @@
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
-import android.graphics.drawable.ColorDrawable;
+import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
@@ -56,6 +56,7 @@
import androidx.core.view.ViewCompat;
import androidx.customview.view.AbsSavedState;
import com.google.android.material.badge.BadgeDrawable;
+import com.google.android.material.drawable.DrawableUtils;
import com.google.android.material.internal.ThemeEnforcement;
import com.google.android.material.resources.MaterialResources;
import com.google.android.material.shape.MaterialShapeDrawable;
@@ -195,10 +196,19 @@ public NavigationBarView(
setItemTextColor(attributes.getColorStateList(R.styleable.NavigationBarView_itemTextColor));
}
- if (getBackground() == null || getBackground() instanceof ColorDrawable) {
- // Add a MaterialShapeDrawable as background that supports tinting in every API level.
- ViewCompat.setBackground(this, createMaterialShapeDrawableBackground(context,
- ShapeAppearanceModel.builder(context, attrs, defStyleAttr, defStyleRes).build()));
+ // Add a MaterialShapeDrawable as background that supports tinting in every API level.
+ Drawable background = getBackground();
+ ColorStateList backgroundCSL = background != null
+ ? DrawableUtils.getColorStateListOrNull(background)
+ : ColorStateList.valueOf(Color.TRANSPARENT);
+
+ if (backgroundCSL != null) {
+ ShapeAppearanceModel shapeAppearanceModel =
+ ShapeAppearanceModel.builder(context, attrs, defStyleAttr, defStyleRes).build();
+ MaterialShapeDrawable materialShapeDrawable = new MaterialShapeDrawable(shapeAppearanceModel);
+ materialShapeDrawable.setFillColor(backgroundCSL);
+ materialShapeDrawable.initializeElevationOverlay(context);
+ ViewCompat.setBackground(this, materialShapeDrawable);
}
if (attributes.hasValue(R.styleable.NavigationBarView_itemPaddingTop)) {
@@ -306,20 +316,6 @@ public void onMenuModeChange(MenuBuilder menu) {}
});
}
- @NonNull
- private MaterialShapeDrawable createMaterialShapeDrawableBackground(
- Context context, ShapeAppearanceModel shapeAppearanceModel) {
- MaterialShapeDrawable materialShapeDrawable = new MaterialShapeDrawable();
- Drawable originalBackground = getBackground();
- if (originalBackground instanceof ColorDrawable) {
- materialShapeDrawable.setFillColor(
- ColorStateList.valueOf(((ColorDrawable) originalBackground).getColor()));
- }
- materialShapeDrawable.initializeElevationOverlay(context);
- materialShapeDrawable.setShapeAppearanceModel(shapeAppearanceModel);
- return materialShapeDrawable;
- }
-
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
diff --git a/lib/java/com/google/android/material/navigation/NavigationView.java b/lib/java/com/google/android/material/navigation/NavigationView.java
index 86c2b5ed5bf..35cfc656803 100644
--- a/lib/java/com/google/android/material/navigation/NavigationView.java
+++ b/lib/java/com/google/android/material/navigation/NavigationView.java
@@ -30,8 +30,6 @@
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.RectF;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.ColorStateListDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.InsetDrawable;
import android.graphics.drawable.RippleDrawable;
@@ -77,6 +75,8 @@
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.drawerlayout.widget.DrawerLayout.DrawerListener;
import androidx.drawerlayout.widget.DrawerLayout.SimpleDrawerListener;
+
+import com.google.android.material.drawable.DrawableUtils;
import com.google.android.material.internal.ContextUtils;
import com.google.android.material.internal.NavigationMenu;
import com.google.android.material.internal.NavigationMenuPresenter;
@@ -201,24 +201,18 @@ public NavigationView(@NonNull Context context, @Nullable AttributeSet attrs, in
drawerLayoutCornerSize =
a.getDimensionPixelSize(R.styleable.NavigationView_drawerLayoutCornerSize, 0);
- Drawable background = getBackground();
// Set the background to a MaterialShapeDrawable if it hasn't been set or if it can be converted
// to a MaterialShapeDrawable.
- if (background == null
- || background instanceof ColorDrawable
- || (VERSION.SDK_INT >= VERSION_CODES.Q
- && background instanceof ColorStateListDrawable)) {
+ Drawable background = getBackground();
+ ColorStateList backgroundCSL = background != null
+ ? DrawableUtils.getColorStateListOrNull(background)
+ : ColorStateList.valueOf(Color.TRANSPARENT);
+
+ if (backgroundCSL != null) {
ShapeAppearanceModel shapeAppearanceModel =
ShapeAppearanceModel.builder(context, attrs, defStyleAttr, DEF_STYLE_RES).build();
MaterialShapeDrawable materialShapeDrawable = new MaterialShapeDrawable(shapeAppearanceModel);
- if (background instanceof ColorDrawable) {
- materialShapeDrawable.setFillColor(
- ColorStateList.valueOf(((ColorDrawable) background).getColor()));
- }
- if (VERSION.SDK_INT >= VERSION_CODES.Q && background instanceof ColorStateListDrawable) {
- materialShapeDrawable.setFillColor(
- ((ColorStateListDrawable) background).getColorStateList());
- }
+ materialShapeDrawable.setFillColor(backgroundCSL);
materialShapeDrawable.initializeElevationOverlay(context);
ViewCompat.setBackground(this, materialShapeDrawable);
}
diff --git a/lib/java/com/google/android/material/tabs/TabLayout.java b/lib/java/com/google/android/material/tabs/TabLayout.java
index 4cb41d3af29..669b94d4eb6 100644
--- a/lib/java/com/google/android/material/tabs/TabLayout.java
+++ b/lib/java/com/google/android/material/tabs/TabLayout.java
@@ -546,10 +546,10 @@ public TabLayout(@NonNull Context context, @Nullable AttributeSet attrs, int def
DEF_STYLE_RES,
R.styleable.TabLayout_tabTextAppearance);
- if (getBackground() instanceof ColorDrawable) {
- ColorDrawable background = (ColorDrawable) getBackground();
+ ColorStateList backgroundCSL = DrawableUtils.getColorStateListOrNull(getBackground());
+ if (backgroundCSL != null) {
MaterialShapeDrawable materialShapeDrawable = new MaterialShapeDrawable();
- materialShapeDrawable.setFillColor(ColorStateList.valueOf(background.getColor()));
+ materialShapeDrawable.setFillColor(backgroundCSL);
materialShapeDrawable.initializeElevationOverlay(context);
materialShapeDrawable.setElevation(ViewCompat.getElevation(this));
ViewCompat.setBackground(this, materialShapeDrawable);