Unverified Commit d8e72c6d authored by flutteractionsbot's avatar flutteractionsbot Committed by GitHub

[CP-stable]Refactor route focus node creation (#149378)

### Issue Link:
https://github.com/flutter/flutter/issues/148867

Cherry-picking https://github.com/flutter/flutter/pull/147390

### Changelog Description:
Fixes a focus issue that causes TextFields to not function after cupertino back swipes

### Impact Description:
iOS, macos, iOS web, macos web app that uses TextField

### Workaround:
disable cupertino back swipe

### Risk:
What is the risk level of this cherry-pick?

### Test Coverage:
Are you confident that your fix is well-tested by automated tests?

### Validation Steps:
What are the steps to validate that this fix works?

TextField should not be broken after a cupertino back swipe
parent a14f74ff
......@@ -10,7 +10,7 @@ void main() {
testWidgets('Tapping FAB increments counter', (WidgetTester tester) async {
await tester.pumpWidget(const example.ListenableBuilderExample());
String getCount() => (tester.widget(find.descendant(of: find.byType(ListenableBuilder), matching: find.byType(Text))) as Text).data!;
String getCount() => (tester.widget(find.descendant(of: find.byType(ListenableBuilder).last, matching: find.byType(Text))) as Text).data!;
expect(find.text('Current counter value:'), findsOneWidget);
expect(find.text('0'), findsOneWidget);
......
......@@ -1022,6 +1022,8 @@ class _ModalScopeState<T> extends State<_ModalScope<T>> {
@override
Widget build(BuildContext context) {
// Only top most route can participate in focus traversal.
focusScopeNode.skipTraversal = !widget.route.isCurrent;
return AnimatedBuilder(
animation: widget.route.restorationScopeId,
builder: (BuildContext context, Widget? child) {
......@@ -1048,24 +1050,22 @@ class _ModalScopeState<T> extends State<_ModalScope<T>> {
},
child: PrimaryScrollController(
controller: primaryScrollController,
child: FocusScope(
node: focusScopeNode, // immutable
// Only top most route can participate in focus traversal.
skipTraversal: !widget.route.isCurrent,
child: FocusScope.withExternalFocusNode(
focusScopeNode: focusScopeNode, // immutable
child: RepaintBoundary(
child: AnimatedBuilder(
animation: _listenable, // immutable
child: ListenableBuilder(
listenable: _listenable, // immutable
builder: (BuildContext context, Widget? child) {
return widget.route.buildTransitions(
context,
widget.route.animation!,
widget.route.secondaryAnimation!,
// This additional AnimatedBuilder is include because if the
// This additional ListenableBuilder is include because if the
// value of the userGestureInProgressNotifier changes, it's
// only necessary to rebuild the IgnorePointer widget and set
// the focus node's ability to focus.
AnimatedBuilder(
animation: widget.route.navigator?.userGestureInProgressNotifier ?? ValueNotifier<bool>(false),
ListenableBuilder(
listenable: widget.route.navigator?.userGestureInProgressNotifier ?? ValueNotifier<bool>(false),
builder: (BuildContext context, Widget? child) {
final bool ignoreEvents = _shouldIgnoreFocusRequest;
focusScopeNode.canRequestFocus = !ignoreEvents;
......
......@@ -1736,7 +1736,7 @@ void main() {
semantics.dispose();
}, variant: const TargetPlatformVariant(<TargetPlatform>{TargetPlatform.iOS}));
testWidgets('focus traverse correct when pop multiple page simultaneously', (WidgetTester tester) async {
testWidgets('focus traversal is correct when popping multiple pages simultaneously', (WidgetTester tester) async {
// Regression test: https://github.com/flutter/flutter/issues/48903
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
await tester.pumpWidget(MaterialApp(
......
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