From b335436cf2f70bf0f9222f1960ad0e442d46ebd7 Mon Sep 17 00:00:00 2001 From: Material Design Team Date: Mon, 24 Apr 2023 15:26:40 -0400 Subject: [PATCH] [M3][Color] Updated content-based dynamic with contrast levels PiperOrigin-RevId: 526722393 --- .../android/material/color/DynamicColors.java | 50 ++++++++++++++++--- .../material/color/MaterialColors.java | 2 +- 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/lib/java/com/google/android/material/color/DynamicColors.java b/lib/java/com/google/android/material/color/DynamicColors.java index b39e9bb415e..27cf761937d 100644 --- a/lib/java/com/google/android/material/color/DynamicColors.java +++ b/lib/java/com/google/android/material/color/DynamicColors.java @@ -21,6 +21,7 @@ import android.app.Activity; import android.app.Application; import android.app.Application.ActivityLifecycleCallbacks; +import android.app.UiModeManager; import android.content.Context; import android.content.res.TypedArray; import android.os.Build; @@ -321,9 +322,8 @@ public static void applyToActivityIfAvailable( SchemeContent scheme = new SchemeContent( Hct.fromInt(dynamicColorsOptions.getContentBasedSeedColor()), - !MaterialAttributes.resolveBoolean( - activity, R.attr.isLightTheme, /* defaultValue= */ true), - /* contrastLevel= */ 0); + !MaterialColors.isLightTheme(activity), + getSystemContrast(activity)); ColorResourcesOverride resourcesOverride = ColorResourcesOverride.getInstance(); if (resourcesOverride == null) { return; @@ -371,9 +371,27 @@ public static Context wrapContextIfAvailable(@NonNull Context originalContext) { @NonNull public static Context wrapContextIfAvailable( @NonNull Context originalContext, @StyleRes int theme) { + return wrapContextIfAvailable( + originalContext, new DynamicColorsOptions.Builder().setThemeOverlay(theme).build()); + } + + /** + * Wraps the given context with the given theme overlay provided in {@link DynamicColorsOptions}. + * The returned context can be used to create views with dynamic color support. + * + *

If dynamic color support is not available, the original context will be returned. + * + * @param originalContext The original context. + * @param dynamicColorsOptions The dynamic colors options object that specifies the theme resource + * ID, seed color for content-based dynamic colors. + */ + @NonNull + public static Context wrapContextIfAvailable( + @NonNull Context originalContext, @NonNull DynamicColorsOptions dynamicColorsOptions) { if (!isDynamicColorAvailable()) { return originalContext; } + int theme = dynamicColorsOptions.getThemeOverlay(); if (theme == USE_DEFAULT_THEME_OVERLAY) { theme = getDefaultThemeOverlay(originalContext); } @@ -382,16 +400,29 @@ public static Context wrapContextIfAvailable( return originalContext; } - if (shouldOverrideNeutralChroma(originalContext)) { + if (dynamicColorsOptions.getContentBasedSeedColor() != null) { + SchemeContent scheme = + new SchemeContent( + Hct.fromInt(dynamicColorsOptions.getContentBasedSeedColor()), + !MaterialColors.isLightTheme(originalContext), + getSystemContrast(originalContext)); ColorResourcesOverride resourcesOverride = ColorResourcesOverride.getInstance(); if (resourcesOverride != null) { return resourcesOverride.wrapContextIfPossible( originalContext, - createColorResourcesIdsToColorValuesWithUpdatedChroma(originalContext), - theme); + MaterialColorUtilitiesHelper.createColorResourcesIdsToColorValues(scheme)); + } + } else { + if (shouldOverrideNeutralChroma(originalContext)) { + ColorResourcesOverride resourcesOverride = ColorResourcesOverride.getInstance(); + if (resourcesOverride != null) { + return resourcesOverride.wrapContextIfPossible( + originalContext, + createColorResourcesIdsToColorValuesWithUpdatedChroma(originalContext), + theme); + } } } - return new ContextThemeWrapper(originalContext, theme); } @@ -529,4 +560,9 @@ public void onActivityDestroyed(@NonNull Activity activity) {} private interface DeviceSupportCondition { boolean isSupported(); } + + private static float getSystemContrast(Context context) { + UiModeManager uiModeManager = (UiModeManager) context.getSystemService(Context.UI_MODE_SERVICE); + return (uiModeManager == null || !BuildCompat.isAtLeastU()) ? 0 : uiModeManager.getContrast(); + } } diff --git a/lib/java/com/google/android/material/color/MaterialColors.java b/lib/java/com/google/android/material/color/MaterialColors.java index 996d7af06aa..cde74b5d299 100644 --- a/lib/java/com/google/android/material/color/MaterialColors.java +++ b/lib/java/com/google/android/material/color/MaterialColors.java @@ -339,7 +339,7 @@ public static int getSurfaceContainerHighFromSeed( return getColorRole(seedColor, tone, CHROMA_NEUTRAL); } - private static boolean isLightTheme(@NonNull Context context) { + static boolean isLightTheme(@NonNull Context context) { return MaterialAttributes.resolveBoolean( context, R.attr.isLightTheme, /* defaultValue= */ true); }