465 lines
16 KiB
Dart
465 lines
16 KiB
Dart
import 'package:flutter/material.dart';
|
|
import '../../../../core/animations/animated_button.dart';
|
|
import '../../../../core/animations/animated_notifications.dart';
|
|
import '../../../../core/animations/page_transitions.dart';
|
|
import '../../../../shared/theme/app_theme.dart';
|
|
|
|
/// Page de démonstration des animations
|
|
class AnimationsDemoPage extends StatefulWidget {
|
|
const AnimationsDemoPage({super.key});
|
|
|
|
@override
|
|
State<AnimationsDemoPage> createState() => _AnimationsDemoPageState();
|
|
}
|
|
|
|
class _AnimationsDemoPageState extends State<AnimationsDemoPage>
|
|
with TickerProviderStateMixin {
|
|
late AnimationController _floatingController;
|
|
late AnimationController _pulseController;
|
|
late Animation<double> _floatingAnimation;
|
|
late Animation<double> _pulseAnimation;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
|
|
_floatingController = AnimationController(
|
|
duration: const Duration(seconds: 2),
|
|
vsync: this,
|
|
)..repeat(reverse: true);
|
|
|
|
_pulseController = AnimationController(
|
|
duration: const Duration(milliseconds: 1500),
|
|
vsync: this,
|
|
)..repeat();
|
|
|
|
_floatingAnimation = Tween<double>(
|
|
begin: -10.0,
|
|
end: 10.0,
|
|
).animate(CurvedAnimation(
|
|
parent: _floatingController,
|
|
curve: Curves.easeInOut,
|
|
));
|
|
|
|
_pulseAnimation = Tween<double>(
|
|
begin: 1.0,
|
|
end: 1.2,
|
|
).animate(CurvedAnimation(
|
|
parent: _pulseController,
|
|
curve: Curves.elasticOut,
|
|
));
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_floatingController.dispose();
|
|
_pulseController.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
title: const Text('Démonstration des Animations'),
|
|
backgroundColor: AppTheme.primaryColor,
|
|
foregroundColor: Colors.white,
|
|
elevation: 0,
|
|
),
|
|
body: SingleChildScrollView(
|
|
padding: const EdgeInsets.all(16),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
children: [
|
|
// Section Boutons Animés
|
|
_buildSection(
|
|
'Boutons Animés',
|
|
[
|
|
const SizedBox(height: 16),
|
|
AnimatedButton(
|
|
text: 'Bouton Principal',
|
|
onPressed: () => _showNotification(NotificationType.success),
|
|
style: AnimatedButtonStyle.primary,
|
|
),
|
|
const SizedBox(height: 12),
|
|
AnimatedButton(
|
|
text: 'Bouton Secondaire',
|
|
onPressed: () => _showNotification(NotificationType.info),
|
|
style: AnimatedButtonStyle.secondary,
|
|
),
|
|
const SizedBox(height: 12),
|
|
AnimatedButton(
|
|
text: 'Bouton de Succès',
|
|
onPressed: () => _showNotification(NotificationType.success),
|
|
style: AnimatedButtonStyle.success,
|
|
),
|
|
const SizedBox(height: 12),
|
|
AnimatedButton(
|
|
text: 'Bouton d\'Avertissement',
|
|
onPressed: () => _showNotification(NotificationType.warning),
|
|
style: AnimatedButtonStyle.warning,
|
|
),
|
|
const SizedBox(height: 12),
|
|
AnimatedButton(
|
|
text: 'Bouton d\'Erreur',
|
|
onPressed: () => _showNotification(NotificationType.error),
|
|
style: AnimatedButtonStyle.error,
|
|
),
|
|
const SizedBox(height: 12),
|
|
AnimatedButton(
|
|
text: 'Bouton Contour',
|
|
onPressed: () => _showNotification(NotificationType.info),
|
|
style: AnimatedButtonStyle.outline,
|
|
),
|
|
],
|
|
),
|
|
|
|
const SizedBox(height: 32),
|
|
|
|
// Section Notifications
|
|
_buildSection(
|
|
'Notifications Animées',
|
|
[
|
|
const SizedBox(height: 16),
|
|
Row(
|
|
children: [
|
|
Expanded(
|
|
child: ElevatedButton.icon(
|
|
onPressed: () => _showNotification(NotificationType.success),
|
|
icon: const Icon(Icons.check_circle),
|
|
label: const Text('Succès'),
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: AppTheme.successColor,
|
|
foregroundColor: Colors.white,
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(width: 8),
|
|
Expanded(
|
|
child: ElevatedButton.icon(
|
|
onPressed: () => _showNotification(NotificationType.error),
|
|
icon: const Icon(Icons.error),
|
|
label: const Text('Erreur'),
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: AppTheme.errorColor,
|
|
foregroundColor: Colors.white,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 8),
|
|
Row(
|
|
children: [
|
|
Expanded(
|
|
child: ElevatedButton.icon(
|
|
onPressed: () => _showNotification(NotificationType.warning),
|
|
icon: const Icon(Icons.warning),
|
|
label: const Text('Avertissement'),
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: AppTheme.warningColor,
|
|
foregroundColor: Colors.white,
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(width: 8),
|
|
Expanded(
|
|
child: ElevatedButton.icon(
|
|
onPressed: () => _showNotification(NotificationType.info),
|
|
icon: const Icon(Icons.info),
|
|
label: const Text('Information'),
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: AppTheme.primaryColor,
|
|
foregroundColor: Colors.white,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
|
|
const SizedBox(height: 32),
|
|
|
|
// Section Transitions de Page
|
|
_buildSection(
|
|
'Transitions de Page',
|
|
[
|
|
const SizedBox(height: 16),
|
|
_buildTransitionButton(
|
|
'Glissement depuis la droite',
|
|
() => _navigateWithTransition(PageTransitions.slideFromRight),
|
|
),
|
|
const SizedBox(height: 8),
|
|
_buildTransitionButton(
|
|
'Glissement depuis le bas',
|
|
() => _navigateWithTransition(PageTransitions.slideFromBottom),
|
|
),
|
|
const SizedBox(height: 8),
|
|
_buildTransitionButton(
|
|
'Fondu',
|
|
() => _navigateWithTransition(PageTransitions.fadeIn),
|
|
),
|
|
const SizedBox(height: 8),
|
|
_buildTransitionButton(
|
|
'Échelle avec fondu',
|
|
() => _navigateWithTransition(PageTransitions.scaleWithFade),
|
|
),
|
|
const SizedBox(height: 8),
|
|
_buildTransitionButton(
|
|
'Rebond',
|
|
() => _navigateWithTransition(PageTransitions.bounceIn),
|
|
),
|
|
const SizedBox(height: 8),
|
|
_buildTransitionButton(
|
|
'Parallaxe',
|
|
() => _navigateWithTransition(PageTransitions.slideWithParallax),
|
|
),
|
|
const SizedBox(height: 8),
|
|
_buildTransitionButton(
|
|
'Morphing avec Blur',
|
|
() => _navigateWithTransition(PageTransitions.morphWithBlur),
|
|
),
|
|
const SizedBox(height: 8),
|
|
_buildTransitionButton(
|
|
'Rotation 3D',
|
|
() => _navigateWithTransition(PageTransitions.rotate3D),
|
|
),
|
|
],
|
|
),
|
|
|
|
const SizedBox(height: 32),
|
|
|
|
// Section Animations Continues
|
|
_buildSection(
|
|
'Animations Continues',
|
|
[
|
|
const SizedBox(height: 16),
|
|
Center(
|
|
child: Column(
|
|
children: [
|
|
AnimatedBuilder(
|
|
animation: _floatingAnimation,
|
|
builder: (context, child) {
|
|
return Transform.translate(
|
|
offset: Offset(0, _floatingAnimation.value),
|
|
child: Container(
|
|
width: 80,
|
|
height: 80,
|
|
decoration: BoxDecoration(
|
|
gradient: LinearGradient(
|
|
colors: [
|
|
AppTheme.primaryColor,
|
|
AppTheme.primaryColor.withOpacity(0.7),
|
|
],
|
|
begin: Alignment.topLeft,
|
|
end: Alignment.bottomRight,
|
|
),
|
|
borderRadius: BorderRadius.circular(40),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: AppTheme.primaryColor.withOpacity(0.3),
|
|
blurRadius: 12,
|
|
offset: const Offset(0, 4),
|
|
),
|
|
],
|
|
),
|
|
child: const Icon(
|
|
Icons.star,
|
|
color: Colors.white,
|
|
size: 40,
|
|
),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
const SizedBox(height: 16),
|
|
const Text(
|
|
'Animation Flottante',
|
|
style: TextStyle(
|
|
fontSize: 16,
|
|
fontWeight: FontWeight.w600,
|
|
),
|
|
),
|
|
const SizedBox(height: 32),
|
|
AnimatedBuilder(
|
|
animation: _pulseAnimation,
|
|
builder: (context, child) {
|
|
return Transform.scale(
|
|
scale: _pulseAnimation.value,
|
|
child: Container(
|
|
width: 60,
|
|
height: 60,
|
|
decoration: BoxDecoration(
|
|
color: AppTheme.successColor,
|
|
borderRadius: BorderRadius.circular(30),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: AppTheme.successColor.withOpacity(0.4),
|
|
blurRadius: 20,
|
|
spreadRadius: 5,
|
|
),
|
|
],
|
|
),
|
|
child: const Icon(
|
|
Icons.favorite,
|
|
color: Colors.white,
|
|
size: 30,
|
|
),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
const SizedBox(height: 16),
|
|
const Text(
|
|
'Animation Pulsante',
|
|
style: TextStyle(
|
|
fontSize: 16,
|
|
fontWeight: FontWeight.w600,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
|
|
const SizedBox(height: 32),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildSection(String title, List<Widget> children) {
|
|
return Card(
|
|
elevation: 4,
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(16),
|
|
),
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(20),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
title,
|
|
style: const TextStyle(
|
|
fontSize: 20,
|
|
fontWeight: FontWeight.bold,
|
|
color: AppTheme.primaryColor,
|
|
),
|
|
),
|
|
const Divider(height: 24),
|
|
...children,
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildTransitionButton(String text, VoidCallback onPressed) {
|
|
return SizedBox(
|
|
width: double.infinity,
|
|
child: OutlinedButton(
|
|
onPressed: onPressed,
|
|
style: OutlinedButton.styleFrom(
|
|
padding: const EdgeInsets.symmetric(vertical: 12),
|
|
side: const BorderSide(color: AppTheme.primaryColor),
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
),
|
|
child: Text(
|
|
text,
|
|
style: const TextStyle(
|
|
color: AppTheme.primaryColor,
|
|
fontWeight: FontWeight.w600,
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
void _showNotification(NotificationType type) {
|
|
switch (type) {
|
|
case NotificationType.success:
|
|
AnimatedNotifications.showSuccess(
|
|
context,
|
|
'Opération réussie avec succès !',
|
|
);
|
|
break;
|
|
case NotificationType.error:
|
|
AnimatedNotifications.showError(
|
|
context,
|
|
'Une erreur s\'est produite lors de l\'opération.',
|
|
);
|
|
break;
|
|
case NotificationType.warning:
|
|
AnimatedNotifications.showWarning(
|
|
context,
|
|
'Attention : cette action nécessite une confirmation.',
|
|
);
|
|
break;
|
|
case NotificationType.info:
|
|
AnimatedNotifications.showInfo(
|
|
context,
|
|
'Information : les données ont été mises à jour.',
|
|
);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void _navigateWithTransition(PageRouteBuilder Function(Widget) transitionBuilder) {
|
|
Navigator.of(context).push(
|
|
transitionBuilder(const _DemoDestinationPage()),
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Page de destination pour les démonstrations de transition
|
|
class _DemoDestinationPage extends StatelessWidget {
|
|
const _DemoDestinationPage();
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
title: const Text('Page de Destination'),
|
|
backgroundColor: AppTheme.secondaryColor,
|
|
foregroundColor: Colors.white,
|
|
),
|
|
body: const Center(
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Icon(
|
|
Icons.check_circle,
|
|
size: 80,
|
|
color: AppTheme.successColor,
|
|
),
|
|
SizedBox(height: 24),
|
|
Text(
|
|
'Transition réussie !',
|
|
style: TextStyle(
|
|
fontSize: 24,
|
|
fontWeight: FontWeight.bold,
|
|
color: AppTheme.primaryColor,
|
|
),
|
|
),
|
|
SizedBox(height: 16),
|
|
Text(
|
|
'Vous pouvez revenir en arrière\npour tester d\'autres transitions.',
|
|
textAlign: TextAlign.center,
|
|
style: TextStyle(
|
|
fontSize: 16,
|
|
color: Colors.grey,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|