Files
unionflow-client-quarkus-pr…/unionflow-mobile-apps/lib/features/demo/presentation/pages/animations_demo_page.dart
2025-09-15 20:15:34 +00:00

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,
),
),
],
),
),
);
}
}