Unverified Commit 6dc9bf0a authored by Michael Goderbauer's avatar Michael Goderbauer Committed by GitHub

Fix curve for popping hero (#39844)

parent 0de6fc82
......@@ -413,6 +413,7 @@ class _HeroFlightManifest {
@required this.createRectTween,
@required this.shuttleBuilder,
@required this.isUserGestureTransition,
@required this.isDiverted,
}) : assert(fromHero.widget.tag == toHero.widget.tag);
final HeroFlightDirection type;
......@@ -425,6 +426,7 @@ class _HeroFlightManifest {
final CreateRectTween createRectTween;
final HeroFlightShuttleBuilder shuttleBuilder;
final bool isUserGestureTransition;
final bool isDiverted;
Object get tag => fromHero.widget.tag;
......@@ -432,6 +434,7 @@ class _HeroFlightManifest {
return CurvedAnimation(
parent: (type == HeroFlightDirection.push) ? toRoute.animation : fromRoute.animation,
curve: Curves.fastOutSlowIn,
reverseCurve: isDiverted ? null : Curves.fastOutSlowIn.flipped,
);
}
......@@ -805,6 +808,7 @@ class HeroController extends NavigatorObserver {
if (toHeroes[tag] != null) {
final HeroFlightShuttleBuilder fromShuttleBuilder = fromHeroes[tag].widget.flightShuttleBuilder;
final HeroFlightShuttleBuilder toShuttleBuilder = toHeroes[tag].widget.flightShuttleBuilder;
final bool isDiverted = _flights[tag] != null;
final _HeroFlightManifest manifest = _HeroFlightManifest(
type: flightType,
......@@ -818,9 +822,10 @@ class HeroController extends NavigatorObserver {
shuttleBuilder:
toShuttleBuilder ?? fromShuttleBuilder ?? _defaultHeroFlightShuttleBuilder,
isUserGestureTransition: isUserGestureTransition,
isDiverted: isDiverted,
);
if (_flights[tag] != null)
if (isDiverted)
_flights[tag].divert(manifest);
else
_flights[tag] = _HeroFlight(_handleFlightEnded)..start(manifest);
......
......@@ -1254,17 +1254,17 @@ Future<void> main() async {
await tester.pump(duration * 0.25);
actualHeroCenter = tester.getCenter(find.byKey(firstKey));
predictedHeroCenter = popCenterTween.lerp(curve.flipped.transform(0.25));
predictedHeroCenter = popCenterTween.lerp(curve.transform(0.25));
expect(actualHeroCenter, within<Offset>(distance: epsilon, from: predictedHeroCenter));
await tester.pump(duration * 0.25);
actualHeroCenter = tester.getCenter(find.byKey(firstKey));
predictedHeroCenter = popCenterTween.lerp(curve.flipped.transform(0.5));
predictedHeroCenter = popCenterTween.lerp(curve.transform(0.5));
expect(actualHeroCenter, within<Offset>(distance: epsilon, from: predictedHeroCenter));
await tester.pump(duration * 0.25);
actualHeroCenter = tester.getCenter(find.byKey(firstKey));
predictedHeroCenter = popCenterTween.lerp(curve.flipped.transform(0.75));
predictedHeroCenter = popCenterTween.lerp(curve.transform(0.75));
expect(actualHeroCenter, within<Offset>(distance: epsilon, from: predictedHeroCenter));
await tester.pumpAndSettle();
......@@ -1375,17 +1375,17 @@ Future<void> main() async {
await tester.pump(duration * 0.25);
actualHeroRect = tester.getRect(find.byKey(firstKey));
predictedHeroRect = popRectTween.lerp(curve.flipped.transform(0.25));
predictedHeroRect = popRectTween.lerp(curve.transform(0.25));
expect(actualHeroRect, within<Rect>(distance: epsilon, from: predictedHeroRect));
await tester.pump(duration * 0.25);
actualHeroRect = tester.getRect(find.byKey(firstKey));
predictedHeroRect = popRectTween.lerp(curve.flipped.transform(0.5));
predictedHeroRect = popRectTween.lerp(curve.transform(0.5));
expect(actualHeroRect, within<Rect>(distance: epsilon, from: predictedHeroRect));
await tester.pump(duration * 0.25);
actualHeroRect = tester.getRect(find.byKey(firstKey));
predictedHeroRect = popRectTween.lerp(curve.flipped.transform(0.75));
predictedHeroRect = popRectTween.lerp(curve.transform(0.75));
expect(actualHeroRect, within<Rect>(distance: epsilon, from: predictedHeroRect));
await tester.pumpAndSettle();
......@@ -2255,4 +2255,83 @@ Future<void> main() async {
moreOrLessEquals(tester.getTopLeft(find.text('1')).dx, epsilon: 0.01)
);
});
testWidgets('popped hero uses fastOutSlowIn curve', (WidgetTester tester) async {
final Key container1 = UniqueKey();
final Key container2 = UniqueKey();
final GlobalKey<NavigatorState> navigator = GlobalKey<NavigatorState>();
final Animatable<Size> tween = SizeTween(
begin: const Size(200, 200),
end: const Size(100, 100),
).chain(CurveTween(curve: Curves.fastOutSlowIn));
await tester.pumpWidget(
MaterialApp(
navigatorKey: navigator,
home: Scaffold(
body: Center(
child: Hero(
tag: 'test',
createRectTween: (Rect begin, Rect end) {
return RectTween(begin: begin, end: end);
},
child: Container(
key: container1,
height: 100,
width: 100,
),
),
),
),
),
);
final Size originalSize = tester.getSize(find.byKey(container1));
expect(originalSize, const Size(100, 100));
navigator.currentState.push(MaterialPageRoute<void>(builder: (BuildContext context) {
return Scaffold(
body: Center(
child: Hero(
tag: 'test',
createRectTween: (Rect begin, Rect end) {
return RectTween(begin: begin, end: end);
},
child: Container(
key: container2,
height: 200,
width: 200,
),
),
),
);
}));
await tester.pumpAndSettle();
final Size newSize = tester.getSize(find.byKey(container2));
expect(newSize, const Size(200, 200));
navigator.currentState.pop();
await tester.pump();
// Jump 25% into the transition (total length = 300ms)
await tester.pump(const Duration(milliseconds: 75)); // 25% of 300ms
Size heroSize = tester.getSize(find.byKey(container1));
expect(heroSize, tween.transform(0.25));
// Jump to 50% into the transition.
await tester.pump(const Duration(milliseconds: 75)); // 25% of 300ms
heroSize = tester.getSize(find.byKey(container1));
expect(heroSize, tween.transform(0.50));
// Jump to 75% into the transition.
await tester.pump(const Duration(milliseconds: 75)); // 25% of 300ms
heroSize = tester.getSize(find.byKey(container1));
expect(heroSize, tween.transform(0.75));
// Jump to 100% into the transition.
await tester.pump(const Duration(milliseconds: 75)); // 25% of 300ms
heroSize = tester.getSize(find.byKey(container1));
expect(heroSize, tween.transform(1.0));
});
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment