Create a Splash Screen in Flutter with Timer
A splash screen is the first screen users see when launching your app. This guide will show you how to create engaging splash screens with timers and smooth transitions in Flutter.
Basic Splash Screen Implementation
Here's a simple splash screen that transitions to the main screen after a fixed duration:
class SplashScreen extends StatefulWidget { @override _SplashScreenState createState() => _SplashScreenState(); } class _SplashScreenState extends State<SplashScreen> { @override void initState() { super.initState(); Timer( Duration(seconds: 3), () => Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => HomeScreen()), ), ); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.blue, body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Image.asset( 'assets/logo.png', width: 200, height: 200, ), SizedBox(height: 20), Text( 'My App', style: TextStyle( fontSize: 24, color: Colors.white, fontWeight: FontWeight.bold, ), ), ], ), ), ); } }
Animated Splash Screen
Add animations to make your splash screen more engaging:
class AnimatedSplashScreen extends StatefulWidget { @override _AnimatedSplashScreenState createState() => _AnimatedSplashScreenState(); } class _AnimatedSplashScreenState extends State<AnimatedSplashScreen> with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation<double> _fadeAnimation; late Animation<double> _scaleAnimation; @override void initState() { super.initState(); _controller = AnimationController( duration: Duration(seconds: 2), vsync: this, ); _fadeAnimation = Tween<double>(begin: 0.0, end: 1.0).animate( CurvedAnimation( parent: _controller, curve: Interval(0.0, 0.5, curve: Curves.easeIn), ), ); _scaleAnimation = Tween<double>(begin: 0.5, end: 1.0).animate( CurvedAnimation( parent: _controller, curve: Interval(0.5, 1.0, curve: Curves.easeOut), ), ); _controller.forward(); Timer( Duration(seconds: 3), () => Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => HomeScreen()), ), ); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, body: AnimatedBuilder( animation: _controller, builder: (context, child) { return Center( child: FadeTransition( opacity: _fadeAnimation, child: ScaleTransition( scale: _scaleAnimation, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Image.asset( 'assets/logo.png', width: 200, height: 200, ), SizedBox(height: 20), Text( 'My App', style: TextStyle( fontSize: 24, fontWeight: FontWeight.bold, ), ), ], ), ), ), ); }, ), ); } }
Splash Screen with Loading Progress
Create a splash screen that shows loading progress:
class LoadingSplashScreen extends StatefulWidget { @override _LoadingSplashScreenState createState() => _LoadingSplashScreenState(); } class _LoadingSplashScreenState extends State<LoadingSplashScreen> { double _progress = 0.0; @override void initState() { super.initState(); _startLoading(); } Future<void> _startLoading() async { for (var i = 0; i <= 100; i++) { await Future.delayed(Duration(milliseconds: 30)); setState(() { _progress = i / 100; }); } Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => HomeScreen()), ); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Image.asset( 'assets/logo.png', width: 200, height: 200, ), SizedBox(height: 30), Container( width: 200, child: LinearProgressIndicator( value: _progress, backgroundColor: Colors.grey[200], valueColor: AlwaysStoppedAnimation<Color>(Colors.blue), ), ), SizedBox(height: 20), Text( '${(_progress * 100).toInt()}%', style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, ), ), ], ), ), ); } }
Splash Screen with Initialization Tasks
Handle initialization tasks during the splash screen:
class InitializationSplashScreen extends StatefulWidget { @override _InitializationSplashScreenState createState() => _InitializationSplashScreenState(); } class _InitializationSplashScreenState extends State<InitializationSplashScreen> { @override void initState() { super.initState(); _initializeApp(); } Future<void> _initializeApp() async { try { // Perform initialization tasks await Future.wait([ _initializeDatabase(), _loadUserPreferences(), _checkNetworkConnection(), ]); // Navigate to home screen after initialization Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => HomeScreen()), ); } catch (e) { // Handle initialization errors _showErrorDialog(); } } Future<void> _initializeDatabase() async { await Future.delayed(Duration(seconds: 1)); // Add your database initialization code } Future<void> _loadUserPreferences() async { await Future.delayed(Duration(seconds: 1)); // Add your preferences loading code } Future<void> _checkNetworkConnection() async { await Future.delayed(Duration(seconds: 1)); // Add your network check code } void _showErrorDialog() { showDialog( context: context, builder: (context) => AlertDialog( title: Text('Initialization Error'), content: Text('Failed to initialize the app. Please try again.'), actions: [ TextButton( onPressed: () { Navigator.pop(context); _initializeApp(); }, child: Text('Retry'), ), ], ), ); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Image.asset( 'assets/logo.png', width: 200, height: 200, ), SizedBox(height: 30), CircularProgressIndicator(), SizedBox(height: 20), Text( 'Initializing...', style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, ), ), ], ), ), ); } }
Best Practices
-
Duration
- Keep splash screen duration between 2-4 seconds
- Consider user experience and app initialization needs
- Don't make users wait unnecessarily
-
Design Guidelines
- Follow platform-specific design guidelines
- Keep the design simple and focused
- Ensure branding elements are clearly visible
-
Performance
- Minimize initialization tasks
- Use async operations efficiently
- Handle errors gracefully
Common Issues and Solutions
Issue 1: Screen Flicker During Transition
Solution: Use pushReplacement
instead of push
:
Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => HomeScreen()), );
Issue 2: Memory Leaks
Solution: Properly dispose of controllers and timers:
@override void dispose() { _controller.dispose(); _timer?.cancel(); super.dispose(); }
Conclusion
A well-designed splash screen can enhance your app's user experience by:
- Providing visual feedback during app initialization
- Reinforcing your brand identity
- Creating a smooth transition to the main content
- Handling necessary setup tasks efficiently
Remember to:
- Keep the duration reasonable
- Add meaningful animations
- Handle initialization tasks properly
- Follow platform design guidelines
- Test on different devices and screen sizes
With these implementations, you can create professional splash screens that enhance your Flutter application's launch experience.