Skip to content

Commit

Permalink
Fix incorrect behavior of ScrollViewKeyboardDismissBehavior.onDrag fo…
Browse files Browse the repository at this point in the history
…r ScrollViewers with Drawer (#148948)

Fixes flutter/flutter#141542
Fixes flutter/flutter#103544
Fixes flutter/flutter#54277
  • Loading branch information
dawidope authored May 31, 2024
1 parent de26ec8 commit 84cff31
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 9 deletions.
6 changes: 3 additions & 3 deletions packages/flutter/lib/src/widgets/scroll_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -498,9 +498,9 @@ abstract class ScrollView extends StatelessWidget {
return NotificationListener<ScrollUpdateNotification>(
child: scrollableResult,
onNotification: (ScrollUpdateNotification notification) {
final FocusScopeNode focusScope = FocusScope.of(context);
if (notification.dragDetails != null && focusScope.hasFocus) {
focusScope.unfocus();
final FocusScopeNode currentScope = FocusScope.of(context);
if (notification.dragDetails != null && !currentScope.hasPrimaryFocus && currentScope.hasFocus) {
FocusManager.instance.primaryFocus?.unfocus();
}
return false;
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,9 +270,9 @@ class SingleChildScrollView extends StatelessWidget {
scrollable = NotificationListener<ScrollUpdateNotification>(
child: scrollable,
onNotification: (ScrollUpdateNotification notification) {
final FocusScopeNode focusNode = FocusScope.of(context);
if (notification.dragDetails != null && focusNode.hasFocus) {
focusNode.unfocus();
final FocusScopeNode currentScope = FocusScope.of(context);
if (notification.dragDetails != null && !currentScope.hasPrimaryFocus && currentScope.hasFocus) {
FocusManager.instance.primaryFocus?.unfocus();
}
return false;
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,9 @@ abstract class TwoDimensionalScrollView extends StatelessWidget {
return NotificationListener<ScrollUpdateNotification>(
child: scrollableResult,
onNotification: (ScrollUpdateNotification notification) {
final FocusScopeNode focusScope = FocusScope.of(context);
if (notification.dragDetails != null && focusScope.hasFocus) {
focusScope.unfocus();
final FocusScopeNode currentScope = FocusScope.of(context);
if (notification.dragDetails != null && !currentScope.hasPrimaryFocus && currentScope.hasFocus) {
FocusManager.instance.primaryFocus?.unfocus();
}
return false;
},
Expand Down
41 changes: 41 additions & 0 deletions packages/flutter/test/widgets/scroll_view_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1757,4 +1757,45 @@ void main() {
expect(item1Height, 30.0);
expect(item2Height, 30.0);
});

testWidgets('ListView dismiss keyboard onDrag and keep dismissed on drawer opened test', (WidgetTester tester) async {
final List<int> list = List<int>.generate(50, (int i) => i);
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();

await tester.pumpWidget(textFieldBoilerplate(
child: Scaffold(
key: scaffoldKey,
drawer: Container(),
body: Column(
children: <Widget>[
const TextField(),
Expanded(
child: ListView(
keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
children: list.map((int i) {
return Container(
height: 50,
);
}).toList(),
),
),
]
),
),
));

expect(tester.testTextInput.isVisible, isFalse);
final Finder finder = find.byType(TextField).first;
await tester.tap(finder);
expect(tester.testTextInput.isVisible, isTrue);

await tester.drag(find.byType(ListView).first, const Offset(0.0, -40.0));
await tester.pumpAndSettle();

expect(tester.testTextInput.isVisible, isFalse);
scaffoldKey.currentState!.openDrawer();
await tester.pumpAndSettle();

expect(tester.testTextInput.isVisible, isFalse);
});
}
40 changes: 40 additions & 0 deletions packages/flutter/test/widgets/single_child_scroll_view_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1078,4 +1078,44 @@ void main() {
await tester.pumpAndSettle();
expect(textField.focusNode!.hasFocus, isTrue);
});

testWidgets('keyboardDismissBehavior.OnDrag with drawer tests', (WidgetTester tester) async {
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();

await tester.pumpWidget(
MaterialApp(
home: Scaffold(
key: scaffoldKey,
drawer: Container(),
body: Column(
children: <Widget>[
const TextField(),
Expanded(
child: SingleChildScrollView(
keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
child: Container(
height: 1000,
)
),
),
]
),
),
),
);

expect(tester.testTextInput.isVisible, isFalse);
final Finder finder = find.byType(TextField).first;
await tester.tap(finder);
expect(tester.testTextInput.isVisible, isTrue);

await tester.drag(find.byType(SingleChildScrollView).first, const Offset(0.0, -40.0));
await tester.pumpAndSettle();

expect(tester.testTextInput.isVisible, isFalse);
scaffoldKey.currentState!.openDrawer();
await tester.pumpAndSettle();

expect(tester.testTextInput.isVisible, isFalse);
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -919,5 +919,51 @@ void main() {
expect(horizontalController.position.pixels, 0.0);
});
});

testWidgets('Dismiss keyboard onDrag and keep dismissed on drawer opened', (WidgetTester tester) async {
late final TwoDimensionalChildBuilderDelegate delegate;
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
addTearDown(() => delegate.dispose());

await tester.pumpWidget(
MaterialApp(
home: Scaffold(
key: scaffoldKey,
drawer: Container(),
body: Column(
children: <Widget>[
const TextField(),
Expanded(
child: SimpleBuilderTableView(
keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
delegate: delegate = TwoDimensionalChildBuilderDelegate(
builder: _testChildBuilder,
maxXIndex: 99,
maxYIndex: 99,
),
),
),
]
),
),
),
);

await tester.pumpAndSettle();

expect(tester.testTextInput.isVisible, isFalse);
final Finder finder = find.byType(TextField).first;
await tester.tap(finder);
expect(tester.testTextInput.isVisible, isTrue);

await tester.drag(find.byType(SimpleBuilderTableView).first, const Offset(-40.0, -40.0));
await tester.pumpAndSettle();

expect(tester.testTextInput.isVisible, isFalse);
scaffoldKey.currentState!.openDrawer();
await tester.pumpAndSettle();

expect(tester.testTextInput.isVisible, isFalse);
});
});
}

0 comments on commit 84cff31

Please sign in to comment.