The official documentation

Necessary concepts and classes

  • AnimationObject, it isFlutterA core class in the animation library that inserts values used to guide the animation
  • AnimationThe object knows the state of the current animation (whether the animation starts, stops, advances, or retreats), but nothing about what is displayed on the screen
  • AnimationControllerObject managementAnimation
  • CurvedAnimationDefine an animation as an animation of nonlinear motion
  • TweenInterpolate between data ranges used by the animated object. For example,TweenInterpolation may be defined from red to blue or from 0 to 255
  • useListenersStatusListenersTo listen for changes in animation state

steps

  • Initialize an AnimationController object

    AnimationController controller = AnimationController(duration: const Duration(milliseconds: 500), vsync: this);
    Copy the code
  • Initialize an Animation object and pass in the AnimationController as a parameter. The Animation object here is created through the Animate method of the Tween object

    Animation<int> alpha = IntTween(begin: 0, end: 255).animate(controller);
    Copy the code
  • Call the AnimationController’s forward() method to perform the animation

    controller.forward();
    Copy the code
  • Call the dispose() method on the Widget to release the resource

    controller.dispose();
    Copy the code

case

The following example changes the width and height of the widget in a given amount of time

  • We need real-time accessAnimationvalueTo assignwidgetThe wide high
  • To change thewidgetWidth and height, then needsetState(...)To make thewidgetredraw

First we need a state-changing widget that inherits from the StatefulWidget, and then follow the steps we’ve done above with the following code:

class AnimateApp extends StatefulWidget {

  @override
  State<StatefulWidget> createState() {
    return_AnimateAppState(); }}class _AnimateAppState extends State<AnimateApp> with SingleTickerProviderStateMixin {

  AnimationController controller;
  Animation<double> animation;
  
  @override
  void initState() {
    super.initState();
    // Create the AnimationController object
    controller = AnimationController(
        vsync: this, duration: const Duration(milliseconds: 2000));
    // Create an Animation using the Tween object
    animation = Tween(begin: 50.0, end: 200.0).animate(controller) .. addListener(() {// Note: Do not omit this sentence, otherwise the widget will not be redrawn and the animation will not be visible
        setState(() {});
      })
    // Perform the animation
    controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'AnimateApp',
        theme: ThemeData(
            primaryColor: Colors.redAccent
        ),
        home: Scaffold(
            appBar: AppBar(
              title: Text('AnimateApp'),
            ),
            body: Center(
              child: Container(
                // Gets the width and height assigned to the widget by the animation value
                width: animation.value,
                height: animation.value,
                decoration: BoxDecoration(
                    color: Colors.redAccent
                ),
              ),
            )
        )
    );
  }

  @override
  void dispose() {
    // Resource release
    controller.dispose();
    super.dispose(); }}Copy the code

The effect is as follows:

It can be seen that the above animation moves linearly. We can use CurvedAnimation to realize the animation code of nonlinear motion as follows:

controller = AnimationController(
    vsync: this, duration: const Duration(milliseconds: 2000));
// Nonlinear animation
final CurvedAnimation curve = CurvedAnimation(
    parent: controller, curve: Curves.elasticOut);
animation = Tween(begin: 50.0, end: 200.0).animate(curve) .. addListener(() { setState(() {}); });Copy the code

The effect is as follows:

We can then add a state listener to the Animation by adding addStatusListener(…) to the Animation. To monitor the state of the current animation, such as whether the animation is finished. We can add a state listener to the above example to let the animation execute indefinitely:

animation = Tween(begin: 50.0, end: 200.0).animate(curve) .. addListener(() { setState(() {}); }).. addStatusListener((status) {if (status == AnimationStatus.completed) {
          controller.reverse();
        } else if(status == AnimationStatus.dismissed) { controller.forward(); }});Copy the code

AnimationStatus.com pleted said animation at the end to stop state, this time we let the animation it reverses after (from); AnimationStatus. Dismissed said animation stops at the start, this time we let the animation normal execution (once upon a time in the future). This allows the animation to execute indefinitely.

Tween can also accept the Color parameter to change the Color of the widget from red to blue. The following code is used to change the Color of the widget from red to blue:

controller = AnimationController(
        duration: const Duration(milliseconds: 3000), vsync: this); animation = ColorTween(begin: Colors.redAccent, end: Colors.blue).animate( controller) .. addListener(() { setState(() {}); }); controller.forward(); . child: Container( decoration: BoxDecoration( color: animation.value ), margin: EdgeInsets.symmetric(vertical:10.0),
        height: 200.0,
        width: 200.0,),Copy the code

The effect is as follows:

tip

with

We can see _AnimateAppState class followed a with SingleTickerProviderStateMixin, what do you mean this with? With is a key word in Dart. It can be interpreted as a mixin. Check out this answer on StackOverflow.

Mixin refers to the ability to add functionality from one or more classes to one’s own classes without having to inherit from those classes. You can call methods in these classes if you mix them. Dart does not have multiple inheritance, and you can use mixins to avoid the problems multiple inheritance can cause.

The _AnimateAppState class inherits the State class, but initializes the AnimationController with a TickerProvider vsync parameter. So we mixed with TickerProvider SingleTickerProviderStateMixin subclass

Look at a simple little example of mixing

void main() {
  var a = new A();
  a.methodB();
  a.methodC();
  a.methodD();

  new E(a);
}

class A extends B with C.D {}class B {
  void methodB() {
    print('Class B methodB is call'); }}class C {
  void methodC() {
    print('Class C methodC is call'); }}class D {
  void methodD() {
    print('Class D methodD is call'); }}class E {
  final C c;

  E(this.c) { c.methodC(); }}Copy the code

You can see that class A inherits from class B, and then mixes with classes C and D. Then, in the main method, you can use instances of class A to call methods from classes B, C, and D. Then there is class E, which needs A class C as A parameter in the constructor, and since class A is mixed with class C, you can pass an instance of class A as A parameter into the constructor of class E.

Run the following output:

Class B methodB is call
Class C methodC is call
Class D methodD is call
Class C methodC is call
Copy the code

..addListener

In the example above, we see this notation

animation = Tween(begin: 50.0, end: 200.0).animate(curve) .. addListener(() { setState(() {}); });Copy the code

Notice the two dots before addListener.. Right? What does that mean? Let’s just look at a quick example!

void main() {
  List<String> list = getList() .. add("android")
    ..add("flutter")
    ..add("kotlin")
    ..removeAt(0);

  list.forEach((item) {
    print(item);
  });

  // ---------- is equivalent to

  print('-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --');

  List<String> list2 = getList();
  list2.add("android");
  list2.add("flutter");
  list2.add("kotlin");
  list2.removeAt(0);

  list2.forEach((item) {
    print(item);
  });
}

List<String> getList() {
  return new List(a); }Copy the code

Enter the following:

flutter
kotlin
---------------------------
flutter
kotlin
Copy the code

If there are any mistakes, please also point out, thank you!