I have a grid of cards depicting products. When a card is tapped, I want it to flip over (around the Y axis) to reveal the "other side" that shows the details, while simultaneously growing to fill the screen.
I have managed to get a flip animation working, but am having trouble figuring out how to also get it to run during the Hero transition. From this article it seems like I may need to make use of flightShuttleBuilder
to be able to animate the overlay but my animation does not run during the transition:
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(...),
);
As it turns out, flightShuttleBuilder
only emits values at the start and end of the transition instead of throughout the animation. Capturing from this issue on GitHub , it is apparently expected behavior.
The workaround is to create your own transition which extends from AnimatedWidget
; that will emit values normally and can be used in the 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,
);
},
As Matt said, the default behavior is only emitting start and end value, so we should listen the animation to get the full animatable widget. Here is an example:
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....
// ...
)
)
It's recommended to wrap in Material
widget to prevent unexpected missing style.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.