Unverified Commit 7bf9aea2 authored by LongCatIsLooong's avatar LongCatIsLooong Committed by GitHub

Fix user gesture in CupertinoPageRoute (#39590)

parent d8ca42e2
......@@ -731,6 +731,33 @@ class HeroController extends NavigatorObserver {
_maybeStartHeroTransition(route, previousRoute, HeroFlightDirection.pop, true);
}
@override
void didStopUserGesture() {
if (navigator.userGestureInProgress)
return;
// If the user horizontal drag gesture initiated the flight (i.e. the back swipe)
// didn't move towards the pop direction at all, the animation will not play
// and thus the status update callback _handleAnimationUpdate will never be
// called when the gesture finishes. In this case the initiated flight needs
// to be manually invalidated.
bool isInvalidFlight(_HeroFlight flight) {
return flight.manifest.isUserGestureTransition
&& flight.manifest.type == HeroFlightDirection.pop
&& flight._proxyAnimation.isDismissed;
}
final List<_HeroFlight> invalidFlights = _flights.values
.where(isInvalidFlight)
.toList(growable: false);
// Treat these invalidated flights as dismissed. Calling _handleAnimationUpdate
// will also remove the flight from _flights.
for (_HeroFlight flight in invalidFlights) {
flight._handleAnimationUpdate(AnimationStatus.dismissed);
}
}
// If we're transitioning between different page routes, start a hero transition
// after the toRoute has been laid out with its animation's value at 1.0.
void _maybeStartHeroTransition(
......
......@@ -4,6 +4,7 @@
import 'dart:ui' as ui;
import 'package:flutter/gestures.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
......@@ -25,6 +26,7 @@ Future<ui.Image> createTestImage() {
Key firstKey = const Key('first');
Key secondKey = const Key('second');
Key thirdKey = const Key('third');
Key simpleKey = const Key('simple');
Key homeRouteKey = const Key('homeRoute');
Key routeTwoKey = const Key('routeTwo');
......@@ -52,6 +54,10 @@ final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
child: const Text('twoInset'),
onPressed: () { Navigator.pushNamed(context, '/twoInset'); },
),
FlatButton(
child: const Text('simple'),
onPressed: () { Navigator.pushNamed(context, '/simple'); },
),
],
),
),
......@@ -108,6 +114,19 @@ final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
],
),
),
// This route is the same as /two except that Hero 'a' is shifted to the right by
// 50 pixels. When the hero's in-flight bounds between / and /twoInset are animated
// using MaterialRectArcTween (the default) they'll follow a different path
// then when the flight starts at /twoInset and returns to /.
'/simple': (BuildContext context) => CupertinoPageScaffold(
child: Center(
child: Hero(
tag: 'a',
transitionOnUserGestures: transitionFromUserGestures,
child: Container(height: 150.0, width: 150.0, key: simpleKey),
),
),
),
};
class ThreeRoute extends MaterialPageRoute<void> {
......@@ -2257,6 +2276,38 @@ Future<void> main() async {
},
);
// Regression test for https://github.com/flutter/flutter/issues/38183.
testWidgets('Remove user gesture driven flights when the gesture is invalid', (WidgetTester tester) async {
transitionFromUserGestures = true;
await tester.pumpWidget(MaterialApp(
theme: ThemeData(
platform: TargetPlatform.iOS,
),
routes: routes,
));
await tester.tap(find.text('simple'));
await tester.pump();
await tester.pumpAndSettle();
expect(find.byKey(simpleKey), findsOneWidget);
// Tap once to trigger a flight.
await tester.tapAt(const Offset(10, 200));
await tester.pumpAndSettle();
// Wait till the previous gesture is accepted.
await tester.pump(const Duration(milliseconds: 500));
// Tap again to trigger another flight, see if it throws.
await tester.tapAt(const Offset(10, 200));
await tester.pumpAndSettle();
// The simple route should still be on top.
expect(find.byKey(simpleKey), findsOneWidget);
expect(tester.takeException(), isNull);
});
// Regression test for https://github.com/flutter/flutter/issues/40239.
testWidgets(
'In a pop transition, when fromHero is null, the to hero should eventually become visible',
......
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