基本概念

  • Animation对象是Flutter动画库中的一个核心类,它生成指导动画的值。
  • Animation对象知道动画的当前状态(例如,它是开始、停止还是向前或向后移动),但它不知道屏幕上显示的内容。
  • AnimationController管理Animation。
  • CurvedAnimation 将过程抽象为一个非线性曲线.
  • Tween在正在执行动画的对象所使用的数据范围之间生成值。例如,Tween可能会生成从红到蓝之间的色值,或者从0到255。
  • 使用Listeners和StatusListeners监听动画状态改变。

Tween的使用

展示了一个自定义button,使用opacity,淡入淡出button的文字。

import 'package:flutter/foundation.dart';
import 'package:flutter/import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

class FancyButton extends StatelessWidget{

  final GestureTapCallback onPressed;


  FancyButton({ this.onPressed});

  
  Widget build(BuildContext context) {
    return new RawMaterialButton(
        fillColor: Colors.deepOrange,
        splashColor: Colors.orange,
        shape: new StadiumBorder(),
        onPressed: (){

        },
        child: Padding(
          padding: const EdgeInsets.symmetric(
            vertical:8.0,
            horizontal:10.0,
          ),
          child: Row(
            mainAxisSize: MainAxisSize.min,
            children: const <Widget>[
              RotatedBox(
                quarterTurns: 2,
                child: Icon(Icons.explore,
                  color:Colors.amber,
                ),
              ),
              SizedBox(width: 8.0,),
              PulseAnimator(
                child: Text(
                  "PUCHASE",
                  style: TextStyle(
                      color: Colors.white
                  ),
                ),
              ),
            ],
          ),
        )
    );

  }
}

class PulseAnimator extends StatefulWidget {

  final Widget child;

  const PulseAnimator({Key key,this.child}) : super(key:key);

  
  _PulseAnimatorState createState() => _PulseAnimatorState();
}

class _PulseAnimatorState extends State<PulseAnimator> with SingleTickerProviderStateMixin{
  AnimationController _controller;

  
  void initState(){
    super.initState();
    _controller = AnimationController(
        duration: const Duration(seconds: 2), //动画时长2s
        vsync: this,
    )..repeat(); //循环
  }
  
  void dispose(){
    _controller.dispose();
    super.dispose();
  }

  
  Widget build(BuildContext context) {
    return FadeTransition(
      // 透明度从0.5-1.0
      opacity: new Tween(begin: 0.5,end: 1.0).animate(_controller),
      child: widget.child,
    );
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

logo

分离动画代码

AnimatedWidget类允许您从setState()调用中的动画代码中分离出widget代码。AnimatedWidget不需要维护一个State对象来保存动画。

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

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

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

class MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
  Animation animation;
  AnimationController animationController;

  
  void initState() {
    super.initState();
    animationController = AnimationController(
        duration: Duration(milliseconds: 2000), vsync: this);

    animation = Tween(begin: 0.0, end: 400.0).animate(animationController);
    animation.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        animationController.reverse();
      } else if (status == AnimationStatus.dismissed) {
        animationController.forward();
      }
    });
    animationController.forward();
  }

  
  Widget build(BuildContext context) {
    return LogoAnimation(
      animation: animation,
    );
  }

  
  void dispose() {
    animationController.dispose();
    super.dispose();
  }
}

/// 动画继承AnimatedWidget
class LogoAnimation extends AnimatedWidget {
  LogoAnimation({Key key, Animation animation})
      : super(key: key, listenable: animation);

  
  Widget build(BuildContext context) {
    Animation animation = listenable;
    return MaterialApp(
      title: "Animation",
      home : Scaffold(
        appBar: AppBar(
          title: Text("Animation"),
        ),
        body: Center(
          child: Container(
            height: animation
                .value,
            width: animation.value,
            child: FlutterLogo(),
          ),
        ),
      ),
    );
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71

logo

Curve动画使用

import 'package:flutter/material.dart';

class Loader extends StatefulWidget {
  
  State createState() => new LoaderState();
}

class LoaderState extends State<Loader> with SingleTickerProviderStateMixin {

  AnimationController animationController;
  Animation<double> animation;

  
  void initState() {
    super.initState();
    animationController = new AnimationController(duration: new Duration(milliseconds: 1750), vsync: this);
    animation = new CurvedAnimation(parent: animatiobounceInnController, curve: Curves.elasticIn)
      ..addListener(() => this.setState(() {}))
      ..addStatusListener((AnimationStatus status) {
      });
    animationController.repeat();
  }

  
  void dispose() {
    animationController.dispose();
    super.dispose();
  }

  
  Widget build(BuildContext context) {
    return Center(
      child: new Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          new Container(
            color: Colors.white,
            width: animation.value * 100.0,
            height: 3.0,
          ),
          new Padding(padding: new EdgeInsets.only(bottom: 5.0),),
          new Container(
            color: Colors.white,
            width: animation.value * 75.0,
            height: 3.0,
          ),
          new Padding(padding: new EdgeInsets.only(bottom: 5.0),),
          new Container(
            color: Colors.white,
            width: animation.value * 50.0,
            height: 3.0,
          ),
          new Padding(padding: new EdgeInsets.only(bottom: 5.0),),
        ],
      ),
    );
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

logo

hero animation

login page animation sample

import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';

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

class MyApp extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return new MaterialApp(
      theme: new ThemeData(primarySwatch: Colors.blue),
      home: new LoginPage(),
    );
  }
}

class LoginPage extends StatefulWidget {
  
  State createState() => new LoginPageState();
}

class LoginPageState extends State<LoginPage>
    with SingleTickerProviderStateMixin {
  Animation<double> _iconAnimation;
  AnimationController _iconAnimationController;

  
  void initState() {
    super.initState();
    _iconAnimationController = new AnimationController(
        vsync: this, duration: new Duration(milliseconds: 1000));

    _iconAnimation = new CurvedAnimation(
      parent: _iconAnimationController,
      curve: Curves.bounceOut,
    );

    _iconAnimation.addListener(() => this.setState(() {}));
    _iconAnimationController.forward();
  }

  
  Widget build(BuildContext context) {
    return new Scaffold(
      backgroundColor: Colors.white,
      body: new Stack(fit: StackFit.expand, children: <Widget>[
        new Image(
          image: new AssetImage("assets/girl.jpeg"),
          fit: BoxFit.cover,
          colorBlendMode: BlendMode.darken,
          color: Colors.black87,
        ),
        new Theme(
          data: new ThemeData(
              brightness: Brightness.dark,
              inputDecorationTheme: new InputDecorationTheme(
                // hintStyle: new TextStyle(color: Colors.blue, fontSize: 20.0),
                labelStyle:
                    new TextStyle(color: Colors.tealAccent, fontSize: 25.0),
              )),
          isMaterialAppTheme: true,
          child: new Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              new FlutterLogo(
                size: _iconAnimation.value * 140.0,
              ),
              new Container(
                padding: const EdgeInsets.all(40.0),
                child: new Form(
                  autovalidate: true,
                  child: new Column(
                    mainAxisAlignment: MainAxisAlignment.start,
                    children: <Widget>[
                      new TextFormField(
                        decoration: new InputDecoration(
                            labelText: "Enter Email", fillColor: Colors.white),
                        keyboardType: TextInputType.emailAddress,
                      ),
                      new TextFormField(
                        decoration: new InputDecoration(
                          labelText: "Enter Password",
                        ),
                        obscureText: true,
                        keyboardType: TextInputType.text,
                      ),
                      new Padding(
                        padding: const EdgeInsets.only(top: 20.0),
                      ),
                      new MaterialButton(
                        height: 50.0,
                        minWidth: 150.0,
                        color: Colors.green,
                        splashColor: Colors.teal,
                        textColor: Colors.white,
                        child: new Icon(FontAwesomeIcons.signInAlt),
                        onPressed: () {},
                      )
                    ],
                  ),
                ),
              )
            ],
          ),
        ),
      ]),
    );
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108

logo

colors loader

logo

参考资料

  • https://medium.com/@nhancv/flutter-curves-simulation-f935bb225ad2
  • https://flutterchina.club/tutorials/animation/#%E7%94%A8animatedwidget%E7%AE%80%E5%8C%96