From 3ad48016f3baf528a68d2c2a48e81d0c98f7eeef Mon Sep 17 00:00:00 2001 From: Vaibhav Surve Date: Sat, 29 Nov 2025 12:34:30 +0530 Subject: [PATCH] Enhance splash screen with improved animations and loading indicator; update logo size and message for better visibility --- lib/view/splash_screen.dart | 171 ++++++++++++++++++++++-------------- 1 file changed, 103 insertions(+), 68 deletions(-) diff --git a/lib/view/splash_screen.dart b/lib/view/splash_screen.dart index 7f84b21..79484b3 100644 --- a/lib/view/splash_screen.dart +++ b/lib/view/splash_screen.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +// Assuming 'package:on_field_work/images.dart' correctly provides 'Images.logoDark' import 'package:on_field_work/images.dart'; class SplashScreen extends StatefulWidget { @@ -8,8 +9,9 @@ class SplashScreen extends StatefulWidget { const SplashScreen({ super.key, - this.message, - this.logoSize = 120, + this.message = + 'GET WORK DONE, ANYWHERE.', // Default message for a modern look + this.logoSize = 150, // Slightly larger logo this.backgroundColor = Colors.white, }); @@ -20,20 +22,59 @@ class SplashScreen extends StatefulWidget { class _SplashScreenState extends State with SingleTickerProviderStateMixin { late AnimationController _controller; - late Animation _animation; + // Animation for the logo's vertical float effect + late Animation _floatAnimation; + // Animation for logo's initial scale-in + late Animation _scaleAnimation; + // Animation for logo and text fade-in + late Animation _opacityAnimation; @override void initState() { super.initState(); _controller = AnimationController( - duration: const Duration(seconds: 1), + duration: + const Duration(seconds: 3), // Longer duration for complex sequence vsync: this, - )..repeat(reverse: true); - - _animation = Tween(begin: 0.0, end: 8.0).animate( - CurvedAnimation(parent: _controller, curve: Curves.easeInOut), ); + + // Initial scale-in: from 0.0 to 1.0 (happens in the first 40% of the duration) + _scaleAnimation = Tween(begin: 0.5, end: 1.0).animate( + CurvedAnimation( + parent: _controller, + curve: + const Interval(0.0, 0.4, curve: Curves.easeOutBack), // Bouncy start + ), + ); + + // Overall fade-in: from 0.0 to 1.0 (happens in the first 50% of the duration) + _opacityAnimation = Tween(begin: 0.0, end: 1.0).animate( + CurvedAnimation( + parent: _controller, + curve: const Interval(0.0, 0.5, curve: Curves.easeIn), + ), + ); + + // Floating effect: from 0.0 to 1.0 (loops repeatedly after initial animations) + _floatAnimation = Tween(begin: -8.0, end: 8.0).animate( + CurvedAnimation( + parent: _controller, + curve: Curves.easeInOut, + ), + ); + + // Start the complex animation sequence + _controller.forward().then((_) { + // After the initial scale/fade, switch to repeating the float animation + if (mounted) { + _controller.repeat( + min: 0.4, // Start repeat from the float interval + max: 1.0, + reverse: true, + ); + } + }); } @override @@ -42,33 +83,14 @@ class _SplashScreenState extends State super.dispose(); } - Widget _buildAnimatedDots() { - return Row( - mainAxisAlignment: MainAxisAlignment.center, - children: List.generate(3, (index) { - return AnimatedBuilder( - animation: _animation, - builder: (context, child) { - double opacity; - if (index == 0) { - opacity = (0.3 + _animation.value / 8).clamp(0.0, 1.0); - } else if (index == 1) { - opacity = (0.3 + (_animation.value / 8)).clamp(0.0, 1.0); - } else { - opacity = (0.3 + (1 - _animation.value / 8)).clamp(0.0, 1.0); - } - return Container( - margin: const EdgeInsets.symmetric(horizontal: 4), - width: 10, - height: 10, - decoration: BoxDecoration( - color: Colors.blueAccent.withOpacity(opacity), - shape: BoxShape.circle, - ), - ); - }, - ); - }), + // A simple, modern custom progress indicator + Widget _buildProgressIndicator() { + return SizedBox( + width: 60, + child: LinearProgressIndicator( + backgroundColor: Colors.blueAccent.withOpacity(0.2), + valueColor: const AlwaysStoppedAnimation(Colors.blueAccent), + ), ); } @@ -76,43 +98,56 @@ class _SplashScreenState extends State Widget build(BuildContext context) { return Scaffold( backgroundColor: widget.backgroundColor, - body: SafeArea( - child: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - // Logo with slight bounce animation - ScaleTransition( - scale: Tween(begin: 0.8, end: 1.0).animate( - CurvedAnimation( - parent: _controller, - curve: Curves.easeInOut, + // Full screen display, no SafeArea needed for a full bleed splash + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + // Animated Logo (Scale, Opacity, and Float) + FadeTransition( + opacity: _opacityAnimation, + child: AnimatedBuilder( + animation: _floatAnimation, + builder: (context, child) { + return Transform.translate( + offset: Offset(0, _floatAnimation.value), + child: ScaleTransition( + scale: _scaleAnimation, + child: SizedBox( + width: widget.logoSize, + height: widget.logoSize, + // Replace with your actual logo image widget + child: Image.asset(Images.logoDark), + ), + ), + ); + }, + ), + ), + + const SizedBox(height: 30), + + // Text Message (Fades in slightly after logo) + if (widget.message != null) + FadeTransition( + opacity: _opacityAnimation, + child: Text( + widget.message!, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Colors.grey.shade700, + letterSpacing: 1.2, ), ), - child: SizedBox( - width: widget.logoSize, - height: widget.logoSize, - child: Image.asset(Images.logoDark), - ), ), - const SizedBox(height: 20), - // Text message - if (widget.message != null) - Text( - widget.message!, - textAlign: TextAlign.center, - style: const TextStyle( - fontSize: 18, - fontWeight: FontWeight.w600, - color: Colors.black87, - ), - ), - const SizedBox(height: 30), - // Animated loading dots - _buildAnimatedDots(), - ], - ), + const SizedBox(height: 40), + + // Modern Loading Indicator + _buildProgressIndicator(), + ], ), ), );