Unverified Commit 09073a08 authored by Hans Muller's avatar Hans Muller Committed by GitHub

Rebuild modal routes when the value of userGestureInProgress changes (#41150)

parent 20d9a244
......@@ -2239,10 +2239,25 @@ class NavigatorState extends State<Navigator> with TickerProviderStateMixin {
route.dispose();
}
int get _userGesturesInProgress => _userGesturesInProgressCount;
int _userGesturesInProgressCount = 0;
set _userGesturesInProgress(int value) {
_userGesturesInProgressCount = value;
userGestureInProgressNotifier.value = _userGesturesInProgress > 0;
}
/// Whether a route is currently being manipulated by the user, e.g.
/// as during an iOS back gesture.
bool get userGestureInProgress => _userGesturesInProgress > 0;
int _userGesturesInProgress = 0;
///
/// See also:
///
/// * [userGestureInProgressNotifier], which notifies its listeners if
/// the value of [userGestureInProgress] changes.
bool get userGestureInProgress => userGestureInProgressNotifier.value;
/// Notifies its listeners if the value of [userGestureInProgress] changes.
final ValueNotifier<bool> userGestureInProgressNotifier = ValueNotifier<bool>(false);
/// The navigator is being controlled by a user gesture.
///
......
......@@ -652,9 +652,18 @@ class _ModalScopeState<T> extends State<_ModalScope<T>> {
context,
widget.route.animation,
widget.route.secondaryAnimation,
IgnorePointer(
ignoring: widget.route.navigator.userGestureInProgress
|| widget.route.animation?.status == AnimationStatus.reverse,
// This additional AnimatedBuilder is include because if the
// value of the userGestureInProgressNotifier changes, it's
// only necessary to rebuild the IgnorePointer widget.
AnimatedBuilder(
animation: widget.route.navigator.userGestureInProgressNotifier,
builder: (BuildContext context, Widget child) {
return IgnorePointer(
ignoring: widget.route.navigator.userGestureInProgress
|| widget.route.animation?.status == AnimationStatus.reverse,
child: child,
);
},
child: child,
),
);
......
......@@ -707,4 +707,76 @@ void main() {
expect(tester.getTopLeft(find.byKey(pageScaffoldKey)), const Offset(400, 0));
expect(tester.getTopLeft(find.byKey(homeScaffoldKey)).dx, lessThan(0));
});
testWidgets('After a pop caused by a back-swipe, input reaches the exposed route', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/41024
final GlobalKey homeScaffoldKey = GlobalKey();
final GlobalKey pageScaffoldKey = GlobalKey();
int homeTapCount = 0;
int pageTapCount = 0;
await tester.pumpWidget(
MaterialApp(
theme: ThemeData(platform: TargetPlatform.iOS),
home: Scaffold(
key: homeScaffoldKey,
body: GestureDetector(
onTap: () {
homeTapCount += 1;
}
),
),
),
);
await tester.tap(find.byKey(homeScaffoldKey));
expect(homeTapCount, 1);
expect(pageTapCount, 0);
final ValueNotifier<bool> notifier = Navigator.of(homeScaffoldKey.currentContext).userGestureInProgressNotifier;
expect(notifier.value, false);
Navigator.push<void>(homeScaffoldKey.currentContext, MaterialPageRoute<void>(
builder: (BuildContext context) {
return Scaffold(
key: pageScaffoldKey,
appBar: AppBar(title: const Text('Page')),
body: Padding(
padding: const EdgeInsets.all(16),
child: GestureDetector(
onTap: () {
pageTapCount += 1;
}
),
),
);
},
));
await tester.pumpAndSettle();
await tester.tap(find.byKey(pageScaffoldKey));
expect(homeTapCount, 1);
expect(pageTapCount, 1);
// Trigger the basic iOS back-swipe dismiss transition. Drag the pushed
// "page" route more than halfway across the screen and then release it.
final TestGesture gesture = await tester.startGesture(const Offset(5, 300));
await gesture.moveBy(const Offset(500, 0));
await tester.pump();
expect(tester.getTopLeft(find.byKey(pageScaffoldKey)), const Offset(500, 0));
expect(tester.getTopLeft(find.byKey(homeScaffoldKey)).dx, lessThan(0));
expect(notifier.value, true);
await gesture.up();
await tester.pumpAndSettle();
expect(notifier.value, false);
expect(find.byKey(pageScaffoldKey), findsNothing);
// The back-swipe dismiss pop transition has finished and input on the
// home page still works.
await tester.tap(find.byKey(homeScaffoldKey));
expect(homeTapCount, 2);
expect(pageTapCount, 1);
});
}
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