Splash Screen in Android

Suson Thapa
The Startup
Published in
8 min readSep 18, 2020

--

Photo by Stanislav Kondratiev on Unsplash

In any mobile app, Splash Screen is the first thing that the user will see. Despite this I have seen many developers implement splash screen with a fixed timeout, making the users of their app wait even though the app is not doing any initialization.

Let’s think about this, suppose you use 2 seconds of delay for splash screen and users open your app about 15 times (just imagine) a day. Then you are wasting 30 seconds a day for each user. That’s roughly 3 hours per year. In short you are taking away 2 moves per year from each user. Well, that’s a lot of movies.

Back to our topic. In my opinion, splash screen should represent your app initialization and not your content initialization. What I mean is that, the splash screen should be visible only during the time the system initializes your app. After your app is initialized you can use various UI like progress bar to reflect your content loading.

Well, how do you show splash screen without initializing it. Splash screen is typically implemented using a normal activity but with one important difference. One of the expensive process in android is layout inflation and this process runs on the main thread. This is the reason for the initial black/white screen in apps before the content is shown. So, what we are trying to achieve is to show some UI without inflating xml file. Is that even possible?

For those in hurry, here is the link to the github repository. Each branch in the repository contains different approaches described here.

Themes

Here comes the important part. Every activity in android has a theme (even if you don’t explicitly set the theme, the platform will provide a default one) and this is one of the first thing that is initialized even before inflating the layout. This makes sense as we need theme to inflate a xml layout as it references various attributes from theme. So, the trick here is to use theme to set some kind of background to the splash activity instead of inflating the layout. Let’s discuss common approach of implementing splash screen.

For the sake of demonstration let’s simulate some heavy layout in MainActivity by doing just math computation like this.

1. Without splash screen

If you start your MainActivity as usual without any splash screen then you will be greeted with a brief black/white screen before your app starts like shown below. I think this a bad user experience and depending on your layout complexity and whether your app process is cached or not(cold start) this black/white screen may last from few milliseconds to multiple seconds.

Here is the link to the branch in github repository.

2. Splash screen with fixed timeout

This is one of the worst implementation. I think it is worse than not using splash screen. Along with the black/white screen during the initial startup, you are adding fixed timeout making the matter worse. Here is a sample of SplashActivity.

The user will have to wait 2 seconds every time they open your app. I think it’s better not to use the splash screen at all like in Option 1 instead of this.

Here is the link to branch in github repository.

3. Splash screen with xml layout

You might want to create a fancy splash screen with various images and app branding. If you create an xml layout and use in the SplashActivity then most of the time the layout may not be visible (depending in the complexity of MainActivity) as we will be starting another activity in the onCreate()function. This method will only make sense if your initialization code is heavy (just make sure to initialize in some background thread). Although you might see the white/black screen for shorter time as splash activity is relatively simple and will be inflated quickly.

Keep in mind that if your initialization code is in MainActivity and SplashActivity only contains code to start the MainActivity then most of the time the splash UI won’t be shown and even if it is shown it will be more like a flicker.

This approach will be same as Option 1.

If your splash activity contains logic like checking internet connection or doing some setup, then the splash screen UI might be visible depending on the time taken by your initialization code.

For above code, the splash screen will be visible as shown below. But it still shows the initial blank white/black screen.

Here is the link to the branch in github repository.

4. Splash screen using themes only

This is the most efficient approach as it doesn’t require any layout inflation and theme is generally initialized at the early stage of application launch. So, the users will see the splash screen as soon as they tap the launcher icon.

For this just add a new theme in your styles.xml and set the attribute windowBackground to your drawable (normally your app logo).

The splash drawable is defined using layer-list .

After that set the theme to your SplashActivity in the AndroidManifest.xml file.

Remember not to inflate the layout file in onCreate() of the SplashActivity . You can also remove the layout file for SplashActivity if you are not going to use it.

This is how it looks. Not bad. Here is the link to branch in github repository.

If this is the only code in you SplashActivity, then you can totally remove this activity and instead set the theme of the MainActivity to SplashTheme and then in onCreate() switch the theme back to the your AppTheme before calling super.onCreate(). It totally depends on you but for most apps with dynamic start destination(like in case of login), having separate splash activity doesn’t hurt.

As you can see below the result is actually the same as using SplashActivity but with one less activity to worry about.

Until now I have tested all these splash screen techniques on Android P. But let’s not forget there are older devices as well. Let’s see how this looks in Android lollypop.

Well that doesn’t look good, the whole icon is stretched. Let’s fix that, we need to create separate versions of splash screen for devices below API level 23. The reason is drawable doesn’t support height and width below API 23 and will cause our drawable to scale and take full available size, which we don’t want.

Create drawable-v23 under res folder and move our splash.xml file there. And add a new splash.xml file in drawable folder and use <bitmap> to set the background.

You might be tempted to use the same splash screen using bitmap for both devices below API 23 and above. But keep in mind that android uses adaptive icons for devices above API 26 so this will result in app crashing as bitmap cannot handle adaptive icons.

That looks pretty good to me. One important thing to keep in mind is to always test you app for different android versions. Here is the link to the branch in github repository.

5. Splash screen using both layout and theme

This is also another approach if you want to have some initialization in the SplashActivity. First the theme will display the background and after the layout of SplashActivity is inflated it will override the background.

As you can see the icon of the theme and the icon in our SplashActivity is overlapping and doesn’t look nice. We can quickly fix that by setting the background of our SplashActivity to white but the icon will still shift as shown below.

We can do better than that, right?

The problem I think is that we are using NoActionBar theme in SplashActivity that causes the icon in the xml layout to position itself with the top of the screen. We can fix that by adding margin at top equal to the height of the status bar.

Well that’s how it looks now

That’s looks pretty good. Here is the link to the branch in github repository.

What about animations?

You can define animations with AnimatedVectorDrawables but keep in mind that setting this drawable to windowBackground in theme doesn’t start the animation. So we will need a xml layout for SplashActivity and start animation there.

This code is same as above with one difference, we get the current drawable from ImageView which is AnimatedVectorDrawable and call it’s start method.

Here is the link to the branch in github repository.

It would be pretty nice if the AnimatedVectorDrawables could start its animation on its own.

It can now be done with custom drawables starting with API 24 (Thanks Xzaninou for helping me out, link to reddit thread).

For API 24 and above we can now use custom drawable and animate it without using layout in SplashActivity. First define a custom drawable that will wrap the AnimatedVectorDrawable.

Then create drawable-v24 folder and create splash_drawable.xml file for our custom drawable.

Then in onCreate() of SplashActivity check the version and for devices running below API 24 use our previous approach of using xml layout to animate.

This is how it looks in Android P with AnimatedVectorDrawable applied to theme.

This is how it looks in Android L with AnimatedVectorDrawable used with xml layout.

Not bad, there is some stutter during the end of the animation. It might be due to the AnimatedVectorDrawable running on MainThread before API 25 as mentioned in this documentation. This story is already getting too long. We will try to fix that later.

Here is the link to the branch in github repository.

So, that’s it for this story. All the above approaches can be found in separate branch in the github repository. Hope you enjoy it.

--

--

Suson Thapa
The Startup

Android | iOS | Flutter | ReactNative — Passionate Software Engineer