material-components / material-components-android

Modular and customizable Material Design UI components for Android
Apache License 2.0
16.14k stars 3.05k forks source link

[M3/DynamicColors] Dynamic Colors not applied when SplashScreen API is used #2555

Closed serbelga closed 2 years ago

serbelga commented 2 years ago

Description:

When application or activity launcher theme inherits from Theme.SplashScreen and we set postSplashScreenTheme to a theme that inherits from Material3, it does not apply Dynamic Colors when we call DynamicColors.applyToActivitiesIfAvailable(this) on the Application class.

Expected behavior: Apply Dynamic colors.

Source code: https://github.com/serbelga/ToDometer/tree/feature/dynamicColors

Android API version: Android SDK 31 (Android 12)

Material Library version: 1.5.0

    <!-- Base application theme. -->
    <style name="Theme.ToDometer" parent="Theme.Material3.DayNight">
    ...
    </style>

    <style name="Theme.ToDometer.NoActionBar">
    ...
    </style>

    <style name="Theme.ToDometer.Starting" parent="Theme.SplashScreen">
        <item name="windowSplashScreenBackground">@color/navy</item>

        <item name="windowSplashScreenAnimatedIcon">@drawable/ic_launcher_foreground</item>
        <item name="windowSplashScreenAnimationDuration">2000</item>

        <item name="postSplashScreenTheme">@style/Theme.ToDometer.NoActionBar</item>
    </style>

AndroidManifest.xml

    <application
        android:name=".App"
        ...
-       android:theme="@style/Theme.ToDometer.NoActionBar">
+       android:theme="@style/Theme.ToDometer.Starting">
drchen commented 2 years ago

Hi, unfortunately due to the restriction of the framework, the splash screen is not something we can really control from the code.

To apply dynamic colors on the splash screen, you need to use system resources directly in your relevant XMLs - here we list all system dynamic color resource you can use: https://github.com/material-components/material-components-android/blob/master/catalog/java/io/material/catalog/color/res/values-v31/arrays.xml

Hope this solves your problem.

serbelga commented 2 years ago

I really don't want to apply Dynamic colors in Splash Screen. The problem is that specifying a Material3 as the postSplashScreenTheme won't apply Dynamic colors.

drchen commented 2 years ago

I don't have access to your github link. Where do you call DynamicColors.applyToActivitiesIfAvailable(this) and installSplashScreen()?

You may want to avoid using postSplashScreenTheme since I guess it will override the dynamic color theme overlay we set. Or you can also try to set postSplashScreenTheme to ThemeOverlay.Material3.DynamicColors.DayNight and see if it works in your case?

serbelga commented 2 years ago

Here is the link: https://github.com/serbelga/ToDometer/tree/develop

You may want to avoid using postSplashScreenTheme since I guess it will override the dynamic color theme overlay we set. Or you can also try to set postSplashScreenTheme to ThemeOverlay.Material3.DynamicColors.DayNight and see if it works in your case?

I will try this

ytheekshana commented 2 years ago

Having the same thing. Is this addressed?

axiel7 commented 1 year ago

I solved this issue by calling DynamicColors.applyToActivityIfAvailable(this) after installSplashScreen(). Don't use DynamicColors.applyToActivitiesIfAvailable(this) in your Application class.

override fun onCreate(savedInstanceState: Bundle?) {
        installSplashScreen()
        DynamicColors.applyToActivityIfAvailable(this)

}
woheller69 commented 1 year ago

I solved this issue by calling DynamicColors.applyToActivityIfAvailable(this) after installSplashScreen(). Don't use DynamicColors.applyToActivitiesIfAvailable(this) in your Application class.

override fun onCreate(savedInstanceState: Bundle?) {
        installSplashScreen()
        DynamicColors.applyToActivityIfAvailable(this)

}

If I apply that solution the status bar at the top still does not get the correct dynamic color

axiel7 commented 1 year ago

@woheller69 try this. Also set the status bar color to transparent in your theme

override fun onCreate(savedInstanceState: Bundle?) {
        installSplashScreen()
        DynamicColors.applyToActivityIfAvailable(this)
        super.onCreate(savedInstanceState)
        WindowCompat.setDecorFitsSystemWindows(window, false)
}
woheller69 commented 1 year ago

This also does not solve the problem. In light mode I get a white status bar with white text on it and in dark mode the status bar is black and does not have the theme color.

woheller69 commented 1 year ago

Cleanest solution is probably to simply remove SplashScreen API...

woheller69 commented 1 year ago

I found a solution:

In Activity:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
      SplashScreen.installSplashScreen(this);
      DynamicColors.applyToActivityIfAvailable(this);
      DynamicColors.applyToActivitiesIfAvailable(this.getApplication());  //both needed to apply to other activities as well
      getWindow().setStatusBarColor(getThemeColor(this,R.attr.colorPrimaryDark));
      super.onCreate(savedInstanceState);

    public static int getThemeColor(Context context, int colorResId) {
      TypedValue typedValue = new TypedValue();
      TypedArray typedArray = context.obtainStyledAttributes(typedValue.data, new int[] {colorResId});
      int color = typedArray.getColor(0, 0);
      typedArray.recycle();
      return color;
    }
the-rebooted-coder commented 11 months ago

getWindow().setStatusBarColor(getThemeColor(this,android.R.attr.colorPrimaryDark)); this worked for me