【问题标题】:Disabling Flutter Hero reverse animation禁用 Flutter Hero 反向动画
【发布时间】:2019-04-04 22:44:34
【问题描述】:

给定 2 条路线,例如parent 和 child 以及具有相同标签的 Hero(..) 小部件。 当用户在“父”屏幕上并打开“子”时 - Hero 小部件是动画的。当它返回时(通过Navigator.pop),它也是动画的。

我正在寻找一种在返回时禁用该动画的方法(通过 Navigator.pop 从子级到父级)。

是否有一种处理程序可以在小部件“动画化”之前在小部件上调用?然后我可能可以更改Hero 标签并解决问题。

或者,当在父窗口小部件中为路由创建“构建器”时,我可能会记得对目标窗口小部件的引用,然后在调用 Navigator.pop 之前通知它“你将被动画化”。这还需要使该小部件有状态(我还没有找到强制重建无状态小部件的方法)。

有没有更简单的实现方法?

【问题讨论】:

    标签: android user-interface animation flutter


    【解决方案1】:

    虽然目前没有内置方法可以在任何特定方向禁用英雄动画,但 CLucera 使用 FadeTransition 和 HeroFlightDirection 是一种创造性的方式,最直接的方法是打破 tag两个英雄之间的关联:

    当你从 2 号英雄回到 1 号英雄时,只是暂时将 1 号英雄的标签更改为其他东西,然后英雄不会动画回来。一个简化的例子:

    class _MyHomePageState extends State<MyHomePage> {
    
      String tag1, tag2;
      String sharedTag = 'test';
      String breakTag = 'notTest';
    
      @override
      void initState() {
        super.initState();
        tag1 = sharedTag;
        tag2 = sharedTag;
      }
    
      @override
      Widget build(BuildContext context) {
    
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: Center(
            child: Hero(
                tag: tag1,
                child: RaisedButton(
                  child: Text("hi"),
                  onPressed: () {
                    // restore the tag
                    if (tag1 != sharedTag) {
                      setState(() {
                        tag1 = sharedTag;
                      });
                    }
    
                    // second route
                    Navigator.of(context).push(
                        MaterialPageRoute<void>(
                            builder: (BuildContext context) {
                              return Scaffold(
                                appBar: AppBar(
                                  title: Text(widget.title),
                                ),
                                body: Container(
                                    alignment: Alignment.topLeft,
                                    child: Hero(
                                      tag: tag2,
                                      child: RaisedButton(
                                        child: Text('hello'),
                                        onPressed: () {
                                          // change the tag to disable the reverse anim
                                          setState(() {
                                            tag1 = breakTag;
                                          });
    
                                          Navigator.of(context).pop();
                                        },
                                      ),
                                    )
                                ),
                              );
                            }
                        )
                    );
                  },
                )
            ),
          ),
        );
      }
    }
    

    但是如果你想直接修改动画,那么在flightShuttleBuilder 里面玩是像 CLucera 那样做的方法。您还可以查看medium/mastering-hero-animations-in-flutter 以进一步探索该区域。

    【讨论】:

      【解决方案2】:

      目前我能想到的唯一方法是以一种似乎没有动画的方式“动画”弹出的英雄,让我们检查一下这段代码:

      class SecondRoute extends StatelessWidget {
        @override
        Widget build(BuildContext context) {
          return Scaffold(
              body: Hero(
                flightShuttleBuilder: (context, anim, direction, fromContext, toContext) {
                  final Hero toHero = toContext.widget;
                  if (direction == HeroFlightDirection.pop) {
                    return FadeTransition(
                      opacity: AlwaysStoppedAnimation(0),
                      child: toHero.child,
                    );
                  } else {
                    return toHero.child;
                  }
                },
                child: FlatButton(
                  child: Text("prev 1"),
                  onPressed: () {
                    Navigator.of(context).pop();
                  },
                ),
                tag: "test",
              ));
        }
      }
      

      在您的 SecondRoute(应该弹出的那个)中,您必须向您的 Hero 提供一个 flightShuttleBuilder 参数,然后您可以检查方向,如果它正在弹出,只需使用 AlwaysStoppedAnimation 淡入淡出过渡隐藏小部件

      结果是这样的:

      我希望这和预期的结果一样,当然你可以完全改变flightShuttleBuilder里面的transition来改变效果!这取决于你:)

      【讨论】:

        猜你喜欢
        • 2019-12-16
        • 1970-01-01
        • 2021-10-07
        • 1970-01-01
        • 2020-10-24
        • 2019-06-25
        • 2020-03-02
        • 2020-02-11
        • 2020-10-28
        相关资源
        最近更新 更多