没有setstate同时出现两个动画

Two animations at the same time without setstate

所以我正在努力解决烦人的问题。我想同时 运行 2 个动画,如果没有:

就无法工作
animationController.addListener(() {
  setState(() {});
});

这让一切变得波涛汹涌,我想根除它。

当我删除我的两个动画控制器中的 setState 和 运行 这个函数时:

 void animateButton() {
    if (_forward) {
      animationController.reverse();
      animationController2.reverse();
      _forward = false;
    } else {
      animationController.forward();
      animationController2.forward();
      _forward = true;
    }
  }

运行只有第一个动画控制器,没有第二个。动画是彼此相反的简单补间动画,所以我正在考虑做一些使用补间动画的事情,然后 属性 我会做一些反函数,但我想不出任何解决方案,所以它实际上会起作用。也许我遗漏了一些简单的东西。

这是我的完整代码:

class _DetailScreenState extends State<DetailScreenWidget>
    with TickerProviderStateMixin {
  final GlobalKey<SendWidgetState> _key = GlobalKey();

  AnimationController animationController;
  Animation<double> tween;
  AnimationController animationController2;
  Animation<double> tween2;

  @override
  void initState() {
    super.initState();
    // FocusScope.of(context).unfocus();
    animationController = AnimationController(
        vsync: this, duration: Duration(milliseconds: 800));
    tween = Tween<double>(begin: 0.0, end: 1.0).animate(
        CurvedAnimation(parent: animationController, curve: Curves.easeOut));
    animationController.addListener(() {
      setState(() {});
    });

    animationController2 = AnimationController(
        vsync: this, duration: Duration(milliseconds: 800));
    tween2 = Tween<double>(begin: 1.0, end: 0.0).animate(
        CurvedAnimation(parent: animationController2, curve: Curves.easeOut));
    animationController2.addListener(() {
      setState(() {});
    });
  }
  void showHideSendView() {
    if (_forward) {
      animationController.reverse();
      animationController2.reverse();
      _forward = false;
    } else {
      animationController.forward();
      animationController2.forward();
      _key.currentState.initView();
      _forward = true;
    }
  }

  void showTransactions() {
    setState(() {
      showHideSendView();
    });
  }

  Widget build(BuildContext context) {
    return Stack(children: [
      
      SafeArea(
        child: Stack(children: [
          TransactionWidget(
            opacity: tween2,
            getTransactions: _getTransactions,
          ),
          SizeTransition(
            sizeFactor: tween,
            axis: Axis.vertical,
            axisAlignment: -1,
            child: SendWidget(
              key:_key,
              func: shrinkSendView,
              height: tween,
            ),
          ),
          BalanceCard(
              getBalanceFuture: _getBalanceFuture,
              onPressSend: showTransactions),
        ]),
      ),
    ]);
  }
}

我在 flutter 中了解了 staggered animation,但是我需要 2 个动画同时到 运行 而没有 setState。为此,我在互联网上没有找到任何东西,所以我求助于在这里提问。

阅读本文的第一部分,它将解决您的疑问以及您不应将 setState 用于自定义动画的原因。

https://medium.com/flutter-community/flutter-laggy-animations-how-not-to-setstate-f2dd9873b8fc

你在这里做的基本上不是使用 setState 并在每次调用它时重建整个小部件,而是删除侦听器和其中的 setState。

然后将要动画的小部件包装在 AnimatedBuilder 中,并将动画控制器作为参数传递给它。现在,如果您仔细观察,它也有构建器和子参数。

将您的小部件的部分在整个动画过程中不会更改的子小部件内。 (例如:如果您尝试为容器的位置设置动画,则可以将整个容器小部件放置在子参数中,因为其中的内容在动画期间不会更新。

这不会为整个小部件设置动画,而是不会在您每次更新动画帧时重建子小部件,从而使动画更加流畅。

小部件的其余部分将受到动画控制器值变化的影响,应将其放置在生成器函数中,该函数提供动画控制器的新值和您刚刚初始化的子小部件。

AnimatedBuilder 小部件的实现请参阅文章。

好吧,我解决了,我想需要 statefulWidget 它会在动画的每一步上更新,或者我可能正在想象事情,现在是工作代码,没有口吃。

我使用了@Simon Pot 的建议,最重要的是我将小部件包装到 FadeTransition

代码如下:

class _DetailScreenState extends State<DetailScreenWidget>
    with TickerProviderStateMixin {
  final GlobalKey<SendWidgetState> _key = GlobalKey();

  AnimationController animationController;
  Animation<double> tween;
  Animation<double> tween2;

  Future _getBalanceFuture;
  Future _getTransactions;

  bool _forward = false;

  @override
  void initState() {
    super.initState();
    animationController = AnimationController(
        vsync: this, duration: Duration(milliseconds: 800));
    tween2 = Tween<double>(begin: 1.0, end: 0.0).animate(
        CurvedAnimation(parent: animationController, curve: Curves.easeOut));
    tween = Tween<double>(begin: 0.0, end: 1.0).animate(
        CurvedAnimation(parent: animationController, curve: Curves.easeOut));

    _getBalanceFuture = getBalance();
    _getTransactions = _getTranData();
  }

 
  void animateButton() {
    if (_forward) {
      animationController.reverse();
      _forward = false;
    } else {
      animationController.forward();
      _key.currentState.initView();
      _forward = true;
    }
  }

  void showTransactions() {
      animateButton();
  }


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

  Widget build(BuildContext context) {
    return Stack(children: [
      SafeArea(
        child: Stack(children: [
          FadeTransition(
            opacity: tween2,
            child: TransactionWidget(
            getTransactions: _getTransactions,
          ),
            ),
          SizeTransition(
            sizeFactor: tween,
            axis: Axis.vertical,
            axisAlignment: -1,
            child: SendWidget(
              key:_key,
              func: shrinkSendView,
              height: tween,
            ),
          ),
          BalanceCard(
              getBalanceFuture: _getBalanceFuture,
              onPressSend: showTransactions),
        ]),
      ),
    ]);
  }
}