Flutter绘制-13-动画专项-多种多样的Tween

1,648 阅读8分钟

查看目录-->

Flutter内置了很多的Tween,下面一一看下:

ColorTween

可以设置颜色渐变,begin颜色,end颜色,中间过渡。

  • 设定颜色过渡,初始颜色绿色,目标颜色棕色,Tween colorTween = new ColorTween(begin: Colors.green,end:Colors.orange);
    • 方式一:通过colorTween.evaluate(_controller)来获取渐变的颜色
    • 方式二:通过animate
      • Animation _animation
      • new ColorTween(begin: Colors.green, end: Colors.orange);
      • _animation = colorTween.animate(_controller);
      • color: _animation.value

5.gif

代码如下:

import 'package:flutter/material.dart';

class Test10ColorTween extends StatefulWidget {
  @override
  _State createState() => _State();
}

class _State extends State<Test10ColorTween>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Tween colorTween = new ColorTween(begin: Colors.green, end: Colors.orange);
  Animation<Color> _animationColor;
  @override
  void initState() {
    super.initState();
    _controller = new AnimationController(
        vsync: this, duration: const Duration(milliseconds: 5000));
    _animationColor = colorTween.animate(_controller);
    _controller.addListener(() {
      setState(() {});
    });
    // 动画开始执行
    _controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("ColorTween"),
        centerTitle: true,
      ),
      body: Center(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
              width: 200,
              height: 200,
              margin: EdgeInsets.all(10),
              color: colorTween.evaluate(_controller),
            ),
            Container(
              width: 200,
              height: 200,
              margin: EdgeInsets.all(10),
              color: _animationColor.value,
            ),
            Text("ColorTween",
                style: TextStyle(
                  fontSize: 14,
                )),
          ],
        ),
      ),
    );
  }

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



IntTween

直接new Tween()时,begin 和 end是double的,IntTween的begin和end是int型的。

Tween sizeTween = new IntTween(begin: 0,end: 200);

print("${sizeTween.evaluate(_controller)}");
  • 通过evaluate,打印的值全是int的。
  • 通过animate.value获取到的值都是int的。

1.gif

代码如下:

import 'package:flutter/material.dart';

class Test09IntTween extends StatefulWidget {
  @override
  _State createState() => _State();
}

class _State extends State<Test09IntTween> with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Tween intTween = new IntTween(begin: 0, end: 200);
  Animation<int> _animationInt;

  @override
  void initState() {
    super.initState();
    _controller = new AnimationController(
        vsync: this, duration: const Duration(milliseconds: 6000));
    _animationInt = intTween.animate(_controller);
    _controller.addListener(() {
      setState(() {});
    });
    // 动画开始执行
    _controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("IntTween"),
        centerTitle: true,
      ),
      body: Center(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
              width: _animationInt.value.toDouble(),
              height: _animationInt.value.toDouble(),
              margin: EdgeInsets.all(10),
              color: Colors.black12,
            ),
            Text("IntTween,_animationInt.value=${_animationInt.value}",
                style: TextStyle(
                  fontSize: 14,
                )),
          ],
        ),
      ),
    );
  }

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

SizeTween

基于Size的过渡变化,其实是size内两个值的变化。

Tween sizeTween = new SizeTween(begin: Size(0.0,0.0),end: Size(100.0,100.0));
Animation<Size> animation = sizeTween.animate(_controller);
Size size = animation.value;
  • 注意Animation animation = sizeTween.animate(_controller); 泛型是Size 效果:

2.gif

代码如下:

import 'package:flutter/material.dart';

class Test11SizeTween extends StatefulWidget {
  @override
  _State createState() => _State();
}

class _State extends State<Test11SizeTween>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Tween sizeTween =
      new SizeTween(begin: Size(0.0, 0.0), end: Size(100.0, 200.0));
  Animation<Size> _animationSize;

  @override
  void initState() {
    super.initState();
    _controller = new AnimationController(
        vsync: this, duration: const Duration(milliseconds: 5000));
    _animationSize = sizeTween.animate(_controller);
    _controller.addListener(() {
      setState(() {});
    });
    // 动画开始执行
    _controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("SizeTween"),
        centerTitle: true,
      ),
      body: Center(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
              width: _animationSize.value.width,
              height: _animationSize.value.height,
              margin: EdgeInsets.all(10),
              color: Colors.black12,
            ),
            Container(
              width: 300,
              child: Text("SizeTween.size.width=${_animationSize.value.width}",
                  style: TextStyle(
                    fontSize: 14,
                  )),
            ),
            Container(
              width: 300,
              child:
                  Text("SizeTween.size.height=${_animationSize.value.height}",
                      style: TextStyle(
                        fontSize: 14,
                      )),
            )
          ],
        ),
      ),
    );
  }

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

RectTween

基于Rect矩形的过渡变化

Tween rectTween = new RectTween(begin: Rect.fromLTWH(0, 0, 0, 0),end: Rect.fromLTWH(100, 100, 100, 100));
Animation<Rect> animation = rectTween.animate(_controller);
Rect rect = animation.value;

效果:

3.gif

代码如下:

import 'package:flutter/material.dart';

class Test12RectTween extends StatefulWidget {
  @override
  _State createState() => _State();
}

class _State extends State<Test12RectTween>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Tween rectTween = new RectTween(
      begin: Rect.fromLTWH(0, 0, 0, 0), end: Rect.fromLTWH(100, 100, 100, 100));
  Animation<Rect> _animationRect;

  @override
  void initState() {
    super.initState();
    _controller = new AnimationController(
        vsync: this, duration: const Duration(milliseconds: 5000));
    _animationRect = rectTween.animate(_controller);
    _controller.addListener(() {
      setState(() {});
    });
    // 动画开始执行
    _controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("RectTween"),
        centerTitle: true,
      ),
      body: Center(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
              width: 200,
              height: 200,
              margin: EdgeInsets.all(10),
              color: Colors.black12,
              child: CustomPaint(
                painter: _MyRectPainter(_animationRect),
              ),
            ),
            Text("RectTween",
                style: TextStyle(
                  fontSize: 14,
                )),
          ],
        ),
      ),
    );
  }

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

class _MyRectPainter extends CustomPainter {
  Animation<Rect> animation;

  _MyRectPainter(this.animation) : super(repaint: animation);

  @override
  void paint(Canvas canvas, Size size) {
    Paint paint = Paint()
      ..color = Colors.red
      ..strokeWidth = 1
      ..style = PaintingStyle.stroke;
    canvas.drawRect(animation.value, paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return true;
  }

  void translateToCenter(Canvas canvas, Size size) {
    canvas.translate(size.width / 2, size.height / 2);
  }
}

StepTween

每次返回插值的floor,从double变为了int。

Tween stepTween = new StepTween(begin: 0,end: 100);
Animation<int> animation = stepTween.animate(_controller);
int value = animation.value;

效果:

4.gif

代码如下:

import 'package:flutter/material.dart';

class Test13StepTween extends StatefulWidget {
  @override
  _State createState() => _State();
}

class _State extends State<Test13StepTween>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Tween stepTween = new StepTween(begin: 0, end: 100);
  Animation<int> _animationStep;

  @override
  void initState() {
    super.initState();
    _controller = new AnimationController(
        vsync: this, duration: const Duration(milliseconds: 6000));
    _animationStep = stepTween.animate(_controller);
    _controller.addListener(() {
      setState(() {});
    });
    // 动画开始执行
    _controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("StepTween"),
        centerTitle: true,
      ),
      body: Center(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
              width: 200,
              height: 200,
              margin: EdgeInsets.all(10),
              color: Colors.black12,
              child: CustomPaint(
                painter: _MyStepPainter(_animationStep),
              ),
            ),
            Text("StepTween.value=${_animationStep.value}",
                style: TextStyle(
                  fontSize: 14,
                )),
          ],
        ),
      ),
    );
  }

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

class _MyStepPainter extends CustomPainter {
  Animation<int> animation;

  _MyStepPainter(this.animation) : super(repaint: animation);

  @override
  void paint(Canvas canvas, Size size) {
    Paint paint = Paint()
      ..color = Colors.red
      ..strokeWidth = 1
      ..style = PaintingStyle.stroke;
    canvas.drawRect(
        Rect.fromLTWH(
            0, 0, animation.value.toDouble(), animation.value.toDouble()),
        paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return true;
  }

  void translateToCenter(Canvas canvas, Size size) {
    canvas.translate(size.width / 2, size.height / 2);
  }
}

ConstantTween

每次返回插常量值,创建时传入什么类型的值,就获取什么类型的值

Tween constantTween = new ConstantTween(100.0);
Animation<int> animation = constantTween.animate(_controller);
int value = animation.value;

效果:

5.gif

代码如下:

import 'package:flutter/material.dart';

class Test14ConstantTween extends StatefulWidget {
  @override
  _State createState() => _State();
}

class _State extends State<Test14ConstantTween>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Tween constantTween = new ConstantTween<String>("ConstantTween");
  Animation<String> _animationConstant;

  @override
  void initState() {
    super.initState();
    _controller = new AnimationController(
        vsync: this, duration: const Duration(milliseconds: 5000));

    _animationConstant = constantTween.animate(_controller);
    _controller.addListener(() {
      setState(() {});
    });
    // 动画开始执行
    _controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("ConstantTween"),
        centerTitle: true,
      ),
      body: Center(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
              width: 200,
              height: 200,
              margin: EdgeInsets.all(10),
              color: Colors.black12,
              child: Center(
                child: Text(_animationConstant.value,
                    style: TextStyle(fontSize: 14, color: Colors.red)),
              ),
            ),
            Text("ConstantTween",
                style: TextStyle(
                  fontSize: 14,
                )),
          ],
        ),
      ),
    );
  }

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

CurveTween

注意CurveTween extends Animatable,不是Tween的子类。用给定的curve将_controller.value进行了转换。

CurveTween curveTween = new CurveTween(curve:Curves.easeInToLinear);
Animation<double> animation = curveTween.animate(_controller);
double value = animation.value;
  • animation.value值在[0,1]之间 效果:

6.gif

代码如下:

import 'package:flutter/material.dart';

class Test15CurveTween extends StatefulWidget {
  @override
  _State createState() => _State();
}

class _State extends State<Test15CurveTween>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;
  CurveTween curveTween = new CurveTween(curve: Curves.bounceInOut);
  Animation<double> _animationCurve;

  @override
  void initState() {
    super.initState();
    _controller = new AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 6000),
    );
    _animationCurve = curveTween.animate(_controller);
    _controller.addListener(() {
      setState(() {});
    });
    // 动画开始执行
    _controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("CurveTween"),
        centerTitle: true,
      ),
      body: Center(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
              width: 200,
              height: 200,
              margin: EdgeInsets.all(10),
              color: Colors.black12,
              child: CustomPaint(
                painter: _MyCurvePainter(_animationCurve),
              ),
            ),
            Container(
              width: 300,
              child: Text("CurveTween.value=${_animationCurve.value}",
                  style: TextStyle(
                    fontSize: 14,
                  )),
            )
          ],
        ),
      ),
    );
  }

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

class _MyCurvePainter extends CustomPainter {
  Animation<double> animation;

  _MyCurvePainter(this.animation) : super(repaint: animation);

  @override
  void paint(Canvas canvas, Size size) {
    translateToCenter(canvas, size);
    Paint paint = Paint()
      ..color = Colors.red
      ..style = PaintingStyle.fill;
    canvas.drawCircle(
        Offset(animation.value * 100, animation.value * 100), 10, paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return true;
  }

  void translateToCenter(Canvas canvas, Size size) {
    canvas.translate(size.width / 2, size.height / 2);
  }
}

AlignmentTween

基于Alignment属性的过渡,比如Container的child从topleft移动到bottomRight.

看下效果:

7.gif

代码如下:

import 'package:flutter/material.dart';

class Test16AlignmentTween extends StatefulWidget {
  @override
  _State createState() => _State();
}

class _State extends State<Test16AlignmentTween>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Tween _tween =
      new AlignmentTween(begin: Alignment.topLeft, end: Alignment.bottomRight);
  Animation<Alignment> _animation;
  @override
  void initState() {
    super.initState();
    _controller = new AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 6000),
    );
    _animation = _tween.animate(_controller);
    _controller.addListener(() {
      setState(() {});
    });
    // 动画开始执行
    _controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("AlignmentTween"),
        centerTitle: true,
      ),
      body: Center(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
              width: 400,
              height: 400,
              alignment: _animation.value,
              margin: EdgeInsets.all(10),
              color: Colors.black12,
              child: Container(
                width: 100,
                height: 100,
                color: Colors.orange,
              ),
            ),
          ],
        ),
      ),
    );
  }

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

AlignmentGeometryTween

与AlignmentTween类似效果。 效果:

8.gif

代码如下:

import 'package:flutter/material.dart';

class Test17AlignmentGeometryTween extends StatefulWidget {
  @override
  _State createState() => _State();
}

class _State extends State<Test17AlignmentGeometryTween>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Tween _tween = new AlignmentGeometryTween(
      begin: AlignmentDirectional.topCenter,
      end: AlignmentDirectional.centerEnd);
  Animation<AlignmentGeometry> _animation;
  @override
  void initState() {
    super.initState();
    _controller = new AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 6000),
    );
    _animation = _tween.animate(_controller);
    _controller.addListener(() {
      setState(() {});
    });
    // 动画开始执行
    _controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("AlignmentGeometryTween"),
        centerTitle: true,
      ),
      body: Center(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
              width: 400,
              height: 400,
              margin: EdgeInsets.all(10),
              color: Colors.black12,
              alignment: _animation.value,
              child: Container(
                width: 100,
                height: 100,
                color: Colors.orange,
              ),
            ),
          ],
        ),
      ),
    );
  }

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

BorderRadiusTween

基于BorderRadius属性的过渡。

效果如下:

9.gif

代码如下:

import 'package:flutter/material.dart';

class Test18BorderRadiusTween extends StatefulWidget {
  @override
  _State createState() => _State();
}

class _State extends State<Test18BorderRadiusTween>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Tween _tween = new BorderRadiusTween(
      begin: BorderRadius.circular(0), end: BorderRadius.circular(200));
  Animation<BorderRadius> _animation;
  @override
  void initState() {
    super.initState();
    _controller = new AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 6000),
    );
    _animation = _tween.animate(_controller);
    _controller.addListener(() {
      setState(() {});
    });
    // 动画开始执行
    _controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("BorderRadiusTween"),
        centerTitle: true,
      ),
      body: Center(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
              width: 400,
              height: 400,
              margin: EdgeInsets.all(10),
              decoration: BoxDecoration(borderRadius: _animation.value,color: Colors.orangeAccent),
            ),
          ],
        ),
      ),
    );
  }

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

BorderTween

基于Border属性的过渡。

效果如下:

10.gif

代码如下:

import 'package:flutter/material.dart';

class Test19BorderTween extends StatefulWidget {
  @override
  _State createState() => _State();
}

class _State extends State<Test19BorderTween>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Tween _tween = new BorderTween(
      begin: Border(top: BorderSide(width: 0, color: Colors.red)),
      end: Border(
          top: BorderSide(width: 50, color: Colors.green),
          bottom: BorderSide(width: 50, color: Colors.blueAccent)));
  Animation<Border> _animation;
  @override
  void initState() {
    super.initState();
    _controller = new AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 6000),
    );
    _animation = _tween.animate(_controller);
    _controller.addListener(() {
      setState(() {});
    });
    // 动画开始执行
    _controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("BorderTween"),
        centerTitle: true,
      ),
      body: Center(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
              width: 400,
              height: 400,
              margin: EdgeInsets.all(10),
              decoration: BoxDecoration(
                  border: _animation.value, color: Colors.orangeAccent),
            ),
          ],
        ),
      ),
    );
  }

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

ShapeBorderTween

基于ShapeBorder属性的过渡。

效果如下:

11.gif

代码如下:

import 'package:flutter/material.dart';

class Test20ShapeBorderTween extends StatefulWidget {
  @override
  _State createState() => _State();
}

class _State extends State<Test20ShapeBorderTween>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Tween _tween = new ShapeBorderTween(
      begin: RoundedRectangleBorder(
          side: BorderSide(width: 0, color: Colors.red),
          borderRadius: BorderRadius.circular(0)),
      end: RoundedRectangleBorder(
          side: BorderSide(width: 50, color: Colors.green),
          borderRadius: BorderRadius.circular(200)));
  Animation<ShapeBorder> _animation;
  @override
  void initState() {
    super.initState();
    _controller = new AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 6000),
    );
    _animation = _tween.animate(_controller);
    _controller.addListener(() {
      setState(() {});
    });
    // 动画开始执行
    _controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("ShapeBorderTween"),
        centerTitle: true,
      ),
      body: Center(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
              width: 400,
              height: 400,
              margin: EdgeInsets.all(10),
              decoration: ShapeDecoration(shape: _animation.value,color: Colors.orangeAccent),
            ),
          ],
        ),
      ),
    );
  }

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

DecorationTween

基于Decoration属性的过渡。

效果如下:

12.gif

代码如下:

import 'package:flutter/material.dart';

class Test21DecorationTween extends StatefulWidget {
  @override
  _State createState() => _State();
}

class _State extends State<Test21DecorationTween>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Tween _tween = new DecorationTween(
      begin: BoxDecoration(
          color: Colors.red,
          // borderRadius: BorderRadius.circular(0),
          border: Border(top: BorderSide(color: Colors.red, width: 0)),
          // shape: BoxShape.rectangle,
          gradient: LinearGradient(
              colors: [Colors.red, Colors.green, Colors.blueAccent])),
      end: BoxDecoration(
          color: Colors.orangeAccent,
          // borderRadius: BorderRadius.circular(200),
          border: Border(top: BorderSide(color: Colors.black, width: 50)),
          // shape: BoxShape.circle,
          gradient: LinearGradient(colors: [
            Colors.black12,
            Colors.blueAccent,
            Colors.yellowAccent
          ])));

  Animation<Decoration> _animation;
  @override
  void initState() {
    super.initState();
    _controller = new AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 6000),
    );
    _animation = _tween.animate(_controller);
    _controller.addListener(() {
      setState(() {});
    });
    // 动画开始执行
    _controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("DecorationTween"),
        centerTitle: true,
      ),
      body: Center(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
              width: 400,
              height: 400,
              margin: EdgeInsets.all(10),
              decoration: _animation.value,
            ),
          ],
        ),
      ),
    );
  }

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

BoxConstraintsTween

基于BoxConstraints属性的过渡。

效果如下:

13.gif

代码如下:

import 'package:flutter/material.dart';

class Test22BoxConstraintsTween extends StatefulWidget {
  @override
  _State createState() => _State();
}

class _State extends State<Test22BoxConstraintsTween>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;

  Tween _tween = new BoxConstraintsTween(
      begin: BoxConstraints(maxWidth: 0, minHeight: 0),
      end: BoxConstraints(maxWidth: 200, minHeight: 200));

  Animation<BoxConstraints> _animation;
  @override
  void initState() {
    super.initState();
    _controller = new AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 6000),
    );
    _animation = _tween.animate(_controller);
    _controller.addListener(() {
      setState(() {});
    });
    // 动画开始执行
    _controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("BoxConstraintsTween"),
        centerTitle: true,
      ),
      body: Center(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
              margin: EdgeInsets.all(10),
              color: Colors.orangeAccent,
              constraints: _animation.value,
            ),
          ],
        ),
      ),
    );
  }

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

EdgeInsetsTween

基于padding 或 margin等需要EdgeInsets控制的属性的过渡。

效果如下:

14.gif

代码如下:

import 'package:flutter/material.dart';

class Test23EdgeInsetsTween extends StatefulWidget {
  @override
  _State createState() => _State();
}

class _State extends State<Test23EdgeInsetsTween>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;

  Tween _tween = new EdgeInsetsTween(
      begin: EdgeInsets.only(left: 0, top: 0),
      end: EdgeInsets.only(left: 100, top: 50));
  Animation<EdgeInsets> _animation;
  @override
  void initState() {
    super.initState();
    _controller = new AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 6000),
    );
    _animation = _tween.animate(_controller);
    _controller.addListener(() {
      setState(() {});
    });
    // 动画开始执行
    _controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("EdgeInsetsTween"),
        centerTitle: true,
      ),
      body: Center(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
              width: 200,
              height: 200,
              padding: _animation.value,
              margin: EdgeInsets.all(10),
              color: Colors.orangeAccent,
              child: Text("pushing by padding"),
            ),
          ],
        ),
      ),
    );
  }

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

EdgeInsetsGeometryTween

基于padding 或 margin等需要EdgeInsetsGeometry控制的属性的过渡。EdgeInsetsGeometry是EdgeInsets的父类。效果几乎一样。

效果如下:

14.gif

代码如下:

import 'package:flutter/material.dart';

class Test24EdgeInsetsGeometryTween extends StatefulWidget {
  @override
  _State createState() => _State();
}

class _State extends State<Test24EdgeInsetsGeometryTween>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;

  Tween _tween = new EdgeInsetsGeometryTween(
      begin: EdgeInsets.only(left: 0, top: 0),
      end: EdgeInsets.only(left: 100, top: 50));

  Animation<EdgeInsetsGeometry> _animation;
  @override
  void initState() {
    super.initState();
    _controller = new AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 6000),
    );
    _animation = _tween.animate(_controller);
    _controller.addListener(() {
      setState(() {});
    });
    // 动画开始执行
    _controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("EdgeInsetsGeometryTween"),
        centerTitle: true,
      ),
      body: Center(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
              width: 200,
              height: 200,
              padding: _animation.value,
              margin: EdgeInsets.all(10),
              color: Colors.orangeAccent,
              child: Text("pushing by padding"),
            ),
          ],
        ),
      ),
    );
  }

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

TextStyleTween

基于Text的style属性的过渡,TextStyle的所有属性都可以渐变。

效果如下:

1.gif

代码如下:

import 'package:flutter/material.dart';

class Test25TextStyleTween extends StatefulWidget {
  @override
  _State createState() => _State();
}

class _State extends State<Test25TextStyleTween>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;

  Tween _tween = new TextStyleTween(
      begin: TextStyle(color: Colors.red,fontSize: 10),
      end: TextStyle(color: Colors.blue,fontSize: 40));
  Animation<TextStyle> _animation;
  @override
  void initState() {
    super.initState();
    _controller = new AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 6000),
    );
    _animation = _tween.animate(_controller);
    _controller.addListener(() {
      setState(() {});
    });
    // 动画开始执行
    _controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("TextStyleTween"),
        centerTitle: true,
      ),
      body: Center(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
              width: 200,
              height: 200,
              margin: EdgeInsets.all(10),
              color: Colors.orangeAccent,
              alignment: Alignment.center,
              child: Text("TextStyle changing",style: _animation.value,),
            ),
          ],
        ),
      ),
    );
  }

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

Matrix4Tween

基于四阶矩阵的渐变,以canvas的transform为例。

效果:

1.gif

代码如下:

import 'package:flutter/material.dart';

class Test26Matrix4Tween extends StatefulWidget {
  @override
  _State createState() => _State();
}

class _State extends State<Test26Matrix4Tween>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;

  Tween _tween = new Matrix4Tween(
      begin: Matrix4(
        1,0,0,0,
        0,1,0,0,
        0,0,1,0,
        0,0,0,1,
      ),
      end: Matrix4(
        1,0,0,0,
        0,1,0,0,
        0,0,1,0,
        100,0,0,1,// 延x平移100
      ));
  Animation<Matrix4> _animation;
  @override
  void initState() {
    super.initState();
    _controller = new AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 6000),
    );
    _animation = _tween.animate(_controller);
    _controller.addListener(() {
      setState(() {});
    });
    // 动画开始执行
    _controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Matrix4Tween"),
        centerTitle: true,
      ),
      body: Center(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
              width: 400,
              height: 400,
              margin: EdgeInsets.all(10),
              color: Colors.orangeAccent,
              alignment: Alignment.center,
              child: CustomPaint(
                size: Size(200,200),
                painter: _MyRectPainter(_animation),
              ),
            ),
          ],
        ),
      ),
    );
  }

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


class _MyRectPainter extends CustomPainter {
  Animation<Matrix4> animation;

  _MyRectPainter(this.animation) : super(repaint: animation);

  @override
  void paint(Canvas canvas, Size size) {
    translateToCenter(canvas, size);
    Paint paint = Paint()
      ..color = Colors.red
      ..strokeWidth = 1
      ..style = PaintingStyle.stroke;
    canvas.drawCircle(Offset.zero, 100, paint);
    canvas.transform(animation.value.storage);
    canvas.drawCircle(Offset.zero, 100, paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return true;
  }

  void translateToCenter(Canvas canvas, Size size) {
    canvas.translate(size.width / 2, size.height / 2);
  }
}
Test27ThemeDataTween

可以定义主题渐变的Tween. 效果:

2.gif

代码:

import 'package:flutter/material.dart';

class Test27ThemeDataTween extends StatefulWidget {
  @override
  _State createState() => _State();
}

class _State extends State<Test27ThemeDataTween>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;

  Tween _tween = new ThemeDataTween(
      begin: ThemeData(primaryColor: Colors.blue),
      end:  ThemeData(primaryColor: Colors.green));
  Animation<ThemeData> _animation;
  @override
  void initState() {
    super.initState();
    _controller = new AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 6000),
    );
    _animation = _tween.animate(_controller);
    _controller.addListener(() {
      setState(() {});
    });
    // 动画开始执行
    _controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Theme(
      data: _animation.value,
      child: Scaffold(
        appBar: AppBar(
          title: Text("ThemeDataTween"),
          centerTitle: true,
        ),
        body: Center(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Container(
                width: 400,
                height: 400,
                margin: EdgeInsets.all(10),
                color: _animation.value.primaryColor,
              ),
            ],
          ),
        ),
      ),
    );
  }

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

Test28RelativeRectTween

可以定义主题渐变的Tween. 效果:

3.gif

代码:

import 'package:flutter/material.dart';

class Test28RelativeRectTween extends StatefulWidget {
  @override
  _State createState() => _State();
}

class _State extends State<Test28RelativeRectTween>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;

  Tween _tween = new RelativeRectTween(
      begin: RelativeRect.fromLTRB(0, 0, 0, 0),
      end:  RelativeRect.fromLTRB(100, 100, 100, 100));
  Animation<RelativeRect> _animation;
  @override
  void initState() {
    super.initState();
    _controller = new AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 6000),
    );
    _animation = _tween.animate(_controller);
    _controller.addListener(() {
      setState(() {});
    });
    // 动画开始执行
    _controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("RelativeRectTween"),
        centerTitle: true,
      ),
      body: Center(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
              width: 400,
              height: 400,
              margin: EdgeInsets.all(10),
              color: Colors.orangeAccent,
              child: CustomPaint(
                painter: _MyRectPainter(_animation),
              ),
            ),
          ],
        ),
      ),
    );
  }

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


class _MyRectPainter extends CustomPainter {
  Animation<RelativeRect> animation;

  _MyRectPainter(this.animation) : super(repaint: animation);

  @override
  void paint(Canvas canvas, Size size) {
    Paint paint = Paint()
      ..color = Colors.red
      ..strokeWidth = 1
      ..style = PaintingStyle.stroke;
    Rect rect = Rect.fromLTWH(0, 0, size.width,size.height);
    canvas.drawRect(animation.value.toRect(rect), paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return true;
  }

  void translateToCenter(Canvas canvas, Size size) {
    canvas.translate(size.width / 2, size.height / 2);
  }
}
Tween总结

flutter提供了有二十个左右的Tween,从基本类型到对象都有,但是有个明显的特点:

  • 可量化,就算是对象,如Decoration,其实也是对其属性的变化,都是可量化的。
  • 同一类型的变化,begin描述初始状态,end描述结束状态

亲自动手试了这么多Tween的效果,其实可以发现,本质都是对AnimationController插值[0,1]变化的封装,我们自己也可以实现这些效果,只是flutter封装后我们更便于使用。