Auth & Onboarding

Splash Screen

A clean animated splash screen that fades the app logo in, slides the wordmark up, and auto-navigates to the next screen after a short delay — all driven by a single AnimationController with staggered Interval curves. The perfect first frame for any Flutter app while it boots, checks auth, or loads config.

onboardinganimationnavigation
9:41
FlutterKit

WHAT'S INCLUDED

  • Single AnimationController driving a staggered logo fade and text slide-up
  • Interval curves so the logo settles before the wordmark animates in
  • Auto-navigation to a configurable nextScreen via pushReplacement after the delay
  • Brand-colored full-bleed background with a rounded logo mark
  • mounted guard before navigating so it is safe to dispose mid-animation
  • Fully self-contained — pass any widget as the destination screen

USE CASES

  • App launch screen shown while Firebase or Supabase initializes
  • Auth gate that decides between the login screen and the home screen
  • Branding moment before onboarding on a fresh install
  • Loading screen while remote config or feature flags are fetched

PRO TIP

Do real startup work — auth check, remote config, cached-session read — inside initState and navigate when both the animation and the work have finished, rather than relying on a fixed Future.delayed. A hardcoded delay either feels slow on fast devices or cuts off work on slow ones; gating navigation on Future.wait of [animation, bootstrap] is smoother.

Complete Dart Code

Copy this entire snippet into your Flutter project. No external packages required.

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

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        backgroundColor: Colors.white,
        body: Center(
          child: SplashScreen(
            nextScreen: Scaffold(
              backgroundColor: Colors.white,
              body: Center(child: Text('Welcome!')),
            ),
          ),
        ),
      ),
    );
  }
}

class SplashScreen extends StatefulWidget {
  final Widget nextScreen;
  const SplashScreen({super.key, required this.nextScreen});

  @override
  State<SplashScreen> createState() => _SplashScreenState();
}

class _SplashScreenState extends State<SplashScreen>
    with SingleTickerProviderStateMixin {
  late final AnimationController _controller;
  late final Animation<double> _logoFade;
  late final Animation<Offset> _textSlide;
  late final Animation<double> _textFade;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 1400),
    );
    _logoFade = CurvedAnimation(
      parent: _controller,
      curve: const Interval(0.0, 0.6, curve: Curves.easeOut),
    );
    _textFade = CurvedAnimation(
      parent: _controller,
      curve: const Interval(0.4, 1.0, curve: Curves.easeOut),
    );
    _textSlide = Tween<Offset>(
      begin: const Offset(0, 0.4),
      end: Offset.zero,
    ).animate(CurvedAnimation(
      parent: _controller,
      curve: const Interval(0.4, 1.0, curve: Curves.easeOutCubic),
    ));

    _controller.forward();

    Future.delayed(const Duration(milliseconds: 2500), () {
      if (!mounted) return;
      Navigator.of(context).pushReplacement(
        MaterialPageRoute(builder: (_) => widget.nextScreen),
      );
    });
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: const Color(0xFF1D9E75),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            FadeTransition(
              opacity: _logoFade,
              child: Container(
                width: 96,
                height: 96,
                decoration: BoxDecoration(
                  color: Colors.white,
                  borderRadius: BorderRadius.circular(24),
                ),
                child: const Icon(
                  Icons.bolt,
                  size: 56,
                  color: Color(0xFF1D9E75),
                ),
              ),
            ),
            const SizedBox(height: 24),
            FadeTransition(
              opacity: _textFade,
              child: SlideTransition(
                position: _textSlide,
                child: const Text(
                  'FlutterKit',
                  style: TextStyle(
                    color: Colors.white,
                    fontSize: 28,
                    fontWeight: FontWeight.w600,
                    letterSpacing: 0.5,
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

How to use this widget

  1. 1Copy the Dart code above
  2. 2Create a new file in your Flutter project — for example splash_screen.dart
  3. 3Set SplashScreen as your app home and pass the screen to show next via nextScreen — for example your login or home page after the auth check completes.

Related components

Auth & Onboarding

Login Screen

Clean email + password login with form validation and loading state

View component →
Auth & Onboarding

Register Screen

Full name, email, password registration with confirm password validation

View component →
Auth & Onboarding

Sign Up with Role Selector

Registration screen with role selection grid — Owner, Manager, or Employee

View component →