首页 > 解决方案 > Flutter loader:同时调整大小和旋转

问题描述

我是 Flutter 的新手,想制作一个自定义的加载器,但找不到解决方案。当用户点击一个按钮并开始一些操作时,我想显示一个自定义小部件(基本上是一个加载器,通知用户操作已经开始)弹出到屏幕中心并增大大小(从 0x0到 300x300),同时它正在旋转。当它达到最大尺寸(300x300)时,我希望它缩小到 0x0 的大小并隐藏/消失,同时旋转。此动画需要 2 秒。如果 2 秒后操作未完成,我想从动画重新开始。

标签: flutterdartflutter-animation

解决方案


您可以非常轻松地创建自己的动画。使用AnimationandAnimationController你基本上可以做任何你能想到的事情。

如果您想深入了解使用 Flutter 制作复杂 UI的动画,请观看此视频

要实现您的要求,您可以使用无状态小部件构建加载指示器。

这是一个交互式示例

class MyLoadingIndicator extends StatefulWidget {
  final Widget child;
  const MyLoadingIndicator({
    @required this.child,
    Key key,
  }) : super(key: key);

  @override
  _MyLoadingIndicatorState createState() => _MyLoadingIndicatorState();
}

class _MyLoadingIndicatorState extends State<MyLoadingIndicator> with TickerProviderStateMixin {
  AnimationController rotateController;
  Animation<double> rotateAnimation;
  AnimationController scaleController;
  Animation<double> scaleAnimation;

  @override
  void initState() {
    super.initState();
    rotateController = AnimationController(
      duration: const Duration(seconds: 1),
      reverseDuration: const Duration(seconds: 1),
      vsync: this,
    );

    rotateAnimation = CurvedAnimation(parent: rotateController, curve: Curves.linear);
    rotateController.repeat(
      min: 0,
      max: 1,
      period: Duration(seconds: 2),
    );
    scaleController = AnimationController(
      duration: const Duration(seconds: 1),
      reverseDuration: const Duration(seconds: 1),
      vsync: this,
    );

    scaleAnimation = CurvedAnimation(parent: scaleController, curve: Curves.linear);
    scaleController.repeat(
      min: 0,
      max: 1,
      period: Duration(seconds: 2),
      reverse: true,
    );
  }

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

  @override
  Widget build(BuildContext context) {
    return RotationTransition(
      turns: rotateAnimation,
      child: ScaleTransition(
        scale: scaleAnimation,
        child: Container(
          height: 300,
          width: 300,
          color: Colors.red,
          child: widget.child,
        ),
      ),
    );
  }
}

推荐阅读