颤动动画不褪色(它闪烁)

时间:2018-03-07 16:22:56

标签: android ios animation mobile flutter

我正在关注flutter这里的动画教程:https://flutter.io/tutorials/animation/#animationcontroller,我正试图让一个图标在紫色和橙色之间淡入淡出。不幸的是,我设法做的就是获得 blink 的图标,这似乎非常令人沮丧,因为这不是ColorTween类的定义方式。来自文档:

  

我们建议您不要将Colors.transparent作为开头或结尾传递   如果你想要淡入或淡出透明效果。代替   喜欢null。 Colors.transparent指黑色透明因此   会消失或变成黑色,这可能是不受欢迎的。

https://docs.flutter.io/flutter/animation/ColorTween/ColorTween.html

我推断这意味着褪色是“开箱即用”。但是,我已经用CurvedAnimation类测试了它,它仍然闪烁。我还用一个文本框进行了测试,认为不知何故它正在加载一个图标可能会弄乱它。但是,文本值也会在橙色和紫色之间闪烁。在下面的代码中,我让它反转动画 - 我也尝试将其撕掉,但这并不影响闪烁。我认为它可能有某些东西与我如何设置状态有关,但我不确定。

我的主要教程示例我试图基于以下代码:https://raw.githubusercontent.com/flutter/website/master/_includes/code/animation/animate3/main.dart

请参阅以下代码了解我的实施情况。任何建议都将非常感谢。

class CloudAnimation1 extends StatefulWidget {

  @override
  CloudAnimation1State createState() => new CloudAnimation1State();
}

class CloudAnimation1State extends State<CloudAnimation1> with SingleTickerProviderStateMixin {

  Animation<Color> animation;
  AnimationController controller;

  initState() {
    super.initState();
    controller = new AnimationController(
        duration: const Duration(milliseconds: 1000), vsync: this);
    final Animation curve = new CurvedAnimation(parent: controller, curve: Curves.easeOut);
    animation = new ColorTween(begin: Colors.orange, end: Colors.purple).animate(curve);


    animation.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        controller.reverse();
      } else if (status == AnimationStatus.dismissed) {
        controller.forward();
      }
      setState(() {
        // the animation object’s value is the changed state
      });
    });
    controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return new Container(
      child: new Row(
        children: <Widget>[
          new Text("hello there sailor",
              style: new TextStyle(fontWeight: FontWeight.bold, fontSize: 25.0, color: animation.value)),
          new Icon(FontAwesomeIcons.cloud, color: animation.value, size: 40.0)
        ],
      ),
    );
  }

  dispose() {
    controller.dispose();
    super.dispose();
  }

}

1 个答案:

答案 0 :(得分:2)

您需要创建一个AnimatedIcon来实际处理动画状态。

class AnimatedIcon extends AnimatedWidget {
  final IconData icon;

  AnimatedIcon({Key key, Animation<Color> animation, this.icon})
      :super(key: key, listenable: animation);

  @override
  Widget build(BuildContext context) {
    final Animation<Color> animation = listenable;
    return new Row(
        children: <Widget>[
          new Text("hello there sailor",
              style: new TextStyle(fontWeight: FontWeight.bold, fontSize: 25.0, color: animation.value)),
          new Icon(icon, color: animation.value, size: 40.0)
        ],
      );
  }
}

然后,您可以使用

替换CloudAnimation1State中的内置版本
@override
Widget build(BuildContext context) {
  return new Container(
    child: new AnimatedIcon(
      animation: animation,
      icon: Icons.ac_unit,
    ),
  );
}

然后删除动画状态监听器中的空setState

...替代地

这是闪烁的原因是因为animation.addStatusListener仅在动画状态更改时调用,而不是在每个刻度上调用。 AnimatedWidget只是包裹和抽象听取勾号。

将以下代码添加到initState

animation.addListener(() => setState((){}));

此回调侦听动画的每个刻度并将导致窗口小部件重新呈现。由于你想重新绘制每个小部件的所有子节点,这是有道理的。如果你只想重绘一些孩子,你可能想把它们包装在AnimatedWidgets中。

您仍然希望删除setState内的addStatusListener,因为它对新侦听器来说是多余的。