Implementing Splash Screen in Flutter: The Complete Guide

In Flutter, a splash screen is the first screen users see when they launch your app. It’s a crucial element for providing initial branding and preparing your app’s resources in the background. A well-implemented splash screen creates a polished user experience and can improve app perception.

What is a Splash Screen?

A splash screen, also known as a launch screen, is a brief visual presented to the user while an application is loading or initializing. It typically displays a logo, branding, or loading animation to inform the user that the app is starting up.

Why Implement a Splash Screen?

  • Branding: Reinforces your app’s brand identity with a logo and color scheme.
  • User Experience: Provides immediate feedback, making the app feel responsive.
  • Loading Time: Masks initial loading processes, improving perceived performance.

Methods for Implementing a Splash Screen in Flutter

There are several ways to implement a splash screen in Flutter, each with its advantages. This guide covers native splash screens, using delays, and leveraging asynchronous tasks.

Method 1: Native Splash Screen (Recommended)

The most performant approach is to utilize the native splash screen provided by the underlying platform (Android/iOS). This ensures the splash screen is displayed almost instantly as the app launches.

Step 1: Add flutter_native_splash Dependency

Use the flutter_native_splash package, which simplifies the creation of native splash screens. Add it to your pubspec.yaml file:

dev_dependencies:
  flutter_native_splash: ^2.3.8  # Use the latest version
Step 2: Configure flutter_native_splash in pubspec.yaml

Define your splash screen configurations within the same pubspec.yaml file:

flutter_native_splash:
  color: "#FFFFFF" # Background color
  image: assets/splash.png # Splash image
  android_12:
    image: assets/splash_android12.png # Android 12 adaptive icon
  android: true
  ios: true

Customize the following:

  • color: Background color of the splash screen.
  • image: The path to your splash screen image asset.
  • android_12: Configuration options specifically for Android 12 adaptive icons.
  • android: Enable or disable the native splash screen on Android.
  • ios: Enable or disable the native splash screen on iOS.
Step 3: Generate the Native Splash Screen

Run the following command in your terminal to generate the native splash screens based on your configuration:

flutter pub get
flutter pub run flutter_native_splash:create

This command will automatically generate the required files for Android and iOS platforms.

Step 4: Implement Code to Hide Splash Screen

After generating the native splash screen, you’ll need to programmatically remove it when your app is ready. You can use the following code in your main.dart file within the initState of your initial screen or after asynchronous operations:

import 'package:flutter/material.dart';
import 'package:flutter_native_splash/flutter_native_splash.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Splash Screen Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State {
  @override
  void initState() {
    super.initState();
    initialization();
  }

  void initialization() async {
    // Simulate app initialization processes
    await Future.delayed(Duration(seconds: 3));
    FlutterNativeSplash.remove();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Home'),
      ),
      body: Center(
        child: Text('App is Ready!'),
      ),
    );
  }
}

Here’s what the code does:

  • In the main() function, we call WidgetsFlutterBinding.ensureInitialized().
  • In the initState() method, we invoke an asynchronous function initialization().
  • The initialization() function simulates app initialization processes (e.g., loading data) using Future.delayed().
  • Finally, we remove the native splash screen by calling FlutterNativeSplash.remove().

Method 2: Using a Delayed Splash Screen in Flutter

This method uses a Flutter Widget to show a splash screen and delays navigating to the main app screen using Future.delayed. While simple, it might be less performant than using the native splash screen for the initial load.

Step 1: Create a Splash Screen Widget

Design a simple splash screen UI as a Flutter Widget.

import 'package:flutter/material.dart';
import 'main.dart'; // Import your main app file

class SplashScreen extends StatefulWidget {
  @override
  _SplashScreenState createState() => _SplashScreenState();
}

class _SplashScreenState extends State {
  @override
  void initState() {
    super.initState();
    _navigateToMainScreen();
  }

  _navigateToMainScreen() async {
    await Future.delayed(Duration(seconds: 3), () {
      Navigator.pushReplacement(
        context,
        MaterialPageRoute(builder: (context) => MyHomePage()),
      );
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.blue,
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Image.asset('assets/splash.png', width: 150, height: 150), // Your logo
            SizedBox(height: 20),
            Text(
              'My Awesome App',
              style: TextStyle(fontSize: 24, color: Colors.white),
            ),
          ],
        ),
      ),
    );
  }
}

In this Widget:

  • Image.asset('assets/splash.png') displays a logo image.
  • Future.delayed is used to delay navigation to the main screen.
  • Navigator.pushReplacement replaces the splash screen with the main app screen to prevent users from navigating back to the splash screen.
Step 2: Set the Splash Screen as the Initial Route

In your main.dart file, set the SplashScreen as the initial route for your app:

import 'package:flutter/material.dart';
import 'splash_screen.dart'; // Import your splash screen file
import 'home_page.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Splash Screen Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: SplashScreen(), // Set SplashScreen as the initial route
    );
  }
}

In this code, the home property of MaterialApp is set to SplashScreen(), making it the first screen displayed when the app starts.

Method 3: Loading Data Asynchronously in Splash Screen

For loading initial data or performing asynchronous operations, a splash screen can be combined with a FutureBuilder. This approach ensures that data is loaded before displaying the main UI.

Step 1: Create a Splash Screen with Data Loading

Design a splash screen that performs an asynchronous task while it is visible. Use FutureBuilder to listen for the completion of this task.

import 'package:flutter/material.dart';

import 'home_page.dart';
import 'main.dart'; // Import your main app file

class SplashScreen extends StatefulWidget {
  @override
  _SplashScreenState createState() => _SplashScreenState();
}

class _SplashScreenState extends State {

  Future _loadData() async {
    // Simulate loading data or any other async operation
    await Future.delayed(Duration(seconds: 3));
    // Here you might load configuration data, authenticate user, etc.
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.blue,
      body: FutureBuilder(
        future: _loadData(),
        builder: (BuildContext context, AsyncSnapshot snapshot) {
          if (snapshot.connectionState == ConnectionState.done) {
            // Once data loading is done, navigate to the main screen
            return MyHomePage(); // Or navigate to your main screen widget
          } else {
            // While loading data, show the splash screen UI
            return Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Image.asset('assets/splash.png', width: 150, height: 150), // Your logo
                  SizedBox(height: 20),
                  Text(
                    'Loading App...',
                    style: TextStyle(fontSize: 24, color: Colors.white),
                  ),
                  SizedBox(height: 20),
                  CircularProgressIndicator(valueColor: AlwaysStoppedAnimation(Colors.white)),
                ],
              ),
            );
          }
        },
      ),
    );
  }
}

Key aspects of this code:

  • _loadData(): Asynchronously loads necessary data and configures the app.
  • FutureBuilder: Displays a loading UI while _loadData is running, and navigates to the main screen once loading is complete.
Step 2: Setting Up as the Initial Route

Set the SplashScreen as the initial route as before:

import 'package:flutter/material.dart';
import 'splash_screen.dart';
import 'home_page.dart'; // Import your main app file

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Splash Screen Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: SplashScreen(), // Set SplashScreen as the initial route
    );
  }
}

Best Practices for Splash Screens

  • Keep it Short: Splash screens should ideally last no more than 2-3 seconds to avoid frustrating users.
  • Native Implementation: Utilize the native splash screen for the best performance.
  • Optimize Images: Ensure splash screen images are properly sized and optimized to reduce load times.
  • Branding Consistency: Maintain consistent branding with your app’s overall theme.

Conclusion

Implementing a splash screen in Flutter enhances the user experience by providing immediate visual feedback and branding reinforcement while your app initializes in the background. The native splash screen approach (using flutter_native_splash) is recommended for optimal performance and a seamless loading experience. By following this guide, you can effectively implement splash screens that improve the initial perception and user satisfaction of your Flutter applications.