Android 12. Splash Screen API. Making an animated loading screen

Hello everyone!

A splash screen (also known as a loading screen) is an integral part of an application when it grows so large that a cold start takes some appreciable time. Until a recent update, splash screen was implemented in two main ways:

  1. Via theme attribute windowBackground

  2. Through a separate Activity

The first approach is more optimal, because does not spend extra resources on creating and manipulating a separate activity. However, with the first approach, there is no way to use animations – a picture placed in windowBackground, must be static.

To help us with the release of Android 12, developers have provided a new API for creating splash screens.

In this article, I will not retell the official documentation on creating a new splash screen (which can be found here), but I will tell you what difficulties and pitfalls that are not described in the official doc, we encountered when creating an animated loading screen in our BestDoctor application.

Expected Result

At the start of the application, we have a small loading of the initial data, so at the same time the splash screen function should also be a loading indication. The good old spinner (or loading indicator) is best suited for this. To do this, it is most convenient to spin the BestDoctor logo (known among the company’s employees as the AGGRESSIVE BLOODY Hedgehog).

This is the splash screen we want to get as a result:

Getting Started

Following the official doc, there are two ways to implement a new splash screen:

  1. Through attributes of the application’s general theme

  2. Across compat library

The difference between these two methods is that the first one only works for Android 12+, while the second one will do the same splash screen for older versions.

IMPORTANT: animated image can be used only on Android 12+ i.e. even when using the compat library on previous versions, there will still be a static picture.

Because our splash screen should replace the loading indication, animation is critical for us, so we will implement the splash screen through the attributes of the general theme only for Android 12+; for older versions, we will leave our old splash.
Let’s get started.

Let’s start with a static image with a background. We add the necessary attributes to the application theme.

<item name="android:windowSplashScreenBackground">@color/splashscreen_background</item>
<item name="android:windowSplashScreenAnimatedIcon">@drawable/ic_splashscreen_logo</item>

We use the BestDoctor vector logo as a picture:

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="32dp"
    android:height="33dp"
    android:viewportWidth="32"
    android:viewportHeight="33">
    <path
        android:fillColor="@color/coral30"
        android:pathData="M32,18.3662H21.7073C21.2638,18.3662 21.042,18.9013 21.3551,19.2145L28.6343,26.4967L25.9992,29.133L18.733,21.8638C18.4199,21.5506 17.885,21.7724 17.885,22.2162V32.5H14.1541V22.2162C14.1541,21.7724 13.6192,21.5506 13.3062,21.8638L6.0008,29.146L3.3657,26.5098L10.6449,19.2276C10.958,18.9144 10.7362,18.3793 10.2927,18.3793H0V14.6468H10.2927C10.7362,14.6468 10.958,14.1117 10.6449,13.7985L3.3657,6.5033L6.0008,3.867L13.267,11.1362C13.5801,11.4494 14.115,11.2276 14.115,10.7839V0.5H17.8459V10.7839C17.8459,11.2276 18.3808,11.4494 18.6938,11.1362L25.96,3.867L28.6343,6.5033L21.3551,13.7855C21.042,14.0987 21.2638,14.6338 21.7073,14.6338H32V18.3662Z" />
</vector>

We run the application and get this crap:

The logo somehow stretched incomprehensibly, this does not suit us. We begin to understand the problem.

Go to section of official documentation on image size and find this text:

The splash screen icon uses the same specifications as adaptive icons, as follows:

* Branded image: This should be 200×80 dp.
* App icon with an icon background: This should be 240×240 dp, and fit within a circle of 160 dp in diameter.
* App icon without an icon background: This should be 288×288 dp, and fit within a circle of 192 dp in diameter.

For example, if the full size of an image is 300×300 dp, the icon needs to fit within a circle with a diameter of 200 dp. Everything outside the circle will be invisible (masked).

What does all this mean:
In Android 12, when you launch an app, the default splash screen is the app icon. Actually, for the picture that we want to use explicitly, the same specifications are used as for adaptive icons. We are using an image without a background (without a background of the image, not the screen itself), so, judging by the dock, our image should be 192×192 dp in size. OK. Let’s update our vector by setting the attributes viewportWidth and viewportHeight. We will also have to wrap our entire vector in group and add translateto enlarge viewport be placed in the center.
We get:

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="32dp"
    android:height="33dp"
    android:viewportWidth="192"
    android:viewportHeight="192">
    <group
        android:translateX="80"
        android:translateY="79.5">
        <path
            android:fillColor="@color/coral30"
            android:pathData="M32,18.3662H21.7073C21.2638,18.3662 21.042,18.9013 21.3551,19.2145L28.6343,26.4967L25.9992,29.133L18.733,21.8638C18.4199,21.5506 17.885,21.7724 17.885,22.2162V32.5H14.1541V22.2162C14.1541,21.7724 13.6192,21.5506 13.3062,21.8638L6.0008,29.146L3.3657,26.5098L10.6449,19.2276C10.958,18.9144 10.7362,18.3793 10.2927,18.3793H0V14.6468H10.2927C10.7362,14.6468 10.958,14.1117 10.6449,13.7985L3.3657,6.5033L6.0008,3.867L13.267,11.1362C13.5801,11.4494 14.115,11.2276 14.115,10.7839V0.5H17.8459V10.7839C17.8459,11.2276 18.3808,11.4494 18.6938,11.1362L25.96,3.867L28.6343,6.5033L21.3551,13.7855C21.042,14.0987 21.2638,14.6338 21.7073,14.6338H32V18.3662Z" />
    </group>
</vector>

We start the application:

Hooray! The picture is no longer smeared, the size is correct. We move on.

Twist Animation

The Splash Screen API supports the use of AnimationDrawable and AnimatedVectorDrawable – let’s take advantage of this opportunity!

  1. Let’s make changes to the code of our vector: add the attributes name (group identifier of our vector, needed to access it) and pivotX, pivotY (coordinates of the pivot point, in our case, the center of the picture).

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="32dp"
    android:height="33dp"
    android:viewportWidth="192"
    android:viewportHeight="192">
    <group
        android:name="logoGroup"
        android:pivotX="16"
        android:pivotY="16.5"
        android:rotation="0"
        android:translateX="80"
        android:translateY="79.5">
        <path
            android:fillColor="@color/coral30"
            android:pathData="M32,18.3662H21.7073C21.2638,18.3662 21.042,18.9013 21.3551,19.2145L28.6343,26.4967L25.9992,29.133L18.733,21.8638C18.4199,21.5506 17.885,21.7724 17.885,22.2162V32.5H14.1541V22.2162C14.1541,21.7724 13.6192,21.5506 13.3062,21.8638L6.0008,29.146L3.3657,26.5098L10.6449,19.2276C10.958,18.9144 10.7362,18.3793 10.2927,18.3793H0V14.6468H10.2927C10.7362,14.6468 10.958,14.1117 10.6449,13.7985L3.3657,6.5033L6.0008,3.867L13.267,11.1362C13.5801,11.4494 14.115,11.2276 14.115,10.7839V0.5H17.8459V10.7839C17.8459,11.2276 18.3808,11.4494 18.6938,11.1362L25.96,3.867L28.6343,6.5033L21.3551,13.7855C21.042,14.0987 21.2638,14.6338 21.7073,14.6338H32V18.3662Z" />
    </group>
</vector>
  1. V res/animator add spin animator:

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1500"
    android:interpolator="@android:anim/linear_interpolator"
    android:propertyName="rotation"
    android:repeatCount="-1"
    android:repeatMode="restart"
    android:valueFrom="0"
    android:valueTo="360" />

Please note that here duration="1500" (the time it takes for a picture to complete a full 360 degree rotation) repeatCount="-1" (an infinite repetition of the animation), we will return to this later.

  1. V res/drawable add ic_splashscreen_logo_animated. V target.name specify the name of the group in which it is wrapped path our entire vector.

<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/ic_splashscreen_logo">
    <target
        android:name="logoGroup"
        android:animation="@animator/splashscreen_animator" />
</animated-vector>
  1. And finally, add the necessary theme attributes (replacing the link from a regular icon to an animated one):

<item name="android:windowSplashScreenBackground">@color/splashscreen_background</item>
<item name="android:windowSplashScreenAnimatedIcon">@drawable/ic_splashscreen_logo_animated</item>
<item name="android:windowSplashScreenAnimationDuration">1500</item>

Please note that in windowSplashScreenAnimationDuration the same 1500 are indicated as in animator, i.e. we want the logo to make one full rotation every 1500 milliseconds.
Run and get this:

Hmmm… Problem: the logo makes one revolution and stops, although we have not finished loading yet.

The theme attributes are missing something responsible for repeating the animation, although our animator is set to repeatCount="-1". Well, let’s fix it with a daring hack.

  1. In animator we leave the desired time for one animation cycle.

  2. V windowSplashScreenAnimationDuration instead of the time of one animation cycle, we substitute Integer.MAX_VALUE, which is 2147483647. If the download does not take 25 days, then users will never notice that the animation has ended.

The updated theme attributes look like this:

<item name="android:windowSplashScreenBackground">@color/splashscreen_background</item>
<item name="android:windowSplashScreenAnimatedIcon">@drawable/ic_splashscreen_logo_animated</item>
<item name="android:windowSplashScreenAnimationDuration">2147483647</item>

Run and get the expected result, hooray!

Branding

Of course, we want users to know which company they use, so we’ll add branding to the splash screen. This feature is also provided in the new API.

Add the desired theme attribute with a vector image:

<item name="android:windowSplashScreenBrandingImage">@drawable/ic_splashscreen_branding</item>

We run and get this mess:

After some googling, I found an easy workaround for this problem:

  1. V res/drawable add ic_splashscreen_branding_centered:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:drawable="@drawable/ic_splashscreen_branding"
        android:gravity="center" />
</layer-list>
  1. Change the link to the centered image in the topic:

<item name="android:windowSplashScreenBrandingImage">@drawable/ic_splashscreen_branding_centered</item>

Voila: the picture is back to normal 🙂

Well, here we have the expected result! We keep such a splash screen on the screen until the end of the initial data loading. How to do this is described in official dock.

Thank you very much for your attention!

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *