
Flutter has a reputation for allowing developers to build beautiful animated UIs and it's rightfully so. While you can build absolutely everything with just default Flutter classes and widgets, it sometimes gets way too tedious and time consuming to do so. Let's see how to make implementing even the most complex animations a breeze.
The simple_animations is all about... simplifying animations! There are multiple areas of animations where this package provides an easier way out. We're going to focus on one of them - the timeline tween.
You should already have a solid grasp of how animations work in Flutter to follow along with this tutorial. If you need to brush up on the absolute basics, feel free to learn from this tutorial. To learn about the default Flutter's way of simplifying animations at least a bit, you can take a look at another tutorial of mine.
Default animations

We're going to start off with a project that contains an already implemented staggered animation snatched and modified a bit from the Flutter documentation. You can get up and running so that you can follow along with this tutorial by cloning the starter project linked above.
This is how the app looks like. By tapping on the screen, you toggle the animation to go forward and then backward.
So how does the default animation code look like and where can it be improved? Just from a brief glance, you can see that the following code is quite long and there are also a lot of Animation fields in the class!
main.dart
class StaggerDemo extends StatefulWidget {
@override
_StaggerDemoState createState() => _StaggerDemoState();
}
class _StaggerDemoState extends State<StaggerDemo>
with TickerProviderStateMixin {
AnimationController controller;
Animation<double> opacity;
Animation<double> width;
Animation<double> height;
Animation<EdgeInsets> padding;
Animation<BorderRadius> borderRadius;
Animation<Color> color;
@override
void initState() {
super.initState();
controller = AnimationController(
duration: const Duration(milliseconds: 2000),
vsync: this,
);
opacity = Tween<double>(
begin: 0.0,
end: 1.0,
).animate(
CurvedAnimation(
parent: controller,
curve: Interval(
0.0,
0.100,
curve: Curves.ease,
),
),
);
width = Tween<double>(
begin: 50.0,
end: 150.0,
).animate(
CurvedAnimation(
parent: controller,
curve: Interval(
0.125,
0.250,
curve: Curves.ease,
),
),
);
height = Tween<double>(begin: 50.0, end: 150.0).animate(
CurvedAnimation(
parent: controller,
curve: Interval(
0.250,
0.375,
curve: Curves.ease,
),
),
);
padding = EdgeInsetsTween(
begin: const EdgeInsets.only(bottom: 16.0),
end: const EdgeInsets.only(bottom: 75.0),
).animate(
CurvedAnimation(
parent: controller,
curve: Interval(
0.250,
0.375,
curve: Curves.ease,
),
),
);
borderRadius = BorderRadiusTween(
begin: BorderRadius.circular(4.0),
end: BorderRadius.circular(75.0),
).animate(
CurvedAnimation(
parent: controller,
curve: Interval(
0.375,
0.500,
curve: Curves.ease,
),
),
);
color = ColorTween(
begin: Colors.indigo[100],
end: Colors.orange[400],
).animate(
CurvedAnimation(
parent: controller,
curve: Interval(
0.500,
0.750,
curve: Curves.ease,
),
),
);
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Staggered Animation'),
),
body: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
if (controller.status == AnimationStatus.dismissed) {
controller.forward();
} else if (controller.status == AnimationStatus.completed) {
controller.reverse();
}
},
child: Center(
child: Container(
width: 300.0,
height: 300.0,
decoration: BoxDecoration(
color: Colors.black.withOpacity(0.1),
border: Border.all(
color: Colors.black.withOpacity(0.5),
),
),
child: AnimatedBuilder(
animation: controller,
builder: _buildAnimation,
),
),
),
),
);
}
Widget _buildAnimation(BuildContext context, Widget child) {
return Container(
padding: padding.value,
alignment: Alignment.bottomCenter,
child: Opacity(
opacity: opacity.value,
child: Container(
width: width.value,
height: height.value,
decoration: BoxDecoration(
color: color.value,
border: Border.all(
color: Colors.indigo[300],
width: 3.0,
),
borderRadius: borderRadius.value,
),
),
),
);
}
}
void main() {
runApp(MaterialApp(home: StaggerDemo()));
}Aside from the sheer number of the Animation fields, notice how the Interval curves are defined. Staggered animations are made possible by running on a certain interval of the parent animation. The parent still runs from 0 to 1 continuously as usual, but it's precisely the Interval curve which makes the animation run only between 0.25 and 0.5, let's say.
The problem lies with the interval beginnings and ends being defined with absolute values (as opposed to relative values). Let's say you want to make the very first opacity interval longer. Well, then you'd need to manually edit all of the intervals coming after it to account for the changed end time of the opacity.
double opacityStart and opacityEnd. The interval following immediately after that (width) would have the widthStart set to opacityEnd + 0.25...The last issue is that we're manually instantiating and then disposing of an AnimationController. While controllers are in no way evil, it's good to hide them behind an abstractions whenever you can.
All of these problems can be solved with the simple_animations package. Let's start with the most pressing issue - absolute intervals. But first...
Adding dependencies
In addition to depending on the simple_animations package, we're also going to add a dependency to supercharged. This adds some nice extensions for creating Tweens and Durations but it's in no way necessary to use simple_animations.
pubspec.yaml
dependencies:
flutter:
sdk: flutter
simple_animations: ^2.5.1
supercharged: ^1.12.0TimelineTween

In the default Flutter approach to animations, we did the following for every single property we wanted to animate:
- Create a
Tween - Animate or "drive" that
Tweenwith aCurvedAnimationwhose parent is the singleAnimationControllerwe have in the widget. - Set the curve for the
CurvedAnimationto be anIntervalcurve, set the begin and end times (or rather fractions of the 0 to 1 progression which theAnimationControlleris going through) - Change the curve during the interval from
Curves.lineartoCurves.ease
With the TimelineTween, we will have a single top-level tween encompassing all of the individual Tweens for individual properties. This vastly reduces the number of fields we have to keep track of. Additionally, this tween makes it easy and clutter-free to define relative intervals.
Animated properties enum
Since we'll now have a single TimelineTween encompass all of the individual property Tweens, we need to have a way to tell which property the Tween belongs to. We can do that with an enum.
main.dart
enum AnimProps {
opacity,
width,
height,
padding,
borderRadius,
color,
}With this enum created, you can now delete all of the Animation fields and also their initializations from initState. We're now going to have just one animation field, its generic parameter being a TimelineValue<AnimProps>. This is just a simple container class that's produced by the TimelineTween which contains all the individual animated properties' values.
Also, notice the supercharged import. We're going to need it in a little while.
main.dart
import 'package:simple_animations/simple_animations.dart';
import 'package:supercharged/supercharged.dart';
...
class _StaggerDemoState extends State<StaggerDemo>
with TickerProviderStateMixin {
AnimationController controller;
Animation<TimelineValue<AnimProps>> animation;
@override
void initState() {
super.initState();
controller = AnimationController(
duration: const Duration(milliseconds: 2000),
vsync: this,
);
// TODO: Set the animation by driving a TimelineTween
}
...
}Scenes and properties

Staggered animations are handled using scenes. A scene defines a span of time in which the properties being animated within that scene are going to be updated with new values. In a way, it's like the Interval curve from default Flutter but a scene can be used to animate multiple properties, not just a single one.
Since we've previously had multiple Intervals with different start and end times, we're also going to have multiple scenes. Let's start with the one that will animate only a single property - opacity.
Note that we're using an extension property so that we can write 0.milliseconds instead of Duration(milliseconds: 0).
main.dart
@override
void initState() {
super.initState();
...
animation = TimelineTween()
// Opacity
.addScene(
begin: 0.milliseconds,
end: 100.milliseconds,
curve: Curves.ease,
)
// Animate the opacity property from 0 to 1 within this scene
.animate(AnimProps.opacity, tween: Tween(begin: 0, end: 1))
// We'll chain more scenes here...
}This first scene is defined in absolute terms - we've firmly defined its begin and end times. This is fine since it's the very first scene and while we could create absolute scenes even for all the other properties, we'd be in the same situation as with the default Flutter Interval curves. That's why we want to create all of the subsequent scenes using the addSubsequentScene method.
These calls are chained one onto another - the scene is relative to the previous one, after all. Also, there are no begin and end times but only duration and delay instead.
main.dart
@override
void initState() {
super.initState();
...
animation = TimelineTween<AnimProps>()
// Opacity - defined with absolute begin and end times
.addScene(
begin: 0.milliseconds,
end: 100.milliseconds,
curve: Curves.ease,
)
.animate(AnimProps.opacity, tween: Tween(begin: 0.0, end: 1.0))
// Width - this scene is relative to the previous one
// There's no begin and end, only delay and duration
.addSubsequentScene(
delay: 25.milliseconds,
duration: 125.milliseconds,
curve: Curves.ease,
)
.animate(AnimProps.width, tween: Tween(begin: 50.0, end: 150.0))
// Height and Padding
.addSubsequentScene(
duration: 125.milliseconds,
curve: Curves.ease,
)
.animate(AnimProps.height, tween: Tween(begin: 50.0, end: 150.0))
.animate(
AnimProps.padding,
tween: EdgeInsetsTween(
begin: const EdgeInsets.only(bottom: 16.0),
end: const EdgeInsets.only(bottom: 75.0),
),
)
// BorderRadius
.addSubsequentScene(
duration: 125.milliseconds,
curve: Curves.ease,
)
.animate(
AnimProps.borderRadius,
tween: BorderRadiusTween(
begin: BorderRadius.circular(4.0),
end: BorderRadius.circular(75.0),
),
)
// Color
.addSubsequentScene(
duration: 250.milliseconds,
curve: Curves.ease,
)
.animate(
AnimProps.color,
tween: ColorTween(
begin: Colors.indigo[100],
end: Colors.orange[400],
),
)
// Get the Tween so that we can drive it with the AnimationController
.parent
.animatedBy(controller);
}Aside from adding scenes and animating properties, we also need to drive the TimelineTween with the AnimationController. That's done on the last two lines above.
Rebuilding the UI
Of course, condensing everything into just one animation field broke the code responsible for rebuilding the widget tree in the AnimatedBuilder. We now need to extract the values for the individual properties, such as opacity or width. We're again going to use our AnimProps enum for that.
main.dart
Widget _buildAnimation(BuildContext context, Widget child) {
return Container(
padding: animation.value.get(AnimProps.padding),
alignment: Alignment.bottomCenter,
child: Opacity(
opacity: animation.value.get(AnimProps.opacity),
child: Container(
width: animation.value.get(AnimProps.width),
height: animation.value.get(AnimProps.height),
decoration: BoxDecoration(
color: animation.value.get(AnimProps.color),
border: Border.all(
color: Colors.indigo[300],
width: 3.0,
),
borderRadius: animation.value.get(AnimProps.borderRadius),
),
),
),
);
}After this last change, we have now successfully refactored the staggered animation using the simple_animations package. The TimelineTween makes the code more maintainable and also easier to write.

I love your tutorials Matt, i’m from Brazil, but your content has a big value for me. Thankss for this
Somebody essentially help to make significantly articles I’d state. This is the first time I frequented your web page and up to now? I surprised with the research you made to make this actual post incredible. Fantastic job!
Hey there, You have done a fantastic job. I will certainly digg it and personally recommend to my friends. I’m confident they’ll be benefited from this site.
you are truly a just right webmaster. The site loading speed is incredible. It kind of feels that you’re doing any distinctive trick. In addition, The contents are masterwork. you have done a great activity in this matter!
Usually I do not read article on blogs, however I would like to say that this write-up very compelled me to take a look at and do it! Your writing style has been amazed me. Thank you, very nice article.
Attractive section of content. I just stumbled upon your blog and in accession capital to assert that I get actually enjoyed account your blog posts. Anyway I will be subscribing to your augment and even I achievement you access consistently fast.
Hi, i think that i saw you visited my web site thus i came to ?eturn the favor텶 am attempting to find things to improve my web site!I suppose its ok to use some of your ideas!!
Usually I do not read article on blogs, however I would like to say that this write-up very compelled me to take a look at and do so! Your writing taste has been amazed me. Thanks, quite nice post.
you are in reality a just right webmaster. The site loading velocity is incredible. It seems that you are doing any unique trick. In addition, The contents are masterwork. you have performed a wonderful task on this topic!
Thanks, I have recently been looking for info about this subject for a while and yours is the greatest I have discovered so far. However, what in regards to the bottom line? Are you certain in regards to the supply?
Excellent blog here! Also your website loads up very fast! What web host are you using? Can I get your affiliate link to your host? I wish my web site loaded up as quickly as yours lol
I do trust all the ideas you’ve presented in your post. They are really convincing and will definitely work. Nonetheless, the posts are too short for newbies. May just you please lengthen them a bit from next time? Thank you for the post.
hello!,I really like your writing so a lot! share we keep up a correspondence extra approximately your post on AOL? I need an expert in this house to unravel my problem. May be that is you! Taking a look ahead to see you.
I just could not depart your web site prior to suggesting that I really loved the usual info an individual supply in your visitors? Is gonna be back regularly to check up on new posts.
i just wanted to drop a note of appreciation for your blog post. it’s evident that you’ve done your research, and the effort you put into it is commendable. thank you for enriching our knowledge..
Bwer Pipes: Empowering Iraqi Farmers with Reliable Irrigation Solutions: Join the countless farmers across Iraq who trust Bwer Pipes for their irrigation needs. Our state-of-the-art sprinkler systems and durable pipes ensure efficient water distribution, helping you achieve maximum crop yields while conserving water resources. Visit Bwer Pipes
Bwer Pipes: Pioneering Irrigation Excellence in Iraq: Explore Bwer Pipes for cutting-edge irrigation solutions that set the standard for excellence in Iraqi agriculture. Our advanced sprinkler technology and durable pipes deliver precise water distribution, enabling farmers to achieve optimal crop yields and sustainable farming practices. Explore Bwer Pipes
Can you be more specific about the content of your article? After reading it, I still have some doubts. Hope you can help me.
Vitazen Keto I do not even understand how I ended up here, but I assumed this publish used to be great
you are in reality a good webmaster The website loading velocity is amazing It sort of feels that youre doing any distinctive trick Also The contents are masterwork you have done a fantastic job in this topic
I just could not leave your web site before suggesting that I really enjoyed the standard information a person supply to your visitors Is gonna be again steadily in order to check up on new posts
Thank you for the good writeup It in fact was a amusement account it Look advanced to far added agreeable from you However how could we communicate
Just wish to say your article is as surprising The clearness in your post is just cool and i could assume youre an expert on this subject Fine with your permission allow me to grab your RSS feed to keep updated with forthcoming post Thanks a million and please keep up the enjoyable work
helloI really like your writing so a lot share we keep up a correspondence extra approximately your post on AOL I need an expert in this house to unravel my problem May be that is you Taking a look ahead to see you
Real Estate I do not even understand how I ended up here, but I assumed this publish used to be great
BaddieHub This is really interesting, You’re a very skilled blogger. I’ve joined your feed and look forward to seeking more of your magnificent post. Also, I’ve shared your site in my social networks!
Its like you read my mind You appear to know so much about this like you wrote the book in it or something I think that you can do with a few pics to drive the message home a little bit but other than that this is fantastic blog A great read Ill certainly be back
Its like you read my mind You appear to know so much about this like you wrote the book in it or something I think that you can do with a few pics to drive the message home a little bit but other than that this is fantastic blog A great read Ill certainly be back
Somebody essentially lend a hand to make significantly articles Id state That is the very first time I frequented your website page and up to now I surprised with the research you made to make this actual submit amazing Wonderful task
Hello i think that i saw you visited my weblog so i came to Return the favore Im trying to find things to improve my web siteI suppose its ok to use some of your ideas
Pink Withney I truly appreciate your technique of writing a blog. I added it to my bookmark site list and will
Thank you for your sharing. I am worried that I lack creative ideas. It is your article that makes me full of hope. Thank you. But, I have a question, can you help me?
dodb buzz Hi there to all, for the reason that I am genuinely keen of reading this website’s post to be updated on a regular basis. It carries pleasant stuff.
BYU Cougars For the reason that the admin of this site is working, no uncertainty very quickly it will be renowned, due to its quality contents.
Mating Press This is my first time pay a quick visit at here and i am really happy to read everthing at one place
Masalqseen I really like reading through a post that can make men and women think. Also, thank you for allowing me to comment!
Fran Candelera I am truly thankful to the owner of this web site who has shared this fantastic piece of writing at at this place.
Fran Candelera I do not even understand how I ended up here, but I assumed this publish used to be great
Blue Techker You’re so awesome! I don’t believe I have read a single thing like that before. So great to find someone with some original thoughts on this topic. Really.. thank you for starting this up. This website is something that is needed on the internet, someone with a little originality!
Blue Techker Good post! We will be linking to this particularly great post on our site. Keep up the great writing
Thinker Pedia I really like reading through a post that can make men and women think. Also, thank you for allowing me to comment!
Thinker Pedia Good post! We will be linking to this particularly great post on our site. Keep up the great writing
Mangaclash I very delighted to find this internet site on bing, just what I was searching for as well saved to fav
Jinx Manga Pretty! This has been a really wonderful post. Many thanks for providing these details.
Back Magazin I very delighted to find this internet site on bing, just what I was searching for as well saved to fav
Blue Techker Pretty! This has been a really wonderful post. Many thanks for providing these details.
SOUNDOS-SEGC.
I don’t think the title of your article matches the content lol. Just kidding, mainly because I had some doubts after reading the article.
Glue Dream strain I really like reading through a post that can make men and women think. Also, thank you for allowing me to comment!
Revolutionize your weighing needs with BWER, Iraq’s top provider of weighbridge systems, featuring unparalleled accuracy, durability, and expert installation services.
NY weekly For the reason that the admin of this site is working, no uncertainty very quickly it will be renowned, due to its quality contents.
Noodlemagazine I like the efforts you have put in this, regards for all the great content.
Hello Neat post Theres an issue together with your site in internet explorer would check this IE still is the marketplace chief and a large element of other folks will leave out your magnificent writing due to this problem
Noodlemagazine This is really interesting, You’re a very skilled blogger. I’ve joined your feed and look forward to seeking more of your magnificent post. Also, I’ve shared your site in my social networks!
Hi Neat post There is a problem along with your website in internet explorer would test this IE still is the market chief and a good section of other folks will pass over your magnificent writing due to this problem
b98NC52J2pV
My brother recommended I might like this web site He was totally right This post actually made my day You cannt imagine just how much time I had spent for this information Thanks
hentairead Nice post. I learn something totally new and challenging on websites
hentairead You’re so awesome! I don’t believe I have read a single thing like that before. So great to find someone with some original thoughts on this topic. Really.. thank you for starting this up. This website is something that is needed on the internet, someone with a little originality!
Mitolyn For the reason that the admin of this site is working, no uncertainty very quickly it will be renowned, due to its quality contents.
Puraburn I very delighted to find this internet site on bing, just what I was searching for as well saved to fav
Wedding Venues In GT Karnal Road. Wedding Venues GT Karnal Road Book Farmhouses, Banquet Halls, Hotels for Party places at GT Karnal Road Ever thought of enjoying a multi-theme Wedding Function while being at just one destination? If not then you must not have visited Farmhouses.
wedding venues in gt karnal road Book Farmhouses, Banquet Halls, Hotels for Party places at GT Karnal Road Ever thought of enjoying a multi-theme Wedding Function while being at just one destination? If no then you must not have visited Farmhouses. Wedding Venues GT Karnal Road
Your point of view caught my eye and was very interesting. Thanks. I have a question for you.
Thanks for sharing. I read many of your blog posts, cool, your blog is very good. https://www.binance.com/en-NG/register?ref=YY80CKRN