Unverified Commit 524bc4a5 authored by Pedro Massango's avatar Pedro Massango Committed by GitHub

add keyboardDismissBehavior into SingleChildScrollView (#76312)

parent 328a262e
...@@ -4,14 +4,19 @@ ...@@ -4,14 +4,19 @@
import 'dart:math' as math; import 'dart:math' as math;
import 'package:flutter/rendering.dart';
import 'package:flutter/gestures.dart' show DragStartBehavior; import 'package:flutter/gestures.dart' show DragStartBehavior;
import 'package:flutter/rendering.dart';
import 'basic.dart'; import 'basic.dart';
import 'focus_manager.dart';
import 'focus_scope.dart';
import 'framework.dart'; import 'framework.dart';
import 'notification_listener.dart';
import 'primary_scroll_controller.dart'; import 'primary_scroll_controller.dart';
import 'scroll_controller.dart'; import 'scroll_controller.dart';
import 'scroll_notification.dart';
import 'scroll_physics.dart'; import 'scroll_physics.dart';
import 'scroll_view.dart';
import 'scrollable.dart'; import 'scrollable.dart';
/// A box in which a single widget can be scrolled. /// A box in which a single widget can be scrolled.
...@@ -221,6 +226,7 @@ class SingleChildScrollView extends StatelessWidget { ...@@ -221,6 +226,7 @@ class SingleChildScrollView extends StatelessWidget {
this.dragStartBehavior = DragStartBehavior.start, this.dragStartBehavior = DragStartBehavior.start,
this.clipBehavior = Clip.hardEdge, this.clipBehavior = Clip.hardEdge,
this.restorationId, this.restorationId,
this.keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual
}) : assert(scrollDirection != null), }) : assert(scrollDirection != null),
assert(dragStartBehavior != null), assert(dragStartBehavior != null),
assert(clipBehavior != null), assert(clipBehavior != null),
...@@ -306,6 +312,9 @@ class SingleChildScrollView extends StatelessWidget { ...@@ -306,6 +312,9 @@ class SingleChildScrollView extends StatelessWidget {
/// {@macro flutter.widgets.scrollable.restorationId} /// {@macro flutter.widgets.scrollable.restorationId}
final String? restorationId; final String? restorationId;
/// {@macro flutter.widgets.scroll_view.keyboardDismissBehavior}
final ScrollViewKeyboardDismissBehavior keyboardDismissBehavior;
AxisDirection _getDirection(BuildContext context) { AxisDirection _getDirection(BuildContext context) {
return getAxisDirectionFromAxisReverseAndDirectionality(context, scrollDirection, reverse); return getAxisDirectionFromAxisReverseAndDirectionality(context, scrollDirection, reverse);
} }
...@@ -319,7 +328,7 @@ class SingleChildScrollView extends StatelessWidget { ...@@ -319,7 +328,7 @@ class SingleChildScrollView extends StatelessWidget {
final ScrollController? scrollController = primary final ScrollController? scrollController = primary
? PrimaryScrollController.of(context) ? PrimaryScrollController.of(context)
: controller; : controller;
final Scrollable scrollable = Scrollable( Widget scrollable = Scrollable(
dragStartBehavior: dragStartBehavior, dragStartBehavior: dragStartBehavior,
axisDirection: axisDirection, axisDirection: axisDirection,
controller: scrollController, controller: scrollController,
...@@ -334,6 +343,20 @@ class SingleChildScrollView extends StatelessWidget { ...@@ -334,6 +343,20 @@ class SingleChildScrollView extends StatelessWidget {
); );
}, },
); );
if (keyboardDismissBehavior == ScrollViewKeyboardDismissBehavior.onDrag) {
scrollable = NotificationListener<ScrollUpdateNotification>(
child: scrollable,
onNotification: (ScrollUpdateNotification notification) {
final FocusScopeNode focusNode = FocusScope.of(context);
if (notification.dragDetails != null && focusNode.hasFocus) {
focusNode.unfocus();
}
return false;
},
);
}
return primary && scrollController != null return primary && scrollController != null
? PrimaryScrollController.none(child: scrollable) ? PrimaryScrollController.none(child: scrollable)
: scrollable; : scrollable;
......
...@@ -4,10 +4,9 @@ ...@@ -4,10 +4,9 @@
import 'dart:ui'; import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import '../rendering/rendering_tester.dart'; import '../rendering/rendering_tester.dart';
import 'semantics_tester.dart'; import 'semantics_tester.dart';
...@@ -922,4 +921,53 @@ void main() { ...@@ -922,4 +921,53 @@ void main() {
expect(inner.offset, 0.0); expect(inner.offset, 0.0);
}); });
}); });
testWidgets('keyboardDismissBehavior tests', (WidgetTester tester) async {
final List<FocusNode> focusNodes = List<FocusNode>.generate(50, (int i) => FocusNode());
Future<void> boilerplate(ScrollViewKeyboardDismissBehavior behavior) {
return tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: SingleChildScrollView(
padding: EdgeInsets.zero,
keyboardDismissBehavior: behavior,
child: Column(
children: focusNodes.map((FocusNode focusNode) {
return Container(
height: 50,
child: TextField(focusNode: focusNode),
);
}).toList(),
),
),
),
),
);
}
// ScrollViewKeyboardDismissBehavior.onDrag dismiss keyboard on drag
await boilerplate(ScrollViewKeyboardDismissBehavior.onDrag);
Finder finder = find.byType(TextField).first;
TextField textField = tester.widget(finder);
await tester.showKeyboard(finder);
expect(textField.focusNode!.hasFocus, isTrue);
await tester.drag(finder, const Offset(0.0, -40.0));
await tester.pumpAndSettle();
expect(textField.focusNode!.hasFocus, isFalse);
// ScrollViewKeyboardDismissBehavior.manual does no dismiss the keyboard
await boilerplate(ScrollViewKeyboardDismissBehavior.manual);
finder = find.byType(TextField).first;
textField = tester.widget(finder);
await tester.showKeyboard(finder);
expect(textField.focusNode!.hasFocus, isTrue);
await tester.drag(finder, const Offset(0.0, -40.0));
await tester.pumpAndSettle();
expect(textField.focusNode!.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