A peek inside Jetpack Core Splashscreen
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'
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
in your build.gradle. I didn't and faced an error like this one:
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.
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>
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.
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)
}
}
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()
}
}
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.