Flutter:使用AnimationController和AnimatedBuilder的动画任务完成环

85 阅读2分钟

任务完成环

但我们的目标是通过一些动画将其带入生活。

任务完成环的动画

进入AnimationController

上面的动画可以被启动停止重置为初始值,被称为显式动画

而在Flutter中,我们使用一个 AnimationController来创建明确的动画。这个视频解释了如何。

TL;DR: 下面是如何创建和配置一个AnimationController

// 1. Create a StatefulWidget
class AnimatedTask extends StatefulWidget {
  @override
  _AnimatedTaskState createState() => _AnimatedTaskState();
}

class _AnimatedTaskState extends State<AnimatedTask>
    // 2. Add SingleTickerProviderStateMixin
    with SingleTickerProviderStateMixin {
  // 3. Declare an AnimationController
  late final AnimationController _animationController;
  @override
  void initState() {
    super.initState();
    // 4. Initialize it
    _animationController = AnimationController(
      vsync: this,
      duration: Duration(milliseconds: 750),
    );
  }

  @override
  void dispose() {
    // 5. Dispose it
    _animationController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    // TODO: Use the AnimationController's value to set the progress:
    return TaskCompletionRing(
      progress: 0.6,
    );
  }
}

设置一个AnimationController 需要大量的模板代码。如果你有很多带有显式动画的小部件,这就会变得相当重复了。本教程提供了两种可能的解决方案。如何减少AnimationController的模板代码。Flutter Hooks vs 扩展State类

完成动画代码

一旦我们创建了一个AnimationController ,我们需要在build() 方法中使用它。本课涵盖了所有的细节。

下面是完成的代码。

// 1. Create a StatefulWidget
class AnimatedTask extends StatefulWidget {
  @override
  _AnimatedTaskState createState() => _AnimatedTaskState();
}

class _AnimatedTaskState extends State<AnimatedTask>
    // 2. Add SingleTickerProviderStateMixin
    with SingleTickerProviderStateMixin {
  // 3. Declare an AnimationController
  late final AnimationController _animationController;
  @override
  void initState() {
    super.initState();
    // 4. Initialize it
    _animationController = AnimationController(
      vsync: this,
      duration: Duration(milliseconds: 750),
    );
    // 5. Forward the animation
    _animationController.forward();
  }

  @override
  void dispose() {
    // 6. Dispose it
    _animationController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    // 7. return an AnimatedBuilder
    return AnimatedBuilder(
      // 8. pass the AnimationController as an input
      animation: _animationController,
      builder: (BuildContext context, Widget? child) {
        // 9. Return a widget that is configured
        // with the AnimationController's value
        return TaskCompletionRing(
          progress: _animationController.value,
        );
      },
    );
  }
}

这段代码可以工作,并使动画在我们每次热重启时以编程方式启动。

热重启时的任务完成环形动画

但我们真正想要的是让事情变得互动,这样动画就可以由用户触发。

编码愉快!