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 @@
import 'dart:math' as math;
import 'package:flutter/rendering.dart';
import 'package:flutter/gestures.dart' show DragStartBehavior;
import 'package:flutter/rendering.dart';
import 'basic.dart';
import 'focus_manager.dart';
import 'focus_scope.dart';
import 'framework.dart';
import 'notification_listener.dart';
import 'primary_scroll_controller.dart';
import 'scroll_controller.dart';
import 'scroll_notification.dart';
import 'scroll_physics.dart';
import 'scroll_view.dart';
import 'scrollable.dart';
/// A box in which a single widget can be scrolled.
......@@ -221,6 +226,7 @@ class SingleChildScrollView extends StatelessWidget {
this.dragStartBehavior = DragStartBehavior.start,
this.clipBehavior = Clip.hardEdge,
this.restorationId,
this.keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual
}) : assert(scrollDirection != null),
assert(dragStartBehavior != null),
assert(clipBehavior != null),
......@@ -306,6 +312,9 @@ class SingleChildScrollView extends StatelessWidget {
/// {@macro flutter.widgets.scrollable.restorationId}
final String? restorationId;
/// {@macro flutter.widgets.scroll_view.keyboardDismissBehavior}
final ScrollViewKeyboardDismissBehavior keyboardDismissBehavior;
AxisDirection _getDirection(BuildContext context) {
return getAxisDirectionFromAxisReverseAndDirectionality(context, scrollDirection, reverse);
}
......@@ -319,7 +328,7 @@ class SingleChildScrollView extends StatelessWidget {
final ScrollController? scrollController = primary
? PrimaryScrollController.of(context)
: controller;
final Scrollable scrollable = Scrollable(
Widget scrollable = Scrollable(
dragStartBehavior: dragStartBehavior,
axisDirection: axisDirection,
controller: scrollController,
......@@ -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
? PrimaryScrollController.none(child: scrollable)
: scrollable;
......
......@@ -4,10 +4,9 @@
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import '../rendering/rendering_tester.dart';
import 'semantics_tester.dart';
......@@ -922,4 +921,53 @@ void main() {
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