DEV Community

loading...
Cover image for A peek inside Jetpack Core Splashscreen

A peek inside Jetpack Core Splashscreen

Thomas Künneth
Developer. Speaker. Listener. Loves writing. GDE Android. Confessing mobile computing addict ;-)
・3 min read

Android 12 will introduce a new splashscreen api. I have written about it before it was officially announced. Beta 3 includes the final Android 12 APIs and the official SDK, so we devs can start using the new splashscreen api. But what about previous platforms? There is a new Jetpack component called Core Splashscreen, which...

provides backward compatibility for the new Splash Screen APIs.
This first alpha version contains all the new APIs backported
down to API 23, with the exception of the icon background.

Sounds cool, right?

Right.

So, let's take a look. At the time of writing the version of the lib is 1.0.0-alpha01, so there may be changes until it becomes stable. On the other hand, the platform apis are not complex. Tu use the lib in your apps, please add this dependency to your build.gradle:

implementation 'androidx.core:core-splashscreen:1.0.0-alpha01'
Enter fullscreen mode Exit fullscreen mode

A look inside the package

If we peek into package androidx.core.splashscreen we see two classes: SplashScreen and SplashScreenViewProvider. Before we turn to them, please make sure that you have set

android {
    compileSdk 31
Enter fullscreen mode Exit fullscreen mode

in your build.gradle. I didn't and faced an error like this one:

error: style attribute 'android:attr/windowSplashScreenAnimatedIcon' not found

We'll find out in a minute, what is going on there. If we set the correct compileSdk, we can build and run our app just fine. To actually see a splashscreen we however need to add a few things. Here's what the docs have to say.

A piece of the SplashScreen source code

So,

  • the theme of the starting activity must have R.style.Theme_SplashScreen as its parent
  • R.attr.windowSplashScreenAnimatedIcon must be set
  • R.attr.postSplashScreenTheme must be set

Your theme file might look like this (if you have one for dark mode be sure to apply all changes there, too):

<resources xmlns:tools="http://schemas.android.com/tools">
  <!-- Base application theme. -->
  <style name="Theme.JetpackSplashScreenDemo" parent="Theme.SplashScreen">
    <!-- Primary brand color. -->
    <item name="colorPrimary">@color/purple_500</item>
    <item name="colorPrimaryVariant">@color/purple_700</item>
    <item name="colorOnPrimary">@color/white</item>
    <!-- Secondary brand color. -->
    <item name="colorSecondary">@color/teal_200</item>
    <item name="colorSecondaryVariant">@color/teal_700</item>
    <item name="colorOnSecondary">@color/black</item>
    <!-- Status bar color. -->
    <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
    <!-- Customize your theme here. -->

    <item name="postSplashScreenTheme">@style/Theme.MaterialComponents.DayNight.DarkActionBar</item>
    <item name="windowSplashScreenAnimatedIcon">@mipmap/ic_launcher</item>

  </style>
</resources>
Enter fullscreen mode Exit fullscreen mode

If we now run the app, we still don't see the splashscreen. Instead, we get a java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity..

So, let's look further.

Portion of the SplashScreen source code

Turns out we just need to call installSplashScreen(). Please make sure you do so early enough (in any case prior to setContentView()).

class MainActivity : AppCompatActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    installSplashScreen()
    setContentView(R.layout.activity_main)
  }
}
Enter fullscreen mode Exit fullscreen mode

This way we get a nice splashscreen that is replaced by the app ui once it is ready. But there is more. With the new platform apis you can have cool exit animations. And with Core Splashscreen you can, too.

val splashScreen = installSplashScreen()
splashScreen.setOnExitAnimationListener { view ->
  view.iconView.let { icon ->
    val animator = ValueAnimator
      .ofInt(icon.height, 0)
      .setDuration(2000)
    animator.addUpdateListener {
      val value = it.animatedValue as Int
      icon.layoutParams.width = value
      icon.layoutParams.height = value
      icon.requestLayout()
      if (value == 0) {
        setContentView(R.layout.activity_main)
      }
    }
    val animationSet = AnimatorSet()
    animationSet.interpolator = AccelerateDecelerateInterpolator()
    animationSet.play(animator);
    animationSet.start()
  }
}
Enter fullscreen mode Exit fullscreen mode

The animation shrinks the app icon until it is completely gone. I tweeted about this back in May.

You may have spotted something weird. I invoke setContentView() when the animation is complete. This may look a little hacky. Especially, as there is setKeepVisibleCondition(). The docs say:

Sets the condition to keep the splash screen visible.

The splash will stay visible until the condition isn't met
anymore. The condition is evaluated before each request to draw
the application, so it needs to be fast to avoid blocking the
UI.

In theory I could return false once the animation is finished, but then I need to do a little more concurrency.

Here's how the animation looks like. Please note that the emulator is running Android 11. 😎

What do you think about Core Splashscreen? Please share your thoughts in the comments.


Source

Discussion (2)

Collapse
_azizbekian profile image
Andranik Azizbekian • Edited

Cool! Though couldn't watch the video, because it's private.

Collapse
tkuenneth profile image
Thomas Künneth Author

Thanks a lot. Regarding the video... Sorry to hear that. Should work now. Thanks for the heads up. 👍