当前位置: 首页 > 知识库问答 >
问题:

(Flutter)在没有setstate的情况下同时出现两个动画

游乐池
2023-03-14

所以我在和烦人的问题作斗争。我想同时运行2个动画,但如果没有:

animationController.addListener(() {
  setState(() {});
});

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

当我在两个动画控制器中删除setstate并运行此函数时:

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

它只运行第一个动画控制器,而不运行第二个。动画是简单的tween,彼此相反,所以我想做一些东西,用一个tween,对于第二个属性,我做一些反函数,但我想不出任何解,所以它实际上是可行的。也许我错过了一些简单的东西。

以下是我的完整代码:

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中学习了交错动画,但是我需要两个动画同时运行,而不需要setstate。因此我在网上没有找到任何东西,所以我在这里提出问题。提前谢谢你。

共有2个答案

南宫俊喆
2023-03-14

阅读本文的第一部分,它将解决您的查询以及为什么不应该对自定义动画使用setState的原因。

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

您在这里所做的基本工作是在每次调用小部件时不使用setState并重新构建整个小部件,而是删除其中的侦听器和setState。

然后在AnimatedBuilder中包装to be animated小部件,并将动画控制器作为参数传递到其中。现在,如果您仔细观察的话,它也有builder和child参数。

将小部件的部分放置在子小部件中,在整个动画中不会被更改。(例如:如果您试图对容器的位置进行动画化,那么您可以将整个容器小部件放置在子参数中,因为在动画化过程中,容器小部件中的内容不会被更新。

这不会在每次更新动画框架时重建子小部件,而不是对整个小部件进行动画,从而生成更平滑的动画。

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

有关AnimatedBuilder小部件的实现,请参阅本文。

况明贤
2023-03-14

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

我使用了@Simon Pot的建议,在此基础上,我将widget包装到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),
        ]),
      ),
    ]);
  }
}
 类似资料:
  • 这两个dataframe没有任何公共列。两个数据流中的行数和列数也不同。我尝试插入一个新的虚拟列,以增加row_index值,如下val dfr=df1.withcolumn(“row_index”,monotonically_increasing_id())所示。 但由于我使用的是Spark2,因此不支持monotonically_increasing_id方法。有没有办法把两个datafram

  • 我刚刚通过nodejs.org上的软件包安装了node和npm,每当我试图搜索或安装npm时,它都会抛出以下错误,除非我执行该命令。我觉得这是一个权限问题?我已经是管理员了。

  • 问题内容: 假定派生自以下类的类: 如果我想在两个初始化器中都使用相同的代码,例如 并且 不要 在类实现中 重复 两次 该代码 ,我将如何构造方法? 尝试的方法: 创建一个在-> Swift编译器在调用之前给出有关未初始化变量的错误之后调用的方法 之前的调用显然失败,并出现编译器错误 “ super.init调用之前使用了’self’ 问题答案: 正如GoZoner所说,将变量标记为可选将起作用。

  • 问题内容: 我正在学习使用Selenium(v2.20)来领先一些 即将使用它创建浏览器测试的程序员。我想在 陷阱到达之前发现它们,而我却跌入了一个陷阱。 当我创建ChromeDriver时,它始终会弹出“ Google Chrome EULA”并 显示两个按钮:“接受并运行”和“取消”。因为我希望这是一个 自动化测试,所以让用户单击按钮是不可能的。 我查看了Chromium CommandSwi

  • 你好,我有个问题。以下是代码示例: 我有一个多选表格: 这是我的开关盒: 代码的工作原理是,如果用户选择例如GB11,结果将是: 工厂GB11 ZMD_LPLCNMAT_GB11 ZMD_LPQAMAT_GB11 ZMD_LSOCNMAT_GB11 ZMD_PLNTMAT_GB11 ZMD_SLSVMAT_GB11 当我选择GB10和GB20时,我不想选择得到结果,例如“测试”,而不是它们的组合。

  • 问题内容: 我正在使用以下sql语句对来自两个不同表的两个列中的值求和。该语句可以输出,但不能输出所需的结果。 我的桌子在这里: -- -转储表数据 -- -表格的表格结构 -- -转储表数据 问题答案: 这应该做到这一点: