Splash Screens in Flutter

Nikita Gandhi
The Startup
Published in
6 min readOct 27, 2020

They say, first impression is the last! Yep, truly for any amazingly crafted application, it’s easier to start impressing your audience with a good start — the splash screen! In this article, I will walk you through steps on how add splash screens to your Flutter application.

Splash screens are used to provide engagements with your user till the app loads. This allows your app to set the app engine and load app processes to initialise. You may keep your splash screen simple with some solid colors and text added or you might add some images with customised animations. Having splash screens with your app logo and version number helps to add wait time till your engine / app process is set to launch.

iOS Splash Screen

Install Xcode if you haven’t already. All apps submitted to the Apple’s App Store must use an Xcode storyboard to provide the app’s launch screen.
By default a blank image launch screen is added to your application which can be customised by you by adding your own assets. Find the default design at LaunchScreen.storyboard in your Xcode project.

To customise your splash screen, go to your project’s root directory. At the terminal type the following command : open ios/Runner.xcworkspace

Then select Runner/Assets.xcassets from the Project Navigator and drop in the desired images to the LaunchImage image set.

Android Start Screens

In Android there are two separate screens that you can control, Launch Screen when the app initialises and Splash Screen when Flutter experience initialises.
If you’re adding Flutter code to your existing Android project, consider to pre heat the Flutter engine to avoid load time and use the same Flutter engine throughout the app lifecycle to ensure minimum wait time to load the Flutter engine.

The two exceptions to using a cached FlutterEngine are:

  • When FlutterFragment is in the first Activity displayed by the app, because pre-warming a FlutterEngine would have no impact in this situation.
  • When you are unsure when/if you will need to display a Flutter experience.

The following illustrates how to pre-warm and cache a FlutterEngine:

// Create and pre-warm a FlutterEngine.
FlutterEngine flutterEngine = new FlutterEngine(context);
flutterEngine
.getDartExecutor()
.executeDartEntrypoint(DartEntrypoint.createDefault());
// Cache the pre-warmed FlutterEngine in the FlutterEngineCache.
FlutterEngineCache.getInstance().put("my_engine", flutterEngine);

Every app requires time to initialise while the OS sets the app to process. The concept of launch screen in Android helps to add a Drawable which can be added while the app is initialising.

For folks who don’t know what Drawable is : In Android, the concept of Drawable is for a graphic that can be drawn to the screen and which you can retrieve with APIs such as getDrawable(int) or apply to another XML resource with attributes such as android:drawable and android:icon. There are several different types of drawables. Read more here.

In a default Flutter project, the definition of launch theme and launch background is added by default. You can customise this based on your own needs. Go to styles.xml in your project where you can define the windowBackgroundwhich is set to the Drawable and is displayed as the launch screen.

<style name="LaunchTheme" parent="@android:style/Theme.Blue.NoTitleBar">
<item name="android:windowBackground">@drawable/launch_background</item>
</style>

In the code above, in the launch theme, a plain blue background is added.

<style name="NormalTheme" parent="@android:style/Theme.Blue.NoTitleBar">
<item name="android:windowBackground">@drawable/normal_background</item>
</style>

Normal theme defines the appearance of the screen as the Flutter engine starts. It appears for a very brief time and hence it’s recommended to add background color similar to the app theme to ensure the transition looks smooth.

Adding Flutter Activity in Android Manifest.xml

  1. In AndroidManifest.xml, set the theme of FlutterActivity to the launch theme.
  2. Then, add a <meta-data> element to the desired FlutterActivity to instruct Flutter to switch from the launch theme to the normal theme at the appropriate time.
<activity
android:name=".MyActivity"
android:theme="@style/LaunchTheme"
// ...
>
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>

The Android app now displays the desired launch screen while the app initializes.

How Flutter Splash Screen Works :

Every time a Flutter application is started, it takes some time to load the Dart isolate (which runs the code). This means user will see a blank screen till Flutter renders the first frame of the application.

To specify a splash screen for Flutter initialization, subclass FlutterActivity and override provideSplashScreen().
Flutter supports an improved user experience by displaying an Android View as a splash screen while Flutter initializes.

Flutter supports two options for a splash screen :
1. The first option is to display a Drawableof your choice, which fades out after the initialization is complete.

2. The other option is to provide a custom SplashScreen that is capable of displaying any Android View content that you want.

A Drawable splash screen can be configured for a FlutterActivity, FlutterFragment, or FlutterView.

For those who don’t know what is FlutterActivity : FlutterActivity is the simplest and most direct way to integrate Flutter within an Android app.

Alternatives to FlutterActivity

If Flutter is needed in a location that cannot use an Activity, consider using a FlutterFragment. Using a FlutterFragment requires forwarding some calls from an Activity to the FlutterFragment.

If Flutter is needed in a location that can only use a View, consider using a FlutterView. Using a FlutterView requires forwarding some calls from an Activity, as well as forwarding lifecycle calls from an Activity or a Fragment.

Inside your Flutter Activity

To display a Drawable as a Flutter splash screen in a FlutterActivity, add the following metadata to the associated FlutterActivity in AndroidManifest.xml :

<meta-data
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@drawable/my_splash"
/>

To display a splash screen with the same visual as a launch screen, reference the same @drawable/launch_background in the io.flutter.embedding.android.SplashScreenDrawable meta-data.

In a FlutterFragment

To display a Drawable as a Flutter splash screen in a FlutterFragment, make a subclass of FlutterFragment and override provideSplashScreen().

public class MyFlutterFragment extends FlutterFragment {
@Override
protected SplashScreen provideSplashScreen() {
// Load the splash Drawable.
Drawable splash = getResources().getDrawable(R.drawable.my_splash);

// Construct a DrawableSplashScreen with the loaded splash
// Drawable and return it.
return new DrawableSplashScreen(splash);
}
}

Creating a custom SplashScreen

Implement a custom splash View

First, define the custom View that should be displayed as the splash screen. This View could display anything, from a simple solid color to an animation.

Implement the SplashScreen interface

With a custom View defined, implement the SplashScreen interface.

This guide shows two approaches to a SplashScreen implementation. First, the following is an example of a SplashScreen that has no visual state and no transition animation.

public class SimpleScreen implements SplashScreen {
@Override
@Nullable
public View createSplashView(
@NonNull Context context,
@Nullable Bundle savedInstanceState
) {
// Return a new MySplashView without saving a reference, because it
// has no state that needs to be tracked or controlled.
return new MySplashView(context);
}
@Override
public void transitionToFlutter(@NonNull Runnable onTransitionComplete) {
// Immediately invoke onTransitionComplete because this SplashScreen
// doesn't display a transition animation.
//
// Every SplashScreen *MUST* invoke onTransitionComplete at some point
// for the splash system to work correctly.
onTransitionComplete.run();
}
}

We created an Android view which does not save instances of the application as no state of the application needs to be tracked or stored. The app does not display the transition animation where the app moves from splash screen to first Flutter frame. Once the app transition is complete, the app is set to run the processes.

The second example is a bit more sophisticated. In this example, the custom SplashScreen keeps a reference to its custom View and instructs the custom View to transition away, passing the onTransitionComplete callback to the custom View to invoke.

public class SplashScreenWithTransition implements SplashScreen {
private MySplashView mySplashView;
@Override
@Nullable
public View createSplashView(
@NonNull Context context,
@Nullable Bundle savedInstanceState
) {
// A reference to the MySplashView is retained so that it can be told
// to transition away at the appropriate time.
mySplashView = new MySplashView(context);
return mySplashView;
}
@Override
public void transitionToFlutter(@NonNull Runnable onTransitionComplete) {
// Instruct MySplashView to animate away in whatever manner it wants.
// The onTransitionComplete Runnable is passed to the MySplashView
// to be invoked when the transition animation is complete.
mySplashView.animateAway(onTransitionComplete);
}
}

In this example, reference to MySplashView is stored and once the transition of Drawable is complete, the app transitions to Flutter screen and the function mySplashView.animateAway() is evoked as soon as the transition is complete.

You can do a lot of experiments with custom splash screens. But use the power you have with responsibility: a splash screen that is too complex may frustrate your users by adding to your app’s load time.

There are instant plugins available with detailed instructions in case you wish to save time and use existing libraries. Explore more at Pub.Dev!

Thanks so much for reading my article till the end. It took me a long time since I last posted an article on Flutter with Firebase. I promise the next one is going to be quicker as I share tips on creating a responsive app in few easy steps. Till then happy coding with Flutter :-)

--

--

Nikita Gandhi
The Startup

Community Manager at Google Developers, Flutter Enthusiast