Last active
June 29, 2025 00:07
-
-
Save loic-sharma/84003840193890d709b294b8499e921a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:async'; | |
import 'dart:math' as math; | |
import 'package:flutter/material.dart'; | |
import 'package:flutter_animate/flutter_animate.dart'; | |
void main() { | |
runApp(const MyApp()); | |
} | |
class MyApp extends StatelessWidget { | |
const MyApp({super.key}); | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
title: 'Simple Flutter App', | |
theme: ThemeData( | |
primarySwatch: Colors.blue, | |
), | |
home: const HomeScreen(), | |
routes: { | |
'/spinning-square': (context) => const SpinningSquarePage(), | |
'/spinning-square2': (context) => const SpinningSquarePage2(), | |
'/ping-pong': (context) => const PingPongPage(), | |
'/ping-pong2': (context) => const PingPongPage2(), | |
'/text-reveal': (context) => const TextRevealPage(), | |
'/text-reveal2': (context) => const TextRevealPage2(), | |
'/text-wiggle': (context) => const TextWigglePage(), | |
'/text-wiggle2': (context) => TextWigglePage2(), | |
}, | |
); | |
} | |
} | |
class HomeScreen extends StatelessWidget { | |
const HomeScreen({super.key}); | |
@override | |
Widget build(BuildContext context) { | |
const pages = { | |
'/spinning-square': 'Spinning square (Flutter)', | |
'/spinning-square2': 'Spinning square (flutter_animate)', | |
'/ping-pong': 'Ping pong square (Flutter)', | |
'/ping-pong2': 'Ping pong square (flutter_animate)', | |
'/text-reveal': 'Text reveal', | |
'/text-reveal2': 'Text reveal (flutter_animate)', | |
'/text-wiggle': 'Text wiggle', | |
'/text-wiggle2': 'Text wiggle (flutter_animate)', | |
}; | |
return Scaffold( | |
appBar: AppBar( | |
title: const Text('Home Screen'), | |
), | |
body: ListView( | |
children: [ | |
for (final page in pages.entries) | |
ListTile( | |
title: Text(page.value), | |
onTap: () => Navigator.pushNamed(context, page.key), | |
), | |
], | |
), | |
); | |
} | |
} | |
// SPINNING SQUARE | |
class SpinningSquarePage extends StatefulWidget { | |
const SpinningSquarePage({super.key}); | |
@override | |
State<SpinningSquarePage> createState() => _SpinningSquarePageState(); | |
} | |
class _SpinningSquarePageState extends State<SpinningSquarePage> | |
with TickerProviderStateMixin { | |
late final AnimationController _controller = AnimationController( | |
duration: const Duration(seconds: 2), | |
vsync: this, | |
); | |
@override | |
void initState() { | |
super.initState(); | |
_controller.repeat(); | |
} | |
@override | |
void dispose() { | |
_controller.dispose(); | |
super.dispose(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar(title: Text('Spinning square')), | |
body: Center( | |
child: AnimatedBuilder( | |
animation: _controller, | |
builder: (BuildContext context, Widget? child) { | |
return Transform.rotate( | |
angle: _controller.value * 2.0 * math.pi, | |
child: child, | |
); | |
}, | |
child: const ColoredBox( | |
color: Colors.green, | |
child: SizedBox.square(dimension: 100), | |
), | |
), | |
), | |
); | |
} | |
} | |
class SpinningSquarePage2 extends StatelessWidget { | |
const SpinningSquarePage2({super.key}); | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar(title: Text('Spinning square (flutter_animate)')), | |
body: Center( | |
child: Animate( | |
onPlay: (controller) => controller.repeat(), | |
effects: [ | |
RotateEffect( | |
duration: Duration(seconds: 2), | |
), | |
], | |
child: const ColoredBox( | |
color: Colors.green, | |
child: SizedBox.square(dimension: 100), | |
), | |
), | |
), | |
); | |
} | |
} | |
// PING PONG | |
class PingPongPage extends StatefulWidget { | |
const PingPongPage({super.key}); | |
@override | |
State<PingPongPage> createState() => _PingPongPageState(); | |
} | |
class _PingPongPageState extends State<PingPongPage> | |
with TickerProviderStateMixin { | |
late final AnimationController _controller = AnimationController( | |
duration: const Duration(seconds: 1), | |
vsync: this, | |
); | |
late final Animation<Offset> _position; | |
@override | |
void initState() { | |
super.initState(); | |
_position = _controller.drive( | |
Tween<Offset>( | |
begin: Offset(-1.0, 0), | |
end: Offset(1.0, 0), | |
), | |
); | |
_controller.repeat(reverse: true); | |
} | |
@override | |
void dispose() { | |
_controller.dispose(); | |
super.dispose(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar(title: Text('Ping Pong (Flutter)')), | |
body: Center( | |
child: SlideTransition( | |
position: _position, | |
child: const ColoredBox( | |
color: Colors.green, | |
child: SizedBox.square(dimension: 100), | |
), | |
), | |
), | |
); | |
} | |
} | |
class PingPongPage2 extends StatelessWidget { | |
const PingPongPage2({super.key}); | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar(title: Text('Ping pong (flutter_animate)')), | |
body: Center( | |
child: Animate( | |
onPlay: (controller) => controller.repeat(reverse: true), | |
effects: [ | |
SlideEffect( | |
duration: Duration(seconds: 1), | |
begin: Offset(-1, 0), | |
end: Offset(1, 0), | |
), | |
], | |
child: const ColoredBox( | |
color: Colors.green, | |
child: SizedBox.square(dimension: 100), | |
), | |
), | |
), | |
); | |
} | |
} | |
// TEXT REVEAL | |
class TextRevealPage extends StatefulWidget { | |
const TextRevealPage({super.key}); | |
@override | |
State<TextRevealPage> createState() => _TextRevealPageState(); | |
} | |
class _TextRevealPageState extends State<TextRevealPage> with TickerProviderStateMixin { | |
late final AnimationController _controller = AnimationController( | |
duration: const Duration(seconds: 3), | |
vsync: this, | |
); | |
late Animation<double> _fadeAnimation1; | |
late Animation<Offset> _slideAnimation1; | |
late Animation<double> _fadeAnimation2; | |
late Animation<Offset> _slideAnimation2; | |
late Animation<double> _fadeAnimation3; | |
late Animation<Offset> _slideAnimation3; | |
@override | |
void initState() { | |
super.initState(); | |
final animation1 = CurvedAnimation( | |
parent: _controller, | |
curve: const Interval(0, 0.33), | |
); | |
final animation2 = CurvedAnimation( | |
parent: _controller, | |
curve: const Interval(0.33, 0.66), | |
); | |
final animation3 = CurvedAnimation( | |
parent: _controller, | |
curve: const Interval(0.66, 1.0), | |
); | |
final fadeTween = Tween<double>(begin: 0.0, end: 1.0); | |
final slideTween = Tween<Offset>(begin: const Offset(-1.0, 0.0), end: Offset.zero); | |
_fadeAnimation1 = animation1.drive(fadeTween); | |
_slideAnimation1 = animation1.drive(slideTween); | |
_fadeAnimation2 = animation2.drive(fadeTween); | |
_slideAnimation2 = animation2.drive(slideTween); | |
_fadeAnimation3 = animation3.drive(fadeTween); | |
_slideAnimation3 = animation3.drive(slideTween); | |
_controller.forward(); | |
} | |
@override | |
void dispose() { | |
_controller.dispose(); | |
super.dispose(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar(title: const Text('Text Reveal')), | |
body: Center( | |
child: Column( | |
mainAxisAlignment: MainAxisAlignment.center, | |
children: [ | |
FadeTransition( | |
opacity: _fadeAnimation1, | |
child: SlideTransition( | |
position: _slideAnimation1, | |
child: const Text('Foo'), | |
), | |
), | |
FadeTransition( | |
opacity: _fadeAnimation2, | |
child: SlideTransition( | |
position: _slideAnimation2, | |
child: const Text('Bar'), | |
), | |
), | |
FadeTransition( | |
opacity: _fadeAnimation3, | |
child: SlideTransition( | |
position: _slideAnimation3, | |
child: const Text('Bar'), | |
), | |
), | |
], | |
), | |
), | |
); | |
} | |
} | |
class TextRevealPage2 extends StatelessWidget { | |
const TextRevealPage2({super.key}); | |
@override | |
Widget build(BuildContext context) { | |
const revealEffect = <Effect>[ | |
FadeEffect( | |
duration: Duration(seconds: 1), | |
), | |
SlideEffect( | |
duration: Duration(seconds: 1), | |
begin: Offset(-1, 0), | |
end: Offset(0, 0), | |
), | |
]; | |
return Scaffold( | |
appBar: AppBar(title: Text('Text reveal (flutter_animate)')), | |
body: Center( | |
child: Column( | |
mainAxisAlignment: MainAxisAlignment.center, | |
children: [ | |
Animate( | |
delay: Duration(seconds: 0), | |
effects: revealEffect, | |
child: Text('Foo'), | |
), | |
Animate( | |
delay: Duration(seconds: 1), | |
effects: revealEffect, | |
child: Text('Bar'), | |
), | |
Animate( | |
delay: Duration(seconds: 2), | |
effects: revealEffect, | |
child: Text('Bar'), | |
), | |
], | |
), | |
) | |
); | |
} | |
} | |
// TEXT WIGGLE | |
class TextWigglePage extends StatefulWidget { | |
const TextWigglePage({super.key}); | |
@override | |
State<TextWigglePage> createState() => _TextWigglePageState(); | |
} | |
class _TextWigglePageState extends State<TextWigglePage> with SingleTickerProviderStateMixin { | |
late final AnimationController _controller = AnimationController( | |
duration: const Duration(seconds: 3), | |
vsync: this, | |
); | |
late Animation<double> _animation; | |
@override | |
void initState() { | |
super.initState(); | |
final wiggleTween = TweenSequence<double>([ | |
TweenSequenceItem(tween: Tween(begin: 0.0, end: 0.05), weight: 1), // Rotate slightly right | |
TweenSequenceItem(tween: Tween(begin: 0.05, end: -0.05), weight: 1), // Rotate left | |
TweenSequenceItem(tween: Tween(begin: 0.0, end: 0.05), weight: 1), // Rotate slightly right | |
TweenSequenceItem(tween: Tween(begin: 0.05, end: -0.05), weight: 1), // Rotate left | |
TweenSequenceItem(tween: Tween(begin: -0.05, end: 0.0), weight: 1), // Return to center | |
]); | |
final sleepInterval = CurvedAnimation( | |
parent: _controller, | |
curve: Interval(0.0, 0.10), // Wiggle for 300ms. | |
); | |
_animation = sleepInterval.drive(wiggleTween); | |
_controller.repeat(); | |
} | |
@override | |
void dispose() { | |
_controller.dispose(); | |
super.dispose(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar(title: Text('Text wiggle')), | |
body: Center( | |
child: AnimatedBuilder( | |
animation: _animation, | |
builder: (context, child) { | |
return Transform.rotate( | |
angle: _animation.value * math.pi, | |
child: Text( | |
'Hello world', | |
style: TextStyle(fontSize: 20), | |
), | |
); | |
}, | |
), | |
), | |
); | |
} | |
} | |
class TextWigglePage2 extends StatelessWidget { | |
TextWigglePage2({super.key}); | |
final TweenSequence<double> _tween = TweenSequence<double>([ | |
TweenSequenceItem(tween: Tween(begin: 0.0, end: 0.05), weight: 1), // Rotate slightly right | |
TweenSequenceItem(tween: Tween(begin: 0.05, end: -0.05), weight: 1), // Rotate left | |
TweenSequenceItem(tween: Tween(begin: 0.0, end: 0.05), weight: 1), // Rotate slightly right | |
TweenSequenceItem(tween: Tween(begin: 0.05, end: -0.05), weight: 1), // Rotate left | |
TweenSequenceItem(tween: Tween(begin: -0.05, end: 0.0), weight: 1), // Return to center | |
]); | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar(title: Text('Text wiggle (flutter_animate)')), | |
body: Center( | |
child: Animate( | |
onComplete: (controller) => controller.repeat(), | |
effects: [ | |
CustomEffect( | |
duration: Duration(milliseconds: 300), | |
builder: (context, value, child) { | |
return Transform.rotate( | |
angle: _tween.transform(value) * math.pi, | |
child: child, | |
); | |
}, | |
), | |
// Sleep for 3 seconds. | |
CustomEffect( | |
duration: Duration(seconds: 3), | |
builder: (context, value, child) => child, | |
), | |
], | |
child: Text( | |
'Hello world', | |
style: TextStyle(fontSize: 20), | |
), | |
), | |
), | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment