Unverified Commit 406d8f7f authored by chunhtai's avatar chunhtai Committed by GitHub

Fix focus when popping pages (#49714)

Fixes the focus handling when popping pages so that when multiple pages are popped, the focus doesn't try to focus the interstitial pages.
parent 2ccf3f87
...@@ -677,10 +677,15 @@ class _ModalScopeState<T> extends State<_ModalScope<T>> { ...@@ -677,10 +677,15 @@ class _ModalScopeState<T> extends State<_ModalScope<T>> {
super.dispose(); super.dispose();
} }
bool get _shouldIgnoreFocusRequest {
return widget.route.animation?.status == AnimationStatus.reverse ||
(widget.route.navigator?.userGestureInProgress ?? false);
}
// This should be called to wrap any changes to route.isCurrent, route.canPop, // This should be called to wrap any changes to route.isCurrent, route.canPop,
// and route.offstage. // and route.offstage.
void _routeSetState(VoidCallback fn) { void _routeSetState(VoidCallback fn) {
if (widget.route.isCurrent) { if (widget.route.isCurrent && !_shouldIgnoreFocusRequest) {
widget.route.navigator.focusScopeNode.setFirstFocus(focusScopeNode); widget.route.navigator.focusScopeNode.setFirstFocus(focusScopeNode);
} }
setState(fn); setState(fn);
...@@ -713,8 +718,7 @@ class _ModalScopeState<T> extends State<_ModalScope<T>> { ...@@ -713,8 +718,7 @@ class _ModalScopeState<T> extends State<_ModalScope<T>> {
AnimatedBuilder( AnimatedBuilder(
animation: widget.route.navigator?.userGestureInProgressNotifier ?? ValueNotifier<bool>(false), animation: widget.route.navigator?.userGestureInProgressNotifier ?? ValueNotifier<bool>(false),
builder: (BuildContext context, Widget child) { builder: (BuildContext context, Widget child) {
final bool ignoreEvents = widget.route.animation?.status == AnimationStatus.reverse || final bool ignoreEvents = _shouldIgnoreFocusRequest;
(widget.route.navigator?.userGestureInProgress ?? false);
focusScopeNode.canRequestFocus = !ignoreEvents; focusScopeNode.canRequestFocus = !ignoreEvents;
return IgnorePointer( return IgnorePointer(
ignoring: ignoreEvents, ignoring: ignoreEvents,
......
...@@ -1159,6 +1159,52 @@ void main() { ...@@ -1159,6 +1159,52 @@ void main() {
modalBarrierAnimation = tester.widget<AnimatedModalBarrier>(animatedModalBarrier).color; modalBarrierAnimation = tester.widget<AnimatedModalBarrier>(animatedModalBarrier).color;
expect(modalBarrierAnimation.value, Colors.black); expect(modalBarrierAnimation.value, Colors.black);
}); });
testWidgets('focus traverse correct when pop mutiple page simultaneously', (WidgetTester tester) async {
// Regression test: https://github.com/flutter/flutter/issues/48903
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
await tester.pumpWidget(MaterialApp(
navigatorKey: navigatorKey,
home: const Text('dummy1'),
));
final Element textOnPageOne = tester.element(find.text('dummy1'));
final FocusScopeNode focusNodeOnPageOne = FocusScope.of(textOnPageOne);
expect(focusNodeOnPageOne.hasFocus, isTrue);
// Pushes one page.
navigatorKey.currentState.push<void>(
MaterialPageRoute<void>(
builder: (BuildContext context) => const Text('dummy2'),
)
);
await tester.pumpAndSettle();
final Element textOnPageTwo = tester.element(find.text('dummy2'));
final FocusScopeNode focusNodeOnPageTwo = FocusScope.of(textOnPageTwo);
// The focus should be on second page.
expect(focusNodeOnPageOne.hasFocus, isFalse);
expect(focusNodeOnPageTwo.hasFocus, isTrue);
// Pushes another page.
navigatorKey.currentState.push<void>(
MaterialPageRoute<void>(
builder: (BuildContext context) => const Text('dummy3'),
)
);
await tester.pumpAndSettle();
final Element textOnPageThree = tester.element(find.text('dummy3'));
final FocusScopeNode focusNodeOnPageThree = FocusScope.of(textOnPageThree);
// The focus should be on third page.
expect(focusNodeOnPageOne.hasFocus, isFalse);
expect(focusNodeOnPageTwo.hasFocus, isFalse);
expect(focusNodeOnPageThree.hasFocus, isTrue);
// Pops two pages simultaneously.
navigatorKey.currentState.popUntil((Route<void> route) => route.isFirst);
await tester.pumpAndSettle();
// It should refocus page one after pops.
expect(focusNodeOnPageOne.hasFocus, isTrue);
});
}); });
} }
......
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