Announcing EzAnimation
Simplify Animations in Flutter!
Flutter offers stunning simplicity in aspects like building UI and the overall process of app development. Some sorts of animations such as implicit animations are also very easy to use and do not require any knowledge of animating objects. However, building explicit animations in the normal way is a concern I have often heard and I decided to do something about it.
Package: https://pub.dev/packages/ezanimation
The Current Situation
Let’s first look at a normal Flutter animation that animates a square from size 0 to 100.0 to establish the problem:
class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
AnimationController _controller;
Animation animation;
@override
void initState() {
super.initState();
_controller = AnimationController(vsync: this, duration: Duration(seconds: 1));
animation = Tween(begin: 0.0, end: 100.0).animate(_controller);
_controller.forward();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: AnimatedBuilder(
animation: animation,
builder: (context, snapshot) {
return Container(
color: Colors.blue,
width: animation.value,
height: animation.value,
);
},
),
),
);
}
}
Creating an explicit animation has cognitive overhead because many things are required to work together. Developers have questions and feedback such as:
- What is the SingleTickerProviderStateMixin?
- Why are controllers and animations separate?
- Creating a Curved animation is hard
- Creating a sequence is not straightforward
Introducing EzAnimation
Here’s the most basic possible animation using EzAnimation doing the same thing above:
Define
var animation = EzAnimation(0.0, 100.0, Duration(seconds: 1));
Start:
animation.start();
Observe:
AnimatedBuilder(
animation: animation,
builder: (context, snapshot) {
return Container(
color: Colors.blue,
width: animation.value,
height: animation.value,
);
},
),
No Ticker is required here, no AnimationController is required here, no Tween is required here, and it is very easy to supply a curve to the animation as will be shown later. (Note that this is not the most efficient type of animation, more details on that later.)
The complete code for this equivalent to the one shown in the first section is:
class _MyHomePageState extends State<MyHomePage> {
var animation = EzAnimation(0.0, 100.0, Duration(seconds: 1));
@override
void initState() {
super.initState();
animation.start();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: AnimatedBuilder(
animation: animation,
builder: (context, snapshot) {
return Container(
color: Colors.blue,
width: animation.value,
height: animation.value,
);
},
),
),
);
}
}
When multiple animations are involved, this is much easier to handle than to use multiple controllers, animations and Tweens.
Going in Deeper
Let us look at all the features and best practices associated with using EzAnimation.
Declaration
Method 1: Simple
var animation = EzAnimation(0.0, 100.0, Duration(seconds: 1));
This is easy to define and does not rely upon a TickerProviderStateMixin, however, it needs to be manually stopped when navigating away as otherwise, it animates to completion regardless (Thanks to Remi Rousselet for pointing out the issue).
Method 2: Context
var animation = EzAnimation(0.0, 100.0, Duration(seconds: 1), context: context);
Passing in a BuildContext gives an option of what to do when you navigate away. By default, it stops and resets the animation. You can also change this by passing in an OnNavigate value:
var animation = EzAnimation(0.0, 100.0, Duration(seconds: 1), context: context, onNavigate: OnNavigate.pauseAnimation);
This defines the behaviour of the animation when you navigate away. Note that when the animation is paused, it needs to be manually restarted.
Method 3: Vsync
You can also directly pass in a vsync parameter which takes care of your animation like a normal animation:
var animation = EzAnimation(0.0, 100.0, Duration(seconds: 1), vsync: this);
Note that in this case, you will need to add a TickerProviderStateMixin to your state. Also, onNavigate does not work with vsync since the Navigator takes care of the animation for you.
Using CurvedAnimations
Adding a curve to an animation is easy with EzAnimation:
var animation = EzAnimation(0.0, 100.0, Duration(seconds: 1), curve: Curves.bounceInOut);
You can also add a reverse curve with:
var animation = EzAnimation(0.0, 100.0, Duration(seconds: 1), curve: Curves.bounceInOut, reverseCurve: Curves.easeInOut);
Making an Animation Sequence
When an animation needs to perform multiple steps, you can use EzAnimation.sequence() like this:
var animation = EzAnimation.sequence([
SequenceItem(0.0, 100.0),
SequenceItem(100.0, 50.0, weight: 2.0),
], Duration(seconds: 1));
You can pass in SequenceItems and also weights: here, the animation goes from 0 to 100 in 1/3rd of the time and then back to 50 in 2/3rds.
Using a Custom Tween
When you need to use something like a ColorTween, you can use EzAnimation.tween() to supply your own Tween:
var animation = EzAnimation.tween(ColorTween(begin: Colors.red, end: Colors.blue), Duration(seconds: 1));
Using a Custom TweenSequence
Similarly, you can also supply your own TweenSequence with EzAnimation.tweenSequence() like:
var animation = EzAnimation.tweenSequence(TweenSequence([
TweenSequenceItem(tween: ColorTween(begin: Colors.red, end: Colors.blue), weight: 1.0),
TweenSequenceItem(tween: ColorTween(begin: Colors.blue, end: Colors.red), weight: 1.0),
]), Duration(seconds: 3));
Looking Ahead
Going forward, I intend to add more functionality and make it even easier to make more complex animations with less code and a way to chain different types of animations together.
Get the package at:
If you wish to contribute to the code:
Note that the more complex ways of the Flutter animation framework are the most efficient way to animate things, this is an attempt to simplify the process or at least provide an equivalent with the smallest performance hit.
That’s it for this article! I hope you enjoyed it and leave a few claps if you did. Follow me for more Flutter articles and comment for any feedback you might have about this article.