preface

The essence of animation is to change what is displayed on the screen over a period of time, resulting in visual persistence.

Animation can generally be divided into two categories:

“Tween animation” : Tween animation is a kind of animation that defines in advance the starting point and end point of the object’s movement, the way of the object’s movement, the movement time, the time curve, and then the transition from the starting point to the end point.

“Physics-based animation” : Physics-based animation is a kind of animation that simulates real world motion by building a model of motion. For example, when a basketball 🏀 falls from a high place, it is necessary to establish a motion model according to its falling height, gravitational acceleration, ground rebound and other influencing factors.

Animation in Flutter

There are many types of animation in Flutter. Start with a simple example, use an AnimatedContainer control, set the animation duration, and call setState to change the desired property value. An animation is created.

animated-container

The following code

import 'package:flutter/material.dart';



class AnimatedContainerPage extends StatefulWidget {

  @override

  _AnimatedContainerPageState createState() => _AnimatedContainerPageState();

}



class _AnimatedContainerPageState extends State<AnimatedContainerPage{

  // The initial attribute value

  double size = 100;

  double raidus = 25;

  Color color = Colors.yellow;



  void _animate() {

    // Change the attribute value

    setState(() {

      size = size == 100 ? 200 : 100;

      raidus = raidus == 25 ? 100 : 25;

      color = color == Colors.yellow ? Colors.greenAccent : Colors.yellow;

    });

  }



  @override

  Widget build(BuildContext context) {

    return Scaffold(

      appBar: AppBar(title: Text('Animated Container')),

      body: Center(

        child: Column(

          mainAxisAlignment: MainAxisAlignment.center,

          children: [

            // Apply property values to AnimatedContainer

            AnimatedContainer(

              width: size,

              height: size,

              curve: Curves.easeIn,

              padding: const EdgeInsets.all(20.0),

              decoration: BoxDecoration(

                color: color,

                borderRadius: BorderRadius.circular(raidus),

              ),

              duration: Duration(seconds: 1),

              child: FlutterLogo(),

            )

].

        ),

      ),

      floatingActionButton: FloatingActionButton(

        onPressed: _animate,

        child: Icon(Icons.refresh),

      ),

    );

  }

}



Copy the code

This is an implicit animation, in addition to explicit animation, Hreo animation, interlacing animation.

Basic concept

The Flutter animation is based on the following concepts.

Animation

The Animation system in Flutter is based on an Animation object, which is an abstract class that holds the value and state of the current Animation (start, pause, forward, backward), but does not record what is displayed on the screen. UI elements run build functions by reading the value of the Animation object and listening for state changes, and then render to the screen to animate.

An Animation object will continuously generate values between two values for a period of time. The most common type is Animation

. In addition to double, there are also Animation
or Animation

, etc.

abstract class Animation<Textends Listenable implements ValueListenable<T{

  / / /...

}

Copy the code

AnimationController

Animation: an Animation object with control methods used to start, pause, end, set the Animation runtime, etc.

class AnimationController extends Animation<double>

  with AnimationEagerListenerMixin.AnimationLocalListenersMixin.AnimationLocalStatusListenersMixin 
{

  / / /...

}



AnimationController controller = AnimationController(

  vsync: this.

  duration: Duration(seconds: 10),

);

Copy the code

Tween

Used to generate different types and ranges of animation values.

class Tween<T extends dynamicextends Animatable<T{

  Tween({ this.begin, this.end });

  / / /...

}



/ / type double

Tween<double> tween = Tween<double>(begin: - 200., end: 200);



/ / color type

ColorTween colorTween = ColorTween(begin: Colors.blue, end: Colors.yellow);



// border Radius type

BorderRadiusTween radiusTween = BorderRadiusTween(

  begin: BorderRadius.circular(0.0),

  end: BorderRadius.circular(150.0),

);

Copy the code

Curve

The default animation process of a Flutter animation is uniform. The time curve can be defined as a nonlinear curve using a CurvedAnimation.

class CurvedAnimation extends Animation<doublewith AnimationWithParentMixin<double{

  / / /...

}



Animation animation = CurvedAnimation(parent: controller, curve: Curves.easeIn);

Copy the code

Ticker

Ticker is used to add a callback function for each screen refresh, TickerCallback, which is called each screen refresh. This is similar to the requestAnimationFrame method in the Web.

class Ticker {

  / / /...

}



Ticker ticker = Ticker(callback);

Copy the code

An implicit animation

Implicit animations are created using animation widgets built into the Flutter framework and are triggered by setting the start and end values of the animation. When you change the animation property value of a widget using the setState method, the framework automatically calculates an animation that transitions from the old value to the new value.

The AnimatedOpacity widget, for example, triggers animation by changing its opacity value.

opacity-toggle
import 'package:flutter/material.dart';



class OpacityChangePage extends StatefulWidget {

  @override

  _OpacityChangePageState createState() => _OpacityChangePageState();

}



class _OpacityChangePageState extends State<OpacityChangePage{

  double _opacity = 1.0;



  // Change the target value

  void _toggle() {

    _opacity = _opacity > 0 ? 0.0 : 1.0;

    setState(() {});

  }



  @override

  Widget build(BuildContext context) {

    return Scaffold(

      appBar: AppBar(title: Text('Implicit animation')),

      body: Center(

        child: AnimatedOpacity(

          // Pass in the target value

          opacity: _opacity,

          duration: Duration(seconds: 1),

          child: Container(

            width: 200.

            height: 200.

            color: Colors.blue,

          ),

        ),

      ),

      floatingActionButton: FloatingActionButton(

        onPressed: _toggle,

        child: Icon(Icons.play_arrow),

      ),

    );

  }

}



Copy the code

In addition to AnimatedOpacity, there are other built-in implicit animation widgets such as: 1. AnimatedContainer, AnimatedPadding, animatedtoy, AnimatedSwitcher, AnimatedAlign, etc.

Explicit animation

Explicit animation refers to the need to manually set the animation time, motion curve, value range of animation. Pass the value to an animation widget such as RotationTransition, and finally use an AnimationController to control the start and end of the animation.

explicit-animation
import 'dart:math';

import 'package:flutter/material.dart';



class RotationAinmationPage extends StatefulWidget {

  @override

  _RotationAinmationPageState createState() => _RotationAinmationPageState();

}



class _RotationAinmationPageState extends State<RotationAinmationPage>

    with SingleTickerProviderStateMixin 
{

  AnimationController _controller;

  Animation<double> _turns;

  bool _playing = false;



  // Control the animation state

  void _toggle() {

    if (_playing) {

      _playing = false;

      _controller.stop();

    } else {

_controller.forward().. whenComplete(() => _controller.reverse());

      _playing = true;

    }

    setState(() {});

  }



  @override

  void initState() {

    super.initState();

    // Initialize the animation controller and set the animation time

    _controller = AnimationController(

      vsync: this.

      duration: Duration(seconds: 10),

    );



    // Set the animation value range and time curve

    _turns = Tween(begin: 0.0, end: pi * 2).animate(

      CurvedAnimation(parent: _controller, curve: Curves.easeIn),

    );

  }



  @override

  void dispose() {

    super.dispose();

    _controller.dispose();

  }



  @override

  Widget build(BuildContext context) {

    return Scaffold(

      appBar: AppBar(title: Text('Show animation')),

      body: Center(

        child: RotationTransition(

          // Pass in the animation value

          turns: _turns,

          child: Container(

            width: 200.

            height: 200.

            child: Image.asset(

              'assets/images/fan.png'.

              fit: BoxFit.cover,

            ),

          ),

        ),

      ),

      floatingActionButton: FloatingActionButton(

        onPressed: _toggle,

        child: Icon(_playing ? Icons.pause : Icons.play_arrow),

      ),

    );

  }

}



Copy the code

In addition to RotationTransition, there are other display animation widgets such as FadeTransition, ScaleTransition, SizeTransition, SlideTransition, etc.

Hero animation

A Hero animation is an animation of an element moving from the old page to the new page as the page switches. The Hero animation is implemented using two Hero controls: one for the old page and one for the new page. Both Hero controls need to use the same tag property and cannot duplicate other tags.

hero-animation
/ / page 1

import 'package:flutter/material.dart';



import 'hero_animation_page2.dart';



String cake1 = 'assets/images/cake01.jpg';

String cake2 = 'assets/images/cake02.jpg';



class HeroAnimationPage1 extends StatelessWidget {

  GestureDetector buildRowItem(context, String image) {

    return GestureDetector(

      onTap: () {

        // Go to page 2

        Navigator.of(context).push(

          MaterialPageRoute(builder: (ctx) {

            return HeroAnimationPage2(image: image);

          }),

        );

      },

      child: Container(

        width: 100.

        height: 100.

        child: Hero(

          // Set the Hero tag attribute

          tag: image,

          child: ClipOval(child: Image.asset(image)),

        ),

      ),

    );

  }



  @override

  Widget build(BuildContext context) {

    return Scaffold(

      appBar: AppBar(title: Text('page 1')),

      body: Column(

        children: <Widget>[

          SizedBox(height: 40.0),

          Row(

            mainAxisAlignment: MainAxisAlignment.spaceAround,

            children: <Widget>[

              buildRowItem(context, cake1),

              buildRowItem(context, cake2),

].

          ),

].

      ),

    );

  }

}



/ / page 2

import 'package:flutter/material.dart';



class HeroAnimationPage2 extends StatelessWidget {

  final String image;



  const HeroAnimationPage2({@required this.image});



  @override

  Widget build(BuildContext context) {

    return Scaffold(

      body: CustomScrollView(

        slivers: <Widget>[

          SliverAppBar(

            expandedHeight: 400.0.

            title: Text('page 2'),

            backgroundColor: Colors.grey[200].

            flexibleSpace: FlexibleSpaceBar(

              collapseMode: CollapseMode.parallax,

              background: Hero(

                // Use the tag values passed in from page 1

                tag: image,

                child: Container(

                  decoration: BoxDecoration(

                    image: DecorationImage(

                      image: AssetImage(image),

                      fit: BoxFit.cover,

                    ),

                  ),

                ),

              ),

            ),

          ),

          SliverList(

            delegate: SliverChildListDelegate(

              <Widget>[

                Container(height: 600.0, color: Colors.grey[200]),

].

            ),

          ),

].

      ),

    );

  }

}





Copy the code

Mixed animation

Interlacing animation is an animation consisting of a series of small animations. Each mini-animation can be continuous or discontinuous, or it can overlap. The key is to use the Interval widget to set an Interval for each small animation, a value range Tween for each animation, and finally an AnimationController to control the overall animation state.

Interval inherits from Curve and sets the attributes begin and end to determine the scope of the little animation.

class Interval extends Curve {

  /// start point of animation

  final double begin;

  /// animation end point

  final double end;

  /// Animate the slow curve

  final Curve curve;



  / / /...

}



Copy the code
staggered-animation

This is an interwoven animation consisting of 5 small animations, width, height, color, rounded corners, borders, each animation has its own animation range.

staggered-animation-timeline
import 'package:flutter/material.dart';



class StaggeredAnimationPage extends StatefulWidget {

  @override

  _StaggeredAnimationPageState createState() => _StaggeredAnimationPageState();

}



class _StaggeredAnimationPageState extends State<StaggeredAnimationPage>

    with SingleTickerProviderStateMixin 
{

  AnimationController _controller;

  Animation<double> _width;

  Animation<double> _height;

  Animation<Color> _color;

  Animation<double> _border;

  Animation<BorderRadius> _borderRadius;



  void _play() {

    if (_controller.isCompleted) {

      _controller.reverse();

    } else {

      _controller.forward();

    }

  }



  @override

  void initState() {

    super.initState();



    _controller = AnimationController(

      vsync: this.

      duration: Duration(seconds: 5),

    );



    _width = Tween<double> (

      begin: 100.

      end: 300.

    ).animate(

      CurvedAnimation(

        parent: _controller,

        curve: Interval(

          0.0.

          0.2.

          curve: Curves.ease,

        ),

      ),

    );



    _height = Tween<double> (

      begin: 100.

      end: 300.

    ).animate(

      CurvedAnimation(

        parent: _controller,

        curve: Interval(

          0.2.

          0.4.

          curve: Curves.ease,

        ),

      ),

    );



    _color = ColorTween(

      begin: Colors.blue,

      end: Colors.yellow,

    ).animate(

      CurvedAnimation(

        parent: _controller,

        curve: Interval(

          0.4.

          0.6.

          curve: Curves.ease,

        ),

      ),

    );



    _borderRadius = BorderRadiusTween(

      begin: BorderRadius.circular(0.0),

      end: BorderRadius.circular(150.0),

    ).animate(

      CurvedAnimation(

        parent: _controller,

        curve: Interval(

          0.6.

          0.8.

          curve: Curves.ease,

        ),

      ),

    );



    _border = Tween<double> (

      begin: 0.

      end: 25.

    ).animate(

      CurvedAnimation(

        parent: _controller,

        curve: Interval(0.8.1.0),

      ),

    );

  }



  @override

  Widget build(BuildContext context) {

    return Scaffold(

      appBar: AppBar(title: Text('Interlace animation')),

      body: Center(

        child: AnimatedBuilder(

          animation: _controller,

          builder: (BuildContext context, Widget child) {

            return Container(

              width: _width.value,

              height: _height.value,

              decoration: BoxDecoration(

                color: _color.value,

                borderRadius: _borderRadius.value,

                border: Border.all(

                  width: _border.value,

                  color: Colors.orange,

                ),

              ),

            );

          },

        ),

      ),

      floatingActionButton: FloatingActionButton(

        onPressed: _play,

        child: Icon(Icons.refresh),

      ),

    );

  }

}



Copy the code

Physical animation

Physical animation is a kind of animation that simulates the movement of objects in the real world. It is necessary to establish the motion model of an object. Taking an object falling as an example, the motion is affected by the falling height of the object, the gravitational acceleration, the ground reaction force and other factors.

throw-animation
import 'package:flutter/material.dart';

import 'package:flutter/scheduler.dart';



class ThrowAnimationPage extends StatefulWidget {

  @override

  _ThrowAnimationPageState createState() => _ThrowAnimationPageState();

}



class _ThrowAnimationPageState extends State<ThrowAnimationPage{

  // Center height

  double y = 70.0;

  // Y-axis velocity

  double vy = 10.0;

  / / gravity

  double gravity = 0.1;

  // Ground rebound

  double bounce = 0.5;

  // Radius of the ball

  double radius = 50.0;

  // Ground height

  final double height = 700;



  // Drop method

  void _fall(_) {

    y += vy;

    vy += gravity;



    // If the ball touches the ground, change the Y velocity of the ball according to the ground rebound

    if (y + radius > height) {

      y = height - radius;

      vy *= bounce;

    } else if (y - radius < 0) {

      y = 0 + radius;

      vy *= bounce;

    }



    setState(() {});

  }



  @override

  void initState() {

    super.initState();

    // Use a Ticker to run the sphere drop method every time the interface is updated

Ticker(_fall).. start();

  }



  @override

  Widget build(BuildContext context) {

    double screenWidth = MediaQuery.of(context).size.width;



    return Scaffold(

      appBar: AppBar(title: Text('Physics animation')),

      body: Column(

        children: <Widget>[

          Container(

            height: height,

            child: Stack(

              children: <Widget>[

                Positioned(

                  top: y - radius,

                  left: screenWidth / 2 - radius,

                  child: Container(

                    width: radius * 2.

                    height: radius * 2.

                    decoration: BoxDecoration(

                      color: Colors.blue,

                      shape: BoxShape.circle,

                    ),

                  ),

                ),

].

            ),

          ),

          Expanded(child: Container(color: Colors.blue)),

].

      ),

    );

  }

}



Copy the code

conclusion

This article introduces the various types of Flutter animation, respectively

  • An implicit animation
  • Explicit animation
  • Hero animation
  • Mixed animation
  • Physics-based animation

The Flutter Animation is based on a typed Animation object. The Widgets re-run the build function by reading the current value of the Animation object and listening for changes in the state, constantly changing the UI to create the Animation effect.

The main elements of an animation are

  • AnimationThe animation object
  • AnimationControllerAnimation controller
  • TweenAnimation value range
  • CurveAnimation curve

reference

Flutter animation basics with implicit animations

Directional animations with built-in explicit animations

Animation effect introduction

Introduction to Flutter Animation

Animate the Flutter application

This article is formatted using MDNICE