add keyboardDismissBehavior into SingleChildScrollView (#76312)
This commit is contained in:
@@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user