【问题标题】:How can I use animation/animation not running during a Hero transition in Flutter?如何在 Flutter 中使用 Hero 转换期间未运行的动画/动画?
【发布时间】:2019-06-25 13:48:52
【问题描述】:

我有一张描述产品的卡片网格。当一张卡片被点击时,我希望它翻转(围绕 Y 轴)以显示显示细节的“另一面”,同时增长以填满屏幕。

  • 持续时间 0.0 - 卡片显示正面并处于网格视图中
  • 持续时间 0.5 - 卡片是全屏的 50% 并且垂直于屏幕(正面朝右,“背面”朝左)
  • 持续时间 1.0 - 卡片完全展开并显示“背面”卡片。

我已经设法让翻转动画正常工作,但我无法弄清楚如何在英雄转换期间也让它运行。从this article 看来,我可能需要使用flightShuttleBuilder 才能为叠加层设置动画,但我的动画在过渡期间没有运行:

return Hero(
  tag: 'test',
  flightShuttleBuilder: (
    BuildContext flightContext,
    Animation<double> animation,
    HeroFlightDirection flightDirection,
    BuildContext fromHeroContext,
    BuildContext toHeroContext,
  ) {
    final Hero toHero = toHeroContext.widget;
    return Transform(
      transform: Matrix4.identity()..rotateY(-pi * animation.value),
      alignment: FractionalOffset.center,
      child: toHero,
    );
  },
  child: Card(...),
);

【问题讨论】:

    标签: animation dart flutter widget


    【解决方案1】:

    事实证明,flightShuttleBuilder 仅在过渡的开始和结束时发出值,而不是在整个动画中发出值。从this issue on GitHub 捕获,这显然是预期的行为。

    解决方法是创建自己的过渡,从 AnimatedWidget 扩展;这将正常发出值并且可以在flightShuttleBuilder中使用:

    class FlipcardTransition extends AnimatedWidget {
      final Animation<double> flipAnim;
      final Widget child;
    
      FlipcardTransition({@required this.flipAnim, @required this.child})
          : assert(flipAnim != null),
            assert(child != null),
            super(listenable: flipAnim);
    
      @override
      Widget build(BuildContext context) {
        return Transform(
          transform: Matrix4.identity()
            ..rotateY(-pi * flipAnim.value),
          alignment: FractionalOffset.center,
          child: child,
        );
      }
    }
    
    ...
    
    flightShuttleBuilder: (BuildContext flightContext,
      Animation<double> animation,
      HeroFlightDirection flightDirection,
      BuildContext fromHeroContext,
      BuildContext toHeroContext,) {
        final Hero toHero = toHeroContext.widget;
        return FlipcardTransition(
          flipAnim: animation,
          child: toHero,
        );
    },
    

    【讨论】:

      【解决方案2】:

      正如马特所说,默认行为只是发出开始和结束值,所以我们应该监听动画以获得完整的动画小部件。这是一个例子:

      Hero(
        tag: "YourHeroTag",
        flightShuttleBuilder: (BuildContext flightContext,
          Animation<double> animation,
          HeroFlightDirection flightDirection,
          BuildContext fromHeroContext,
          BuildContext toHeroContext,) {
            return AnimatedBuilder(
              animation: animation,
              builder: (context, value) {
                return Container(
                  color: Color.lerp(Colors.white, Colors.black87, animation.value),
                );
              },
            );
        },
        child: Material( // Wrap in Material to prevent missing theme, mediaquery, ... features....
          // ...
        )
      )
      

      建议包裹在Material 小部件中以防止意外丢失样式。

      【讨论】:

        猜你喜欢
        • 2019-12-16
        • 2019-04-04
        • 1970-01-01
        • 2020-10-28
        • 2021-10-07
        • 2020-03-02
        • 2022-08-17
        • 2013-02-15
        • 2015-06-27
        相关资源
        最近更新 更多