Flutter Animation

This is the most important concept in Flutter. When you tap on a button or go from one page to another page the movements all are animations. Animations increase user experiences and the applications become more interactive.

Flutter provides awesome support for animation and we can separate it into two types as given below:

  • Tween Animation
  • Physics-based Animation

Tween Animation

It’s a short form for in-betweening. It is to define the start and endpoint of animation on screen. Animation begins at the start value, and completes at the end value. It provides the timeline and curve also, we can define the time and speed of transition. It provides a calculation of the transition between the start and endpoint.

Example
ColorTween {  
    begin: color.green,  
    end: color.blue,  
}     

Physics-based Animation

This type of animation allows you to make an interaction with the app feel realistic and interactive. This animation simulates real-world movements, such as to animate a widget like spring, falling, or swinging which feels like gravity. Thus, it is used to animate the responses to input/movement. An example is time of a flight, and the distance covered which will be calculated according to laws of physics.

Flutter provides two techniques for physics based animation. Which are:

  1. Implicit Animation
  2. Explicit Animation
The following figure shows the animation hierarchy in Flutter.

flutter-animation

Now, we are going to learn how to create explicit animation in Flutter. There are mainly three types of an animation, which are given below:

  1. Ticker
  2. Animation Class
  3. AnimationController

Ticker

The Ticker class sends a signal at a regular interval, i.e., around 60 times per second. You can understand it by looking at your watch, which ticks at a regular interval. At every tick, It provides a callback method with duration since the first ticks at every second, after starting.

Animation

The Animation class is a core building block of flutter animation. This is nothing else, but it represents a value of a specific type that can change over the lifetime of animation. In Flutter, the widgets that can be animated take an animation object in its parameter. This Animation object provides the information which it reads as the current value of the animation and to which it listens for changes in the values. It has two methods addListener() and addStatusListener(). When any value changes it notifies its listeners added using addListener(). Again, when the status value changes it notifies its listeners added using addStatusListener().

The most common Animation classes are:
  • Animation: It moves values between two decimal numbers over a certain duration.
  • Animation: It moves colors between two color values.
  • Animation: It imoves sizes between two size values.

Animation Controller

The animation controller allows us to control the animation of the widget. It generates new values whenever the widget is rebuilt and is ready for a new frame. For example, it helps control the start, stop, forward, or repeat of an animation. Once we created the animation controller, we can start building animations based on it, such as a reverse and a curved animation.

Syntax

Step: 1 animationController = AnimationController(vsync: this, duration: Duration(milliseconds: 2500));

Here, we need a vsync and the duration denotes the duration of the animation.

Let’s check an example to learn how to implement them

import 'package:flutter/animation.dart';  
import 'package:flutter/material.dart';  
  
void main() => runApp(MyApp());  
  
class MyApp extends StatelessWidget {  
  // This widget is the root of your application.  
  @override  
  Widget build(BuildContext context) {  
    return MaterialApp(  
      title: 'Flutter Animation',  
      theme: ThemeData(  
        // This is the theme of your application.  
        primarySwatch: Colors.blue,  
      ),  
      home: MyHomePage(),  
    );  
  }  
}  
class MyHomePage extends StatefulWidget {  
  _HomePageState createState() => _HomePageState();  
}  
class _HomePageState extends State with SingleTickerProviderStateMixin {  
  Animation animation;  
  AnimationController animationController;  
  @override  
  void initState() {  
    super.initState();  
    animationController = AnimationController(vsync: this, duration: Duration(milliseconds: 2500));  
    animation = Tween(begin: 0.0, end: 1.0).animate(animationController);  
    animation.addListener((){  
      setState((){  
        print (animation.value.toString());  
      });  
    });  
    animation.addStatusListener((status){  
      if(status == AnimationStatus.completed){  
        animationController.reverse();  
      } else if(status == AnimationStatus.dismissed) {  
        animationController.forward();  
        }  
      });  
      animationController.forward();  
    }  
  @override  
  Widget build(BuildContext context) {  
    return Center(  
      child: AnimatedLogo(  
        animation: animation,  
      )  
    );  
  }  
}  
class AnimatedLogo extends AnimatedWidget {  
  final Tween _sizeAnimation = Tween (begin: 0.0, end: 500.0);  
  AnimatedLogo({Key key, Animation animation}):super(key: key, listenable: animation);  
  @override  
  Widget build(BuildContext context) {  
    final Animation animation = listenable;  
    return Transform.scale(  
      scale: _sizeAnimation.evaluate(animation),  
      child: FlutterLogo(),  
    );  
  }  
}    
Output

When you run the application in Android Studio, you will get the output. In the screen, you will see that the Flutter logo scaling in forward and reverse direction.

flutter-animation-controller

Curved Animation

The curved animation is useful to apply a non-linear curve on the animation object. Thus, the animation’s progress is a curve.

Syntax:

Step: 1 CurvedAnimation(parent: animationController, curve: Curves.bounceOut));

Let us understand it with the previous example by making some changes.

import 'package:flutter/material.dart';  
  
void main() => runApp(MyApp());  
  
class MyApp extends StatelessWidget {  
  // This widget is the root of your application.  
  @override  
  Widget build(BuildContext context) {  
    return MaterialApp(  
      title: 'Flutter Application',  
      theme: ThemeData(  
        primarySwatch: Colors.orange,  
      ),  
      home: HeroAnimation(title: 'Hero Animation'),  
    );  
  }  
}  
  
class HeroAnimation extends StatefulWidget {  
  HeroAnimation({Key key, this.title}) : super(key: key);  
  final String title;  
  
  @override  
  _HeroAnimationState createState() => _HeroAnimationState();  
}  
  
class _HeroAnimationState extends State {  
  
  Widget _greenRectangle() {  
    return Container(  
      width: 75,  
      height: 75,  
      color: Colors.green,  
    );  
  }  
  
  Widget _detailPageRectangle() {  
    return Container(  
      width: 150,  
      height: 150,  
      color: Colors.red,  
    );  
  }  
  
  @override  
  Widget build(BuildContext context) {  
    return Scaffold(  
      appBar: AppBar(  
        title: Text(widget.title),  
      ),  
      body: buildDemoWidget(context),  
    );  
  }  
  
  Widget buildDemoWidget(BuildContext context) {  
    return Center(  
      child: Column(  
        crossAxisAlignment: CrossAxisAlignment.start,  
        children: [  
          SizedBox(  
            height: 30.0,  
          ),  
          ListTile(  
            leading: GestureDetector(  
              child: Hero(  
                tag: 'hero-rectangle',  
                child: _greenRectangle(),  
              ),  
              onTap: () => _gotoDetailsPage(context),  
            ),  
            title: Text('Tap on the green icon rectangle to analyse hero animation transition.'),  
          ),  
        ],  
      ),  
    );  
  }  
  
  void _gotoDetailsPage(BuildContext context) {  
    Navigator.of(context).push(MaterialPageRoute(  
      builder: (ctx) => Scaffold(  
        body: Center(  
          child: Column(  
            mainAxisAlignment: MainAxisAlignment.center,  
            children: [  
              Hero(  
                tag: 'hero-rectangle',  
                child: _detailPageRectangle(),  
              ),  
              Text('This is a place where you can see details about the icon tapped at previous page.'),  
            ],  
          ),  
        ),  
      ),  
    ));  
  }  
}    
Output
flutter-hello-animation
flutter-text-animation