Create an Interactive Splash Screen in Flutter
Tags: flutter, android, beginners, tutorial
Published: 2021-05-30 12:41:58

Hi, I hope you all are doing great. In this tutorial I'll be sharing the technique I use to make a quick and interactive splash screen in flutter.

### Prerequisites
- Basic knowledge of flutter
- Basic knowledge of android

### Overview
In some cases we want to add an interactive splash screen to our app to prompt the user for different states, such as no internet connection. But just creating a splash widget may not be as satisfactory because flutter takes some time to draw its first frame when the app is launched. So today we'll be combining flutter splash screen with native android splash to get a quick and interactive splash screen.

### Let's Get Started

#### Flutter Side

1\. Create a new flutter project and open it in an IDE of your choice.

2\. Go to the pubspec.yaml file and specify the assets directory as following:
```yaml
flutter:
  # ... other properties here
  assets:
    - assets/images/
```
Also change the dart SDK version constraints to enable null safety:
```yaml
environment:
  sdk: ">=2.12.0 <3.0.0"
```

3\. Create a folder `assets` in the project root directory. And paste this [image](https://raw.githubusercontent.com/muiz6/flutter_interactive_splash/main/assets/images/logo_flutter.png) as "logo_flutter.png" in it.

4\. Create a new dart file "splash_page.dart" in the "lib" folder and paste the following code in it:
```dart
import 'package:flutter/material.dart';

class SplashPage extends StatefulWidget {
  @override
  _SplashPageState createState() => _SplashPageState();
}

class _SplashPageState extends State<SplashPage> {
  @override
  void initState() {
    WidgetsBinding.instance?.addPostFrameCallback((_) => _afterBuild(context));
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.white,
      child: Center(
        child: Image.asset('assets/images/logo_flutter.png'),
      ),
    );
  }

  void _afterBuild(BuildContext context) {
    showModalBottomSheet(
      context: context,
      isDismissible: false,
      enableDrag: false,
      barrierColor: Colors.transparent,
      backgroundColor: Colors.blue,
      shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.only(
        topLeft: const Radius.circular(25),
        topRight: const Radius.circular(25),
      )),
      builder: (builderContext) {
        return SizedBox(
          height: 100,
          child: Padding(
            padding: EdgeInsets.all(16),
            child: Center(
              child: ElevatedButton(
                style: ElevatedButton.styleFrom(
                  primary: Colors.white,
                  onPrimary: Colors.blue,
                ),
                onPressed: () => Navigator.pop(context),
                child: Text('Dismiss'),
              ),
            ),
          ),
        );
      },
    );
  }
}
```
In the above code, we schedule our `_afterBuild` method to be called after the `build` method, inside the `initState` callback. The `_afterBuild` method will display a modal bottom sheet after the splash page has been drawn. Which can be dismissed by pressing the dismiss button.

5\. Go to main.dart file and replace the existing code with following.
```dart
import 'package:flutter/material.dart';
import 'splash_page.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter App',
      debugShowCheckedModeBanner: false,
      home: SplashPage(),
    );
  }
}
```
The `SplashPage` widget has been passed as the `home` parameter, meaning flutter will show the `SplashPage` when our app is launched.

#### Android Side

6\. For the android side we will need to create resolution aware image assets for our splash logo. Open the [Image Baker](https://www.img-bak.in/) website in your browser. Drop the the "logo_flutter.png" image you downloaded earlier. The site will generate the assets for you. Go ahead and download them by clicking on the Android button.

7\. Extract the folder somewhere and you will find several drawable folders inside the extracted folder. These folders tell android which asset to use for different density displays. Copy all the drawable folders and paste them inside the `{your_project}/android/app/src/main/res` folder.

8\. Now we need to tell android to use our newly added asset. Open the "launch_background.xml" file in the "res/drawable" folder and replace the contents with following:
```xml
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@android:color/white" />

    <item>
        <bitmap
            android:gravity="center"
            android:src="@drawable/logo_flutter" />
    </item>
</layer-list>
```
Make sure you are using the correct drawable resource name. Flutter creates a drawable-v21 variant by default for "launch_background.xml". If you don't need it for anything else delete the drawable-v21 folder or the "launch_background.xml" in it.

9\. Now that we have added all the assets we need to make sure that the splash image size for our flutter splash and native android splash is the same. Open "logo_flutter.png" inside the res/drawable-xxxhdpi folder. Note the size of the image, we will need our flutter splash image to match the size of this image. 
> For xxxhdpi an image of 640px will be drawn as 1 inch on the device screen, while for flutter an image of 160 logical pixels will occupy 1 physical inch. 

So we can calculate the size needed for flutter splash with the following equation:
```
h = (height of the xxxhdpi image) / 640 * 160
```
Where `h` is the calculated height for the flutter splash image. Go to "splash_page.dart" and add the calculated height to the image.
```dart
@override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.white,
      child: Center(
        child: Image.asset(
          'assets/images/logo_flutter.png',
          height: 168.94,  // calculated height in my case
        ),
      ),
    );
  }
```

### Conclusion

And that's it we're done. Go ahead and run the application to watch your custom splash screen in action! Now we can discuss the pros and cons of this approach.

#### Pros
You get an instantaneous splash screen that is visible the moment your app launches. The splash becomes interactive when the flutter splash widget is drawn.

#### Cons
There is a slight blink when flutter draws its first frame. The lag is unacceptably long in development mode but it turns to only a slight blink in release mode. You can try to further optimize your flutter splash image by using [resolution aware image assets](https://flutter.dev/docs/development/ui/assets-and-images#resolution-aware).

---

That concludes this tutorial. I have hosted an example project on [GitHub](https://github.com/muiz6/flutter_interactive_splash/) for anyone who is interested. I can't wait to see your feedback in the comments below. I hope to see you folks next time with more interesting content.