如何在 Flutter 中使用 Hero 转换期间未运行的动画/动画?
Posted
技术标签:
【中文标题】如何在 Flutter 中使用 Hero 转换期间未运行的动画/动画?【英文标题】:How can I use animation/animation not running during a Hero transition in Flutter? 【发布时间】: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(...),
);
【问题讨论】:
【参考方案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
小部件中以防止意外丢失样式。
【讨论】:
以上是关于如何在 Flutter 中使用 Hero 转换期间未运行的动画/动画?的主要内容,如果未能解决你的问题,请参考以下文章
Flutter:在 ListView Builder 中使用 Hero 动画
如何在 Flutter 中将 Hero 动画添加到我的 ListView?