Sitemap

Tween Animations in Flutter

3 min readSep 11, 2019

--

Polishing UI in a mobile application is a must and animations comes first.

When Flutter comes around, its biggest promise is 60 fps smooth animations on low level mobile phones. Let’s check how to make some easy animations.

Flutter split animations in two types. I will talk about physics based animations in another post.

Tween Animations: This type has a start&end point like a timeline and we can define a curve for timing and speed.

// Tween Animation Example. Replace main.dart in a flutter project // with this codeimport 'package:flutter/material.dart';
import 'package:flutter/animation.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
_MyApp createState() => _MyApp();
}

class _MyApp extends State<MyApp> with SingleTickerProviderStateMixin {
Animation<double> animation;
AnimationController controller;

@override
void initState() {
super.initState();

controller =
AnimationController(vsync: this, duration: Duration(seconds: 2));
animation = Tween<double>(begin: 0, end: 300).animate(controller)
..addListener(() {
setState(() {});
})
..addStatusListener((status) {
if (status == AnimationStatus.completed) {
controller.reverse();
} else if (status == AnimationStatus.dismissed) {
controller.forward();
}
});

controller.forward();
}

@override
Widget build(BuildContext context) {
return MaterialApp(
home: Center(
child: Container(
color: Colors.white,
height: animation.value,
width: animation.value,
),
),
);
}

@override
void dispose() {
controller.dispose();
super.dispose();
}
}

Above dart code builds a scaling up-down white container animation loop as seen below.

I am going to try to explain some concepts in this code.

SingleTickerProviderStateMixin: This mixin allow us to use ONE animation controller in a state. If you need multiple controllers in a state we can use TickerProviderStateMixin.

AnimationController: This class will help us to control our animation with methods like reverse, forward, animateTo, animateBack. And some useful properties like isAnimating, isCompleted, isDismissed…

Tween: Tween returns an Animatable typed object but we use animate method on tween and it returns an animation typed object and with double-dot syntax we can assign it to animation variable. As you see tween has a start and end value.

vsync: This animation controller’s parameter is type of TickerProvider. We passed “this” as vsync because our SingleTickerProviderStateMixin implements TickerProvider class.

addListener: This listener fires every time the value of tween changes between min and max values. We pass setState function to listener so whenever tween value changes our widget updates itself.

addStatusListener: This listener fires when status of animation changes. With this listener we were able to loop our animation. AnimationStatus.dismissed means animation reversed and reached where it started first.

Chaining Tweens

Flutter lets us to add two or more Animatable<double> type tween to our main tween. It is practical for using tweens with curves. Addition to our code seeing below will result an elastic scale.

animation = Tween<double>(begin: 0, end: 255)
.chain(CurveTween(curve: Curves.elasticOut))
.animate(controller)
..addListener(() {
setState(() {
});
})

Tween Implementers

There are tons of Tween class implementers. You can find all of them in flutter documentation.

Let’s finish this short post with a Tween class implementer ColorTween. We can tween between two colors with this class.

// add these right after the AnimationController controller; line
Animation<Color> colorAnimation;
AnimationController colorController;
// change mixin from SingleTickerProviderStateMixin to TickerProviderStateMixin// add these codes after super.initState(); line
colorController =
AnimationController(vsync: this, duration: Duration(seconds: 2));
colorAnimation = ColorTween(begin: Colors.blueAccent, end: Colors.red).animate(colorController)
..addListener(() {
setState(() {});
})
..addStatusListener((status) {
if (status == AnimationStatus.completed) {
colorController.reverse();
} else if (status == AnimationStatus.dismissed) {
colorController.forward();
}
});
colorController.forward();
// and change color property of Container widget to colorAnimation.value

--

--

Erdoğan Bavaş
Erdoğan Bavaş

Written by Erdoğan Bavaş

Software Developer, Physics Grad.

No responses yet