微信交流群

老孟公众号

# Tween

AnimationController 设置的最小/大值类型是 double,如果动画的变化是颜色要如何处理?

AnimationController 在执行动画期间返回的值是 0 到 1,颜色从蓝色变为红色方法如下:

_controller =
    AnimationController(vsync: this, duration: Duration(milliseconds: 500))
      ..addListener(() {
        setState(() {
          _color = Color.lerp(_startColor, _endColor, _controller.value);
        });
      });
1
2
3
4
5
6
7

重点是 Color.lerp 方法,此方法是在两种颜色之间线性插值。

完整代码如下:

class TweenDemo extends StatefulWidget {
  
  _TweenDemoState createState() => _TweenDemoState();
}

class _TweenDemoState extends State<TweenDemo>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;
	Color _startColor = Colors.blue;
  Color _endColor = Colors.red;

  Color _color = Colors.blue;

  
  void initState() {
    super.initState();
    _controller =
        AnimationController(vsync: this, duration: Duration(milliseconds: 500))
          ..addListener(() {
            setState(() {
              _color = Color.lerp(_startColor, _endColor, _controller.value);
            });
          });
  }

  
  Widget build(BuildContext context) {
    return Center(
      child: GestureDetector(
        onTap: () {
          _controller.forward();
        },
        child: Container(
          height: 100,
          width: 100,
          color: _color,
          alignment: Alignment.center,
          child: Text(
            '点我变色',
            style: TextStyle(color: Colors.white, fontSize: 18),
          ),
        ),
      ),
    );
  }

  
  void dispose() {
    super.dispose();
    _controller.dispose();
  }
}
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

Flutter 中把这种从 0 -> 1 转换为 蓝色 -> 红色 行为称之为 Tween(映射)

使用 Tween 完成动画 蓝色 -> 红色:

class _TweenDemoState extends State<TweenDemo>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Animation<Color> _animation;

  
  void initState() {
    super.initState();
    _controller =
        AnimationController(vsync: this, duration: Duration(milliseconds: 500))
          ..addListener(() {
            setState(() {});
          });
    _animation =
        ColorTween(begin: Colors.blue, end: Colors.red).animate(_controller);
  }

  
  Widget build(BuildContext context) {
    return Center(
      child: GestureDetector(
        onTap: () {
          _controller.forward();
        },
        child: Container(
          height: 100,
          width: 100,
          color: _animation.value,
          alignment: Alignment.center,
          child: Text(
            '点我变色',
            style: TextStyle(color: Colors.white, fontSize: 18),
          ),
        ),
      ),
    );
  }

  
  void dispose() {
    super.dispose();
    _controller.dispose();
  }
}
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

效果和上面是一样的。

Tween 仅仅是映射,动画的控制依然由 AnimationController 控制,因此需要 Tween.animate(_controller) 将控制器传递给Tween。

系统提供了大量的 Tween:

基本上常用的属性都包含了其对应的 Tween,看一下 ColorTween 的源代码实现:

本质上也是使用 Color.lerp 实现的。