first commit
This commit is contained in:
@@ -0,0 +1,306 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import '../../../../shared/theme/app_theme.dart';
|
||||
|
||||
class SplashScreen extends StatefulWidget {
|
||||
const SplashScreen({super.key});
|
||||
|
||||
@override
|
||||
State<SplashScreen> createState() => _SplashScreenState();
|
||||
}
|
||||
|
||||
class _SplashScreenState extends State<SplashScreen>
|
||||
with TickerProviderStateMixin {
|
||||
late AnimationController _logoController;
|
||||
late AnimationController _progressController;
|
||||
late AnimationController _textController;
|
||||
|
||||
late Animation<double> _logoScaleAnimation;
|
||||
late Animation<double> _logoOpacityAnimation;
|
||||
late Animation<double> _progressAnimation;
|
||||
late Animation<double> _textOpacityAnimation;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_initializeAnimations();
|
||||
_startSplashSequence();
|
||||
}
|
||||
|
||||
void _initializeAnimations() {
|
||||
// Animation du logo
|
||||
_logoController = AnimationController(
|
||||
duration: const Duration(milliseconds: 1000),
|
||||
vsync: this,
|
||||
);
|
||||
|
||||
_logoScaleAnimation = Tween<double>(
|
||||
begin: 0.5,
|
||||
end: 1.0,
|
||||
).animate(CurvedAnimation(
|
||||
parent: _logoController,
|
||||
curve: Curves.elasticOut,
|
||||
));
|
||||
|
||||
_logoOpacityAnimation = Tween<double>(
|
||||
begin: 0.0,
|
||||
end: 1.0,
|
||||
).animate(CurvedAnimation(
|
||||
parent: _logoController,
|
||||
curve: const Interval(0.0, 0.6, curve: Curves.easeIn),
|
||||
));
|
||||
|
||||
// Animation de la barre de progression
|
||||
_progressController = AnimationController(
|
||||
duration: const Duration(milliseconds: 2000),
|
||||
vsync: this,
|
||||
);
|
||||
|
||||
_progressAnimation = Tween<double>(
|
||||
begin: 0.0,
|
||||
end: 1.0,
|
||||
).animate(CurvedAnimation(
|
||||
parent: _progressController,
|
||||
curve: Curves.easeInOut,
|
||||
));
|
||||
|
||||
// Animation du texte
|
||||
_textController = AnimationController(
|
||||
duration: const Duration(milliseconds: 800),
|
||||
vsync: this,
|
||||
);
|
||||
|
||||
_textOpacityAnimation = Tween<double>(
|
||||
begin: 0.0,
|
||||
end: 1.0,
|
||||
).animate(CurvedAnimation(
|
||||
parent: _textController,
|
||||
curve: Curves.easeIn,
|
||||
));
|
||||
}
|
||||
|
||||
void _startSplashSequence() async {
|
||||
// Configuration de la barre de statut
|
||||
SystemChrome.setSystemUIOverlayStyle(
|
||||
const SystemUiOverlayStyle(
|
||||
statusBarColor: Colors.transparent,
|
||||
statusBarIconBrightness: Brightness.light,
|
||||
),
|
||||
);
|
||||
|
||||
// Séquence d'animations
|
||||
await Future.delayed(const Duration(milliseconds: 300));
|
||||
_logoController.forward();
|
||||
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
_textController.forward();
|
||||
|
||||
await Future.delayed(const Duration(milliseconds: 300));
|
||||
_progressController.forward();
|
||||
|
||||
// Attendre la fin de toutes les animations + temps de chargement
|
||||
await Future.delayed(const Duration(milliseconds: 2000));
|
||||
|
||||
// Le splash screen sera remplacé automatiquement par l'AppWrapper
|
||||
// basé sur l'état d'authentification
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_logoController.dispose();
|
||||
_progressController.dispose();
|
||||
_textController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Container(
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
colors: [
|
||||
AppTheme.primaryColor,
|
||||
AppTheme.primaryDark,
|
||||
const Color(0xFF0D47A1),
|
||||
],
|
||||
),
|
||||
),
|
||||
child: SafeArea(
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
// Logo animé
|
||||
AnimatedBuilder(
|
||||
animation: _logoController,
|
||||
builder: (context, child) {
|
||||
return Transform.scale(
|
||||
scale: _logoScaleAnimation.value,
|
||||
child: Opacity(
|
||||
opacity: _logoOpacityAnimation.value,
|
||||
child: Container(
|
||||
width: 120,
|
||||
height: 120,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(30),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.2),
|
||||
blurRadius: 20,
|
||||
offset: const Offset(0, 10),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: const Icon(
|
||||
Icons.groups_rounded,
|
||||
size: 60,
|
||||
color: AppTheme.primaryColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
const SizedBox(height: 32),
|
||||
|
||||
// Titre animé
|
||||
AnimatedBuilder(
|
||||
animation: _textController,
|
||||
builder: (context, child) {
|
||||
return Opacity(
|
||||
opacity: _textOpacityAnimation.value,
|
||||
child: Column(
|
||||
children: [
|
||||
const Text(
|
||||
'UnionFlow',
|
||||
style: TextStyle(
|
||||
fontSize: 36,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.white,
|
||||
letterSpacing: 1.2,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'Gestion d\'associations professionnelle',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: Colors.white.withOpacity(0.9),
|
||||
fontWeight: FontWeight.w300,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// Section de chargement
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
// Barre de progression animée
|
||||
Container(
|
||||
width: 200,
|
||||
margin: const EdgeInsets.symmetric(horizontal: 40),
|
||||
child: Column(
|
||||
children: [
|
||||
AnimatedBuilder(
|
||||
animation: _progressController,
|
||||
builder: (context, child) {
|
||||
return LinearProgressIndicator(
|
||||
value: _progressAnimation.value,
|
||||
backgroundColor: Colors.white.withOpacity(0.2),
|
||||
valueColor: const AlwaysStoppedAnimation<Color>(
|
||||
Colors.white,
|
||||
),
|
||||
minHeight: 3,
|
||||
);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
AnimatedBuilder(
|
||||
animation: _progressController,
|
||||
builder: (context, child) {
|
||||
return Text(
|
||||
'${(_progressAnimation.value * 100).toInt()}%',
|
||||
style: TextStyle(
|
||||
color: Colors.white.withOpacity(0.8),
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: 24),
|
||||
|
||||
// Texte de chargement
|
||||
AnimatedBuilder(
|
||||
animation: _textController,
|
||||
builder: (context, child) {
|
||||
return Opacity(
|
||||
opacity: _textOpacityAnimation.value,
|
||||
child: Text(
|
||||
'Initialisation...',
|
||||
style: TextStyle(
|
||||
color: Colors.white.withOpacity(0.7),
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// Footer
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 40),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
'Version 1.0.0',
|
||||
style: TextStyle(
|
||||
color: Colors.white.withOpacity(0.6),
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'© 2024 Lions Club International',
|
||||
style: TextStyle(
|
||||
color: Colors.white.withOpacity(0.5),
|
||||
fontSize: 10,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user