Flutter Animation动画开发之——reverse反向播放

我们知道AnimationController.forward()可以正向播放动画,如果要反向播放动画,可以调用AnimationController.reverse()

踩坑

马上写段代码验证一下,如下代码演示了一个绿色的方块,方向执行动画,大小从200缩小到100

但是理想很美好,现实很残酷,运行后方块一动不动,一直保持最小的状态,也就是宽高100

class AnimationRoute extends StatefulWidget {
  @override
  AnimationRouteState createState() => AnimationRouteState();
}

class AnimationRouteState extends State<AnimationRoute> with SingleTickerProviderStateMixin {

  AnimationController controller;

  initState() {
    super.initState();
    // Controller设置动画时长
    // vsync设置一个TickerProvider,当前State 混合了SingleTickerProviderStateMixin就是一个TickerProvider
    controller = AnimationController(
        lowerBound: 100,
        upperBound: 200,
        duration: Duration(seconds: 5),
        vsync: this //
    );
    controller.reverse();
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
        animation: controller,
        builder: (BuildContext ctx, Widget child) {
          return Center(
            child: Container(
              color: Colors.green,
              width: controller.value,
              height: controller.value,
            ),
          );
        }
    );
  }

  @override
  void dispose() {
    // 释放资源
    controller.dispose();
    super.dispose();
  }
}

解决方法

发现问题,最有效的解决方法就是看源码,我们先看下reverse方法的源码,发现里面有一个可选参数from,该参数如果有传就会设置当前动画的value值为from的值,然后从该值开始反向执行动画。

我猜想可能是AnimationController的value起始值是lowerBound,反向播放的时候也是lowerBound,导致了动画我发播放,因为反向播放时lowerBound是终点值,已开始就是终点值,肯定是无变化的

所以我们一开始可以传入一个from值,比如200或者upperBound,这样就可以从200变化到100

  /// Starts running this animation in reverse (towards the beginning).
  ///
  /// Returns a [TickerFuture] that completes when the animation is dismissed.
  ///
  /// The most recently returned [TickerFuture], if any, is marked as having been
  /// canceled, meaning the future never completes and its [TickerFuture.orCancel]
  /// derivative future completes with a [TickerCanceled] error.
  ///
  /// During the animation, [status] is reported as [AnimationStatus.reverse],
  /// which switches to [AnimationStatus.dismissed] when [lowerBound] is
  /// reached at the end of the animation.
  TickerFuture reverse({ double from }) {
    assert(() {
      if (duration == null && reverseDuration == null) {
        throw FlutterError(
          'AnimationController.reverse() called with no default duration or reverseDuration.\n'
          'The "duration" or "reverseDuration" property should be set, either in the constructor or later, before '
          'calling the reverse() function.'
        );
      }
      return true;
    }());
    assert(
      _ticker != null,
      'AnimationController.reverse() called after AnimationController.dispose()\n'
      'AnimationController methods should not be used after calling dispose.'
    );
    _direction = _AnimationDirection.reverse;
    if (from != null)
      value = from;
    return _animateToInternal(lowerBound);
  }

所以只需把原来示例里的controller.reverse()改成如下代码即可

controller.reverse(from: controller.upperBound);

或者直接设置200,或者100到200间的任何值也可以,这样可以从中间某个地方反向执行动画

controller.reverse(from: 200);

 或者在调用controller.reverse()前先设置value的值

controller.value = 200;
controller.reverse();

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值