├── README.md
├── rainbow_text
├── README.md
└── visual_view.dart
├── scale_animation
├── README.md
└── scale_animation.dart
├── size_animation
├── README.md
└── size_animation.dart
├── slider_animation
├── README.md
└── adapter_view.dart
└── widgets_animation
├── README.md
└── everything_view.dart
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Flutter Animations
7 |
8 |
9 |
10 |
11 |
12 |
13 | In this repository I will keep some animations that I made during studies.
14 |
15 | ## How To Use
16 |
17 | Navigate between the repository folders, in each of them you will have a README file that will show the animation and the code responsible for it
18 |
--------------------------------------------------------------------------------
/rainbow_text/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Rainbow Text
7 |
8 |
9 |
10 |
11 | https://user-images.githubusercontent.com/57817746/189343934-1ddaf774-29c6-4a08-9e34-926869604618.mov
12 |
--------------------------------------------------------------------------------
/rainbow_text/visual_view.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_animate/flutter_animate.dart';
3 |
4 | class VisualView extends StatelessWidget {
5 | const VisualView({Key? key}) : super(key: key);
6 |
7 | @override
8 | Widget build(BuildContext context) {
9 | // create our stylish text:
10 | Widget title = const Text(
11 | 'SOME\nVISUAL\nEFFECTS\n\n on\n\nRAINBOW\nTEXT',
12 | style: TextStyle(
13 | fontWeight: FontWeight.w900,
14 | fontSize: 64,
15 | color: Color(0xFF666870),
16 | height: 0.9,
17 | letterSpacing: -5,
18 | ),
19 | );
20 |
21 | // add a rainbow gradient:
22 | // I'm lazy so I'll just apply a ShimmerEffect, use a ValueAdapter to
23 | // pause it half way, and let it handle the details
24 | title = title.animate(adapter: ValueAdapter(0.5)).shimmer(
25 | colors: [
26 | const Color(0xFFFFFF00),
27 | const Color(0xFF00FF00),
28 | const Color(0xFF00FFFF),
29 | const Color(0xFF0033FF),
30 | const Color(0xFFFF00FF),
31 | const Color(0xFFFF0000),
32 | const Color(0xFFFFFF00),
33 | ],
34 | );
35 |
36 | // sequence some visual effects
37 | title = title
38 | .animate(onPlay: (controller) => controller.repeat(reverse: true))
39 | .saturate(delay: 1.seconds, duration: 2.seconds)
40 | .then() // set delay to when the previous effect ends.
41 | .tint(color: const Color(0xFF80DDFF))
42 | .then()
43 | .blur(end: 24)
44 | .fadeOut();
45 |
46 | return Padding(padding: const EdgeInsets.all(24), child: title);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/scale_animation/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Scale Animation
7 |
8 |
9 |
10 | https://user-images.githubusercontent.com/57817746/189344175-bed69578-74f7-4069-abf8-6bb829cc64ab.mov
11 |
--------------------------------------------------------------------------------
/scale_animation/scale_animation.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | ///Animates the child
4 | ///
5 | ///using TweenAnimationBuilder
6 | class ScaleAnimation extends StatelessWidget {
7 | const ScaleAnimation({
8 | Key? key,
9 | required this.child,
10 | this.begin = 0.4,
11 | this.end = 1,
12 | this.intervalStart = 0,
13 | this.intervalEnd = 1,
14 | this.duration = const Duration(milliseconds: 1000),
15 | this.curve = Curves.fastOutSlowIn,
16 | }) : super(key: key);
17 |
18 | ///Animate from value
19 | ///
20 | ///[default value 0.4]
21 | final double begin;
22 |
23 | ///Animate to value
24 | ///
25 | ///[default value 1]
26 | final double end;
27 |
28 | ///Animation Duration
29 | ///
30 | ///[default is 750ms]
31 | final Duration duration;
32 |
33 | ///Animation delay
34 | ///
35 | ///[default is 0]
36 | final double intervalStart;
37 |
38 | ///Animation delay
39 | ///
40 | ///[default is 1]
41 | final double intervalEnd;
42 |
43 | ///Animation Curve
44 | ///
45 | ///[default is Curves.fastOutSlowIn]
46 | final Curve curve;
47 |
48 | ///This widget will be animated
49 | final Widget child;
50 |
51 | @override
52 | Widget build(BuildContext context) {
53 | return TweenAnimationBuilder(
54 | tween: Tween(begin: begin, end: end),
55 | duration: duration,
56 | curve: Interval(intervalStart, intervalEnd, curve: curve),
57 | child: child,
58 | builder: (BuildContext context, double? value, Widget? child) {
59 | return Transform.scale(
60 | scale: value!,
61 | child: child,
62 | );
63 | },
64 | );
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/size_animation/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Scale Animation
7 |
8 |
9 |
10 |
11 | https://user-images.githubusercontent.com/57817746/188716593-e5db801e-569f-4230-820e-c22f8ee73dfd.mov
12 |
--------------------------------------------------------------------------------
/size_animation/size_animation.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class SizeAnimation extends StatefulWidget {
4 | const SizeAnimation({Key? key}) : super(key: key);
5 |
6 | @override
7 | State createState() => _SizeAnimationState();
8 | }
9 |
10 | class _SizeAnimationState extends State {
11 | double _size = 300;
12 |
13 | @override
14 | Widget build(BuildContext context) {
15 | return Scaffold(
16 | body: Center(
17 | child: GestureDetector(
18 | onTap: () {
19 | setState(() {
20 | _size = _size == 300 ? 100 : 300;
21 | });
22 | },
23 | child: Container(
24 | color: Colors.white,
25 | child: AnimatedSize(
26 | curve: Curves.easeIn,
27 | child: FlutterLogo(
28 | size: _size,
29 | ),
30 | duration: Duration(seconds: 1),
31 | ),
32 | ),
33 | ),
34 | ),
35 | );
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/slider_animation/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Slider Animation
7 |
8 |
9 |
10 |
11 | https://user-images.githubusercontent.com/57817746/189345052-3e9157b8-913b-4f0e-a1aa-3432ba40fc86.mov
12 |
13 |
--------------------------------------------------------------------------------
/slider_animation/adapter_view.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_animate/flutter_animate.dart';
3 |
4 | class AdapterView extends StatelessWidget {
5 | const AdapterView({Key? key}) : super(key: key);
6 |
7 | @override
8 | Widget build(BuildContext context) {
9 | // example of driving an animation with a ValueNotifier
10 |
11 | // create the ValueNotifier:
12 | ValueNotifier notifier = ValueNotifier(0);
13 |
14 | // create an overly elaborate animation using ValueNotifierAdapter,
15 | // and wire up a Slider to update the ValueNotifier
16 | Widget panel = Container(
17 | color: const Color(0xFF2A2B2F),
18 | child: Column(children: [
19 | const SizedBox(height: 32),
20 | const Text(
21 | 'Slider Driven Animation',
22 | style: TextStyle(
23 | fontSize: 36,
24 | fontWeight: FontWeight.bold,
25 | height: 1,
26 | ),
27 | textAlign: TextAlign.center,
28 | )
29 | .animate(adapter: ValueNotifierAdapter(notifier))
30 | .blur(end: 16)
31 | .scale(begin: 1, end: 2)
32 | .tint(color: const Color(0xFF80DDFF))
33 | .fadeOut(curve: Curves.easeInExpo),
34 |
35 | // Slider:
36 | AnimatedBuilder(
37 | animation: notifier,
38 | builder: (_, __) => Slider(
39 | activeColor: const Color(0xFF80DDFF),
40 | value: notifier.value,
41 | onChanged: (value) => notifier.value = value,
42 | ),
43 | )
44 | ]),
45 | );
46 |
47 | // example driving animations with a ScrollController
48 |
49 | // create the scroll controller:
50 | ScrollController scrollController = ScrollController();
51 |
52 | // create some dummy items for the list:
53 | List items = [
54 | const Text(
55 | 'Scroll driven animation',
56 | style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18),
57 | )
58 | ];
59 | for (int i = 0; i < 100; i++) {
60 | items.add(Text('item $i', style: const TextStyle(height: 2.5)));
61 | }
62 | // layer the indicators under the list, and assign the ScrollController to
63 | // the list, and both animations (via ScrollAdapter):
64 | Widget list = Stack(
65 | children: [
66 | Container(
67 | height: 64,
68 | decoration: const BoxDecoration(
69 | gradient: LinearGradient(
70 | begin: Alignment.topCenter,
71 | end: Alignment.bottomCenter,
72 | colors: [Color(0x8080DDFF), Colors.transparent]),
73 | ),
74 | )
75 | .animate(adapter: ScrollAdapter(scrollController, end: 500)) //
76 | .fadeIn(),
77 |
78 | // bottom indicator:
79 | Align(
80 | alignment: Alignment.bottomCenter,
81 | child: Container(
82 | height: 64,
83 | decoration: const BoxDecoration(
84 | gradient: LinearGradient(
85 | begin: Alignment.bottomCenter,
86 | end: Alignment.topCenter,
87 | colors: [Color(0x8080DDFF), Colors.transparent],
88 | ),
89 | ),
90 | )
91 | .animate(adapter: ScrollAdapter(scrollController, begin: -500))
92 | .fadeOut(),
93 | ),
94 |
95 | // the list (with the scrollController assigned):
96 | ListView(
97 | padding: const EdgeInsets.all(24.0),
98 | controller: scrollController,
99 | children: items,
100 | ),
101 | ],
102 | );
103 |
104 | return Column(
105 | children: [
106 | panel,
107 | Flexible(child: list),
108 | ],
109 | );
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/widgets_animation/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Widgets Animations
7 |
8 |
9 |
10 |
11 | https://user-images.githubusercontent.com/57817746/189347999-84e06a6a-e3e3-4bb9-bcf1-5e27a590cb1c.mov
12 |
13 |
--------------------------------------------------------------------------------
/widgets_animation/everything_view.dart:
--------------------------------------------------------------------------------
1 | // Kitchen sink view of all Effects
2 |
3 | import 'dart:math';
4 |
5 | import 'package:flutter/material.dart';
6 | import 'package:flutter_animate/flutter_animate.dart';
7 |
8 | class EverythingView extends StatelessWidget {
9 | const EverythingView({Key? key}) : super(key: key);
10 |
11 | @override
12 | Widget build(BuildContext context) {
13 | return LayoutBuilder(
14 | builder: (_, box) => GridView.count(
15 | crossAxisCount: (box.maxWidth / 128).floor(),
16 | childAspectRatio: 0.8,
17 | children: [
18 | // these are in alphabetic order according to their classes
19 | // ex. BlurEffect defines both blur and unblur.
20 |
21 | tile("blur", a.blur()),
22 | tile("unblur", a.unblur()),
23 |
24 | // callback?
25 |
26 | tile("custom", a.custom(builder: (_, val, child) {
27 | val = val * pi * 2 - pi / 2;
28 | return Transform.translate(
29 | offset: Offset(cos(val) * 24, sin(val) * 24),
30 | child: Transform.scale(scale: 0.66, child: child),
31 | );
32 | })),
33 |
34 | tile("fadeIn", a.fadeIn()),
35 | tile("fadeOut", a.fadeOut()),
36 |
37 | // listen?
38 |
39 | tile("move", a.move()),
40 |
41 | tile("rotate", a.rotate()),
42 |
43 | tile("saturate", a.saturate()),
44 | tile("desaturate", a.desaturate()),
45 |
46 | tile("scale", a.scale()),
47 |
48 | tile("shake", a.shake()),
49 | tile("shakeX", a.shakeX()),
50 | tile("shakeY", a.shakeY()),
51 |
52 | tile("shimmer", a.shimmer()),
53 |
54 | tile("slide", a.slide()),
55 |
56 | tile("swap", a.swap(builder: (_, __) => const Text("HELLO!"))),
57 | tile("swap (child)", a.swap(builder: (_, child) {
58 | return Opacity(opacity: 0.5, child: child!);
59 | })),
60 |
61 | // then?
62 |
63 | tile("tint", a.tint()),
64 | tile("untint", a.untint()),
65 |
66 | tile("toggle", a.toggle(builder: (_, b, child) {
67 | return Container(
68 | color: b ? Colors.purple : Colors.yellow,
69 | padding: const EdgeInsets.all(8),
70 | child: child,
71 | );
72 | })),
73 |
74 | tile("hide", a.hide()),
75 | tile("show", a.show()),
76 | ],
77 | ),
78 | );
79 | }
80 |
81 | // this returns a ready to use Animate instance targeting a `box` (see below)
82 | // it uses empty effects to set default delay/duration values (750 & 1500ms)
83 | // and a total duration (3000ms), so there is a 750ms pause at the end.
84 | Animate get a => box
85 | .animate(onPlay: (controller) => controller.repeat())
86 | .effect(duration: 3000.ms) // this "pads out" the total duration
87 | .effect(delay: 750.ms, duration: 1500.ms); // set defaults
88 |
89 | // simple square box with a gradient to use as the target for animations.
90 | Widget get box => Container(
91 | decoration: const BoxDecoration(
92 | gradient: LinearGradient(
93 | colors: [Colors.red, Colors.green, Colors.blue],
94 | begin: Alignment.topLeft,
95 | end: Alignment.bottomRight,
96 | ),
97 | ),
98 | width: 64,
99 | height: 64,
100 | );
101 |
102 | // grid tile. Naming should be `buildTile`, but going for brevity.
103 | Widget tile(String label, Widget demo) => Container(
104 | margin: const EdgeInsets.all(4),
105 | color: Colors.black12,
106 | height: 160,
107 | child: Column(
108 | children: [
109 | Flexible(child: Center(child: demo)),
110 | Container(
111 | color: Colors.black12,
112 | height: 32,
113 | alignment: Alignment.center,
114 | child: Text(label, style: const TextStyle(fontSize: 12)),
115 | )
116 | ],
117 | ),
118 | );
119 | }
120 |
--------------------------------------------------------------------------------