Android: How to set a drawable as a windowSplashScreenBackground parameter in the new SplashScreen API?

Viewed 3480

I want to make splash screen with gradient background and logo using Splash Screen API

Smth like this:

enter image description here

I`ve style with field windowSplashScreenBackground where value is solid color and it works fine:

<style name="Theme.MyApp.SplashScreen" parent="Theme.SplashScreen">
    <item name="windowSplashScreenBackground">@color/blue</item>
    <item name="windowSplashScreenAnimatedIcon">@mipmap/ic_launcher</item>
    <item name="postSplashScreenTheme">@style/Theme.MyApp</item>
</style>

The attribute windowSplashScreenBackground can take only colors.

Any ideas how to create gradient background? May be smth like this:

 <style name="Theme.MyApp.SplashScreen" parent="Theme.SplashScreen">
    ... 
    <item name="windowSplashScreenBackground">@drawable/gradient_splash_screen_background</item>
    ...
</style>

UPDATE

Also I tried declare background in field android:windowBackground instead of windowSplashScreenBackground

<style name="Theme.MyApp.SplashScreen" parent="Theme.SplashScreen">
    <item name="android:windowBackground">@drawable/gradient_splash_screen_background</item>
<!--        <item name="windowSplashScreenBackground">@color/purple</item>-->
<!--        <item name="windowSplashScreenBackground">@drawable/splash_screen_layers</item>-->
    <item name="windowSplashScreenAnimatedIcon">@mipmap/ic_launcher</item>
    <item name="postSplashScreenTheme">@style/Theme.MyApp</item>
</style>

But it solve one issue and consume another one. Background of screen accept gradient but logo become invisible

3 Answers

The short answer is - no, you can't use any drawable in windowSplashScreenBackground. Only regular hex color. That's limitation of new splash screen api. I have used and deeply investigated this version on June 1, 2022:

"androidx.core:core-splashscreen:1.0.0-rc01"

if you'll use this property like this, or will remove it at all -- you'll receive as a result - default system color on background or totaly black screen on API level < 31.

<item name="windowSplashScreenBackground">@null</item>
<item name="windowSplashScreenBackground">@drawable/some_custom_splash_background</item>

The same story with icon property: if it is NULL -- then default app icon will be shown (but on android api < 31 - it will be even worse), if icon has wrong sizes - it will be sqeezed to fixed sizes and circle shape. If you'll remove that property at all - it will use default app icon. You can't run away from icon in the center of the screen. Maby just try to make such icon with transparent color -- I think it can help, but didn't tried by myself.

<item name="windowSplashScreenAnimatedIcon">@null</item>
<item name="windowSplashScreenAnimatedIcon">@drawable/ic_launcher_foreground</item>

Other properties like: windowSplashScreenIconBackgroundColor, windowSplashScreenBrandingImage - are only available for API version 31+.

What I find out as workaround: it's to use new approach of SplashScreenAPI on Android 12+, and old one -- on all older versions. I have one MainActivity - and all of my screens are fragments. I have two style.xml files: res/values/style.xml and res-v31/values/style.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <style name="Theme.App.NewSplashScreenTheme" parent="Theme.SplashScreen">
        <item name="windowSplashScreenBackground">#24a0d1</item>
        <item name="windowSplashScreenAnimatedIcon">@drawable/ic_launcher_foreground</item>
        <item name="postSplashScreenTheme">@style/Theme.MyAppTheme</item>
        <item name="windowSplashScreenIconBackgroundColor">#f0e067</item>
        <item name="android:windowSplashScreenBrandingImage">@drawable/brand_logo</item>
    </style>
</resources>

and this is style.xml -- for all previous android versions:

<style name="Theme.App.NewSplashScreenTheme" parent="Theme.MyAppTheme">
        <item name="android:windowBackground">@drawable/splash_screen_background</item>
        <item name="android:windowFullscreen">true</item>
    </style>

And then in MainActivity's onCreate method I just do check for Android API version. That's it.

override fun onCreate(savedInstanceState: Bundle?) {
    if (Build.VERSION.SDK_INT >= 31){
        val splashScreen = installSplashScreen() //init new splash screen api for Android 12+
    } else{
        setTheme(R.style.Theme_MyAppTheme) //else use old approach
    }
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    }

and in AndroidManifest use new theme, which has the same name, but is different for different android versions:

<activity
            android:name=".MainActivity"
            android:screenOrientation="portrait"
            android:theme="@style/Theme.App.NewSplashScreenTheme">

But as for me - I highly recommend to use only one approach: new splash screen api or the old one. Because who knows how it will be behaving in future versions.

Also, I can recommend some links to read, which helped me to investigate it faster: https://developer.android.com/guide/topics/ui/splash-screen https://developer.android.com/guide/topics/ui/splash-screen/migrate

https://www.raywenderlich.com/32555180-splash-screen-tutorial-for-android https://itnext.io/a-comprehensive-guide-to-android-12s-splash-screen-api-644609c811fa https://habr.com/ru/post/648535/ https://medium.com/viithiisys/android-perfect-way-to-create-splash-screen-ca3c5bee137f https://proandroiddev.com/splash-screen-android-12-173c3c641671 https://medium.com/nerd-for-tech/modern-splash-screen-in-android-9c804903c7c9

I had this discussion (on Slack group 'Android Developers France') with a Google engineer working on the Android framework. He told me this is not a limitation but by design. Google designers wanted to unify the design and the transition between the OS and the application.

(here is the screenshot of his answer -in french- https://imgur.com/5lO17Nf)

He also stated that we could still code a custom animation with the splash screen to fade in the gradient tho.

Hope it helps.

Please create a drawable and declare your new drawable in style

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/splash_bg" />
 <item>
    <bitmap
        android:gravity="centre"
        android:src="@drawable/splash_logo" />
</item>
</layer-list>
Related