禁用 Flutter Hero 反向动画
Posted
技术标签:
【中文标题】禁用 Flutter Hero 反向动画【英文标题】:Disabling Flutter Hero reverse animation 【发布时间】:2019-04-04 22:44:34 【问题描述】:给定 2 条路线,例如parent 和 child 以及具有相同标签的 Hero(..) 小部件。
当用户在“父”屏幕上并打开“子”时 - Hero 小部件是动画的。当它返回时(通过Navigator.pop
),它也是动画的。
我正在寻找一种在返回时禁用该动画的方法(通过 Navigator.pop
从子级到父级)。
是否有一种处理程序可以在小部件“动画化”之前在小部件上调用?然后我可能可以更改Hero
标签并解决问题。
或者,当在父窗口小部件中为路由创建“构建器”时,我可能会记得对目标窗口小部件的引用,然后在调用 Navigator.pop
之前通知它“你将被动画化”。这还需要使该小部件有状态(我还没有找到强制重建无状态小部件的方法)。
有没有更简单的实现方法?
【问题讨论】:
【参考方案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来改变效果!这取决于你:)
【讨论】:
以上是关于禁用 Flutter Hero 反向动画的主要内容,如果未能解决你的问题,请参考以下文章
Flutter:在 ListView Builder 中使用 Hero 动画
Flutter - 我可以用 Hero 包装每个小部件来为它们设置动画吗