How to Implement a Splash Screen in Flutter: Native Android and iOS Setup Guide

To add a splash screen in Flutter, you must configure native platform resources—XML layouts on Android and storyboards on iOS—because the Flutter engine renders its UI only after the Dart runtime initializes.

When working with the flutter/flutter repository, implementing a splash screen requires a two-phase approach. Since the Flutter framework cannot display widgets until the engine fully boots, the initial visual feedback must be handled by the native Android and iOS embedding layers. This guide covers the specific source files and implementation patterns used by the Flutter SDK to deliver seamless launch experiences.

Architecture of Splash Screens in Flutter

The Flutter engine initializes asynchronously after the user taps your app icon. During this gap, the operating system displays a native view controlled by the platform project, not Dart code. The Flutter SDK provides default templates for these native screens in the flutter_tools package, specifically within packages/flutter_tools/templates/app/android/ and packages/flutter_tools/templates/app/ios/.

Once the engine is ready, you may optionally transition to a Flutter-based splash screen to perform additional initialization logic, such as loading configuration or authenticating users.

Android Splash Screen Implementation

On Android, the splash screen is defined by a combination of drawable resources and layout XML files. The default template provided by Flutter resides at packages/flutter_tools/templates/app/android/app/src/main/res/layout/launch_screen.xml.

Modifying the Launch Background

Create or edit android/app/src/main/res/layout/launch_screen.xml to reference your branding assets:

<!-- android/app/src/main/res/layout/launch_screen.xml -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:drawable="@color/white"/>
  <item>
    <bitmap
        android:gravity="center"
        android:src="@drawable/your_logo"/>
  </item>
</layer-list>

Place your logo image in android/app/src/main/res/drawable/ (or drawable-v21/ for API level 21+ specific implementations). The launch_background.xml file in packages/flutter_tools/templates/app/android/app/src/main/res/drawable/ serves as the base template for this drawable.

iOS Splash Screen Implementation

For iOS, the launch interface is defined by a storyboard file. The Flutter SDK template is located at packages/flutter_tools/templates/app/ios/Runner/Base.lproj/LaunchScreen.storyboard.

Configuring the LaunchScreen.storyboard

Open ios/Runner/Base.lproj/LaunchScreen.storyboard in Xcode and replace the placeholder image view with your own logo. You can also edit the XML directly if managing the file through version control:

<viewController id="01J-lp-oVM" ...>
  <view ...>
    <imageView ... image="LaunchImage"/>
  </view>
</viewController>

Add your logo to the Xcode asset catalog (Assets.xcassets) and reference it in the storyboard’s image view. This storyboard displays immediately upon app launch and persists until the Flutter engine renders its first frame.

Extending with a Flutter-Based Splash Screen

After the native splash dismisses, you can display a Flutter widget to handle asynchronous initialization. This pattern uses WidgetsFlutterBinding.ensureInitialized(), defined in packages/flutter/lib/src/widgets/binding.dart, to guarantee the Flutter binding is ready before running UI code.

Implementing the Secondary Splash in Dart

Update your main.dart to show a splash widget while loading resources:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: const SplashScreen(),
    );
  }
}

class SplashScreen extends StatefulWidget {
  const SplashScreen({super.key});
  
  @override
  State<SplashScreen> createState() => _SplashScreenState();
}

class _SplashScreenState extends State<SplashScreen> {
  @override
  void initState() {
    super.initState();
    _initialize();
  }

  Future<void> _initialize() async {
    await Future.delayed(const Duration(seconds: 2)); // simulate network/auth
    if (!mounted) return;
    Navigator.of(context).pushReplacement(
      MaterialPageRoute(builder: (_) => const HomePage()),
    );
  }

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      backgroundColor: Colors.white,
      body: Center(
        child: Image.asset('assets/logo.png'),
      ),
    );
  }
}

Declaring Assets

Ensure your logo is available to Flutter by updating pubspec.yaml:

flutter:
  assets:
    - assets/logo.png

Run flutter build apk or flutter build ios to compile the app with both native and Flutter splash configurations.

Summary

  • Native resources are mandatory: Because the Dart VM initializes after app launch, Android requires launch_screen.xml in res/layout/ and iOS requires LaunchScreen.storyboard to provide immediate visual feedback.
  • Use lightweight native assets: Keep platform splash screens simple—avoid heavy logic or animations that delay engine startup.
  • Leverage WidgetsFlutterBinding: Call WidgetsFlutterBinding.ensureInitialized() before runApp() to safely display a secondary Flutter splash for async initialization tasks.
  • Template files live in flutter_tools: The default implementations are found at packages/flutter_tools/templates/app/android/ and packages/flutter_tools/templates/app/ios/ within the Flutter SDK.

Frequently Asked Questions

Can I create a splash screen using only Flutter widgets?

No. Because the Flutter engine requires time to initialize the Dart runtime, the operating system displays a native view first. You must configure platform-specific resources—Android XML layouts and iOS storyboards—to cover the gap between app launch and engine readiness.

Where does Flutter store the default native splash templates?

The Flutter SDK includes default templates in the flutter_tools package. Key files include packages/flutter_tools/templates/app/android/app/src/main/res/layout/launch_screen.xml for Android and packages/flutter_tools/templates/app/ios/Runner/Base.lproj/LaunchScreen.storyboard for iOS.

How do I ensure the native splash matches my Flutter theme?

Align the background colors and logo assets between your native configuration and Flutter widgets. Use identical hex color values in android/app/src/main/res/values/colors.xml and your Flutter ThemeData, and ensure the logo image used in the native splash is visually consistent with the one loaded by Flutter in your Dart code.

Is there a performance impact to showing a Flutter splash after the native one?

Minimal. The transition from native to Flutter view occurs after the engine is fully initialized. As long as your Flutter splash screen performs only necessary async work (such as checking authentication status or loading cached data) and avoids heavy computations, users will experience a seamless visual transition.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →