禁用Flutter Hero反向动画

时间:2018-10-31 17:20:26

标签: android user-interface animation flutter

给出2条路线,例如父和子以及带有相同标签的Hero(..)小部件。 当用户在“父”屏幕上并打开“子”时,将对Hero小部件进行动画处理。当它返回时(通过Navigator.pop),它也具有动画效果。

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

有没有一种在小部件上被动画化之前会被其调用的处理程序?然后,我可能可以更改Hero标签并解决问题。

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

有没有更简单的方法来实现这一点?

2 个答案:

答案 0 :(得分:0)

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

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(应该弹出的那个)中,您必须向flightShuttleBuilder提供一个Hero参数,然后您才能检查方向,如果它正在弹出,只需用一个{ {1}}淡入淡出过渡

结果是这样的: enter image description here

我希望这是预期的结果,当然,您可以完全更改flightShuttleBuilder内部的过渡以改变效果!由您决定:)

答案 1 :(得分:0)

尽管目前尚无内置方法可以在任何特定方向上禁用Hero动画,尽管CLucera将FadeTransitionHeroFlightDirection结合使用是一种创造性的方法,但最直接的方法是打破两个英雄之间的tag关联:

当您从第二英雄回到第一英雄时,只需将第一英雄的标签临时更改为其他标签,英雄就不会恢复动画。简化示例:

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();
                                    },
                                  ),
                                )
                            ),
                          );
                        }
                    )
                );
              },
            )
        ),
      ),
    );
  }
}

但是,如果您想直接修改动画,则可以像在CLucera中一样在flightShuttleBuilder内播放。您还可以查看medium/mastering-hero-animations-in-flutter来进一步探索该区域。