From f6c8fa5aefc84a1543eca3056a538120de0b4297 Mon Sep 17 00:00:00 2001 From: dsn5ft <1420597+dsn5ft@users.noreply.github.com> Date: Fri, 4 Feb 2022 09:04:21 -0800 Subject: [PATCH] [Color] Update DynamicColors util to applyStyle() on window decorView theme as well to fix potential ContextMenu issue PiperOrigin-RevId: 426416360 --- .../android/material/color/DynamicColors.java | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/lib/java/com/google/android/material/color/DynamicColors.java b/lib/java/com/google/android/material/color/DynamicColors.java index 21a69d92d28..d4767a975b2 100644 --- a/lib/java/com/google/android/material/color/DynamicColors.java +++ b/lib/java/com/google/android/material/color/DynamicColors.java @@ -22,12 +22,15 @@ import android.app.Application; import android.app.Application.ActivityLifecycleCallbacks; import android.content.Context; +import android.content.res.Resources.Theme; import android.content.res.TypedArray; import android.os.Build; import android.os.Build.VERSION; import android.os.Build.VERSION_CODES; import android.os.Bundle; import android.view.ContextThemeWrapper; +import android.view.View; +import android.view.Window; import androidx.annotation.ChecksSdkIntAtLeast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -231,8 +234,7 @@ private static void applyIfAvailable( theme = getDefaultThemeOverlay(activity); } if (theme != 0 && precondition.shouldApplyDynamicColors(activity, theme)) { - // Use applyStyle() instead of setTheme() due to Force Dark issue. - activity.getTheme().applyStyle(theme, /* force= */ true); + applyDynamicColorThemeOverlay(activity, theme); } } @@ -297,6 +299,33 @@ private static int getDefaultThemeOverlay(@NonNull Context context) { return theme; } + private static void applyDynamicColorThemeOverlay(Activity activity, @StyleRes int theme) { + // Use applyStyle() instead of setTheme() due to Force Dark issue. + activity.getTheme().applyStyle(theme, /* force= */ true); + + // Make sure theme is applied to the Window decorView similar to Activity#setTheme, to ensure + // that the dynamic colors will be applied to things like ContextMenu using the DecorContext. + Theme windowDecorViewTheme = getWindowDecorViewTheme(activity); + if (windowDecorViewTheme != null) { + windowDecorViewTheme.applyStyle(theme, /* force= */ true); + } + } + + @Nullable + private static Theme getWindowDecorViewTheme(@NonNull Activity activity) { + Window window = activity.getWindow(); + if (window != null) { + View decorView = window.getDecorView(); + if (decorView != null) { + Context context = decorView.getContext(); + if (context != null) { + return context.getTheme(); + } + } + } + return null; + } + /** * The interface that provides a precondition to decide if dynamic colors should be applied. */