[Flutter] Removing the Default White Flash with flutter_native_splash

When you launch a Flutter app, you might notice a brief white flash before your custom splash screen appears. This is the native splash screen displayed by the OS while the Flutter engine is loading. Its default is white, so it stands out.

This post covers how to change that screen with the flutter_native_splash package.


Why Do You See a White Screen?

The startup flow of a Flutter app is as follows:

TEXT
App Launch → [Native Splash] → Flutter Engine Loading → [Flutter Widget Rendering]

Because Dart code cannot run before the Flutter engine is loaded, the OS displays a static screen at the native level. This corresponds to launch_background.xml on Android and LaunchScreen.storyboard on iOS.

If your custom splash screen is dark, the transition from White → Custom Splash becomes very noticeable.


Solution

1. Install the Package

Bash
flutter pub add flutter_native_splash

2. Configure pubspec.yaml

Add the configuration to pubspec.yaml. You can also put it in a separate flutter_native_splash.yaml file at the project root.

YAML
flutter_native_splash:
  color: "#009CCC"              # Background color (matching your splash screen)
  image: assets/images/logo.png # Logo to display in the center (optional)
  android: true
  ios: true

  # Android 12+ ignores the settings above, so configure it separately
  android_12:
    color: "#009CCC"
    image: assets/images/logo.png  # clipped to a circle in the center

flutter:
  uses-material-design: true
  # ...

Tip: If your custom splash uses a gradient, set the mid-tone color as the background color for a smoother transition. To use the gradient itself, put a gradient image in background_image instead of color (not on Android 12+).

3. Generate the Native Splash

Bash
dart run flutter_native_splash:create

This command modifies the following native files:

  • Android: launch_background.xml, styles.xml
  • iOS: LaunchScreen.storyboard, Assets.xcassets

4. Modify main.dart - Preserve Splash

By default, the native splash is removed when Flutter draws its first frame. Calling preserve() keeps the native splash visible until you call remove().

Dart
import 'package:flutter_native_splash/flutter_native_splash.dart';

Future<void> main() async {
  // Prepare Flutter bindings + Preserve native splash
  WidgetsBinding widgetsBinding = WidgetsFlutterBinding.ensureInitialized();
  FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);

  // Initialize Firebase, SDKs, etc.
  await Firebase.initializeApp();

  runApp(MyApp());
}

5. Remove in the Splash Screen

Remove the native splash in the initState() of your custom Flutter splash widget.

Dart
import 'package:flutter_native_splash/flutter_native_splash.dart';

class _SplashScreenState extends State<SplashScreen> {
  
  void initState() {
    super.initState();

    // Remove native splash → Flutter splash becomes visible
    FlutterNativeSplash.remove();

    // Business logic like server checks or authentication...
    _checkServerAndAuth();
  }
}

Final Execution Flow

  1. App Launch
  2. Native Splash (#009CCC + Logo) ← Instead of the white screen!
  3. Flutter Engine Loading (Native splash persists)
  4. Flutter Splash Widget initState() executes
  5. FlutterNativeSplash.remove() is called
  6. Custom Splash (Gradients + Animations)
  7. Main Screen

Native Splash vs. Flutter Splash

FeatureNative SplashFlutter Splash
Execution TimingBefore engine loadsAfter engine loads
ImplementationOS Level (XML, Storyboard)Dart Widgets
GradientsOnly via a background image (not on Android 12+)Supported
AnimationsNot supportedSupported
Business LogicNot possiblePossible (API calls, Auth)
Custom FontsNot supportedSupported

Important Considerations

  • Gradients: Use a gradient image in background_image. Android 12+ doesn't support background images, so only solid colors work there.
  • Android 12+: Configure the android_12 section separately. The logo is clipped to a circle in the center of the screen.
  • Mandatory Removal: You must call remove() after preserve(), otherwise the splash screen stays on screen.
  • No Dart Logic: Native splashes cannot execute Dart code like server checks.
  • Apply Changes: You must re-run dart run flutter_native_splash:create every time you modify the configuration.
  • iOS Cache: Changes might not appear on iOS due to caching. The package README suggests uninstalling the app, restarting the device, and reinstalling.

Summary

flutter_native_splash changes the native splash background, and if needed, two calls control when it stays and when it goes:

Dart
// 1. Preserve in main()
FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);

// 2. Remove in the splash screen widget
FlutterNativeSplash.remove();