Unverified Commit 87332183 authored by sanlittt's avatar sanlittt Committed by GitHub

Expose enableDrag property for showBottomSheet (#90932)

parent 3f688f6e
......@@ -722,6 +722,9 @@ Future<T?> showModalBottomSheet<T>({
/// persistent bottom sheets (see the documentation for these on [BottomSheet]
/// for more details).
///
/// The [enableDrag] parameter specifies whether the bottom sheet can be
/// dragged up and down and dismissed by swiping downwards.
///
/// To rebuild the bottom sheet (e.g. if it is stateful), call
/// [PersistentBottomSheetController.setState] on the controller returned by
/// this method.
......@@ -759,6 +762,7 @@ PersistentBottomSheetController<T> showBottomSheet<T>({
ShapeBorder? shape,
Clip? clipBehavior,
BoxConstraints? constraints,
bool? enableDrag,
AnimationController? transitionAnimationController,
}) {
assert(context != null);
......@@ -772,6 +776,7 @@ PersistentBottomSheetController<T> showBottomSheet<T>({
shape: shape,
clipBehavior: clipBehavior,
constraints: constraints,
enableDrag: enableDrag,
transitionAnimationController: transitionAnimationController,
);
}
......@@ -2318,6 +2318,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin, Resto
ShapeBorder? shape,
Clip? clipBehavior,
BoxConstraints? constraints,
bool? enableDrag,
bool shouldDisposeAnimationController = true,
}) {
assert(() {
......@@ -2367,7 +2368,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin, Resto
bottomSheet = _StandardBottomSheet(
key: bottomSheetKey,
animationController: animationController,
enableDrag: !isPersistent,
enableDrag: enableDrag ?? !isPersistent,
onClosing: () {
if (_currentBottomSheet == null) {
return;
......@@ -2468,6 +2469,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin, Resto
ShapeBorder? shape,
Clip? clipBehavior,
BoxConstraints? constraints,
bool? enableDrag,
AnimationController? transitionAnimationController,
}) {
assert(() {
......@@ -2494,6 +2496,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin, Resto
shape: shape,
clipBehavior: clipBehavior,
constraints: constraints,
enableDrag: enableDrag,
shouldDisposeAnimationController: transitionAnimationController == null,
);
});
......
......@@ -88,6 +88,150 @@ void main() {
await tester.pumpWidget(Container());
});
testWidgets('Swiping down a BottomSheet should dismiss it by default', (WidgetTester tester) async {
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
bool showBottomSheetThenCalled = false;
await tester.pumpWidget(MaterialApp(
home: Scaffold(
key: scaffoldKey,
body: const Center(child: Text('body')),
),
));
await tester.pump();
expect(showBottomSheetThenCalled, isFalse);
expect(find.text('BottomSheet'), findsNothing);
scaffoldKey.currentState!.showBottomSheet<void>((BuildContext context) {
return const SizedBox(
height: 200.0,
child: Text('BottomSheet'),
);
}).closed.whenComplete(() {
showBottomSheetThenCalled = true;
});
await tester.pumpAndSettle();
expect(showBottomSheetThenCalled, isFalse);
expect(find.text('BottomSheet'), findsOneWidget);
// Swipe the bottom sheet to dismiss it.
await tester.drag(find.text('BottomSheet'), const Offset(0.0, 150.0));
await tester.pumpAndSettle(); // Bottom sheet dismiss animation.
expect(showBottomSheetThenCalled, isTrue);
expect(find.text('BottomSheet'), findsNothing);
});
testWidgets('Swiping down a BottomSheet should not dismiss it when enableDrag is false', (WidgetTester tester) async {
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
bool showBottomSheetThenCalled = false;
await tester.pumpWidget(MaterialApp(
home: Scaffold(
key: scaffoldKey,
body: const Center(child: Text('body')),
),
));
await tester.pump();
expect(showBottomSheetThenCalled, isFalse);
expect(find.text('BottomSheet'), findsNothing);
scaffoldKey.currentState!.showBottomSheet<void>((BuildContext context) {
return const SizedBox(
height: 200.0,
child: Text('BottomSheet'),
);
},
enableDrag: false
).closed.whenComplete(() {
showBottomSheetThenCalled = true;
});
await tester.pumpAndSettle();
expect(showBottomSheetThenCalled, isFalse);
expect(find.text('BottomSheet'), findsOneWidget);
// Swipe the bottom sheet, attempting to dismiss it.
await tester.drag(find.text('BottomSheet'), const Offset(0.0, 150.0));
await tester.pumpAndSettle(); // Bottom sheet should not dismiss.
expect(showBottomSheetThenCalled, isFalse);
expect(find.text('BottomSheet'), findsOneWidget);
});
testWidgets('Swiping down a BottomSheet should dismiss it when enableDrag is true', (WidgetTester tester) async {
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
bool showBottomSheetThenCalled = false;
await tester.pumpWidget(MaterialApp(
home: Scaffold(
key: scaffoldKey,
body: const Center(child: Text('body')),
),
));
await tester.pump();
expect(showBottomSheetThenCalled, isFalse);
expect(find.text('BottomSheet'), findsNothing);
scaffoldKey.currentState!.showBottomSheet<void>((BuildContext context) {
return const SizedBox(
height: 200.0,
child: Text('BottomSheet'),
);
},
enableDrag: true
).closed.whenComplete(() {
showBottomSheetThenCalled = true;
});
await tester.pumpAndSettle();
expect(showBottomSheetThenCalled, isFalse);
expect(find.text('BottomSheet'), findsOneWidget);
// Swipe the bottom sheet to dismiss it.
await tester.drag(find.text('BottomSheet'), const Offset(0.0, 150.0));
await tester.pumpAndSettle(); // Bottom sheet dismiss animation.
expect(showBottomSheetThenCalled, isTrue);
expect(find.text('BottomSheet'), findsNothing);
});
testWidgets('Modal BottomSheet builder should only be called once', (WidgetTester tester) async {
late BuildContext savedContext;
await tester.pumpWidget(MaterialApp(
home: Builder(
builder: (BuildContext context) {
savedContext = context;
return Container();
},
),
));
int numBuilderCalls = 0;
showModalBottomSheet<void>(
context: savedContext,
isDismissible: false,
enableDrag: true,
builder: (BuildContext context) {
numBuilderCalls++;
return const Text('BottomSheet');
},
);
await tester.pumpAndSettle();
expect(numBuilderCalls, 1);
// Swipe the bottom sheet to dismiss it.
await tester.drag(find.text('BottomSheet'), const Offset(0.0, 150.0));
await tester.pumpAndSettle(); // Bottom sheet dismiss animation.
expect(numBuilderCalls, 1);
});
testWidgets('Tapping on a modal BottomSheet should not dismiss it', (WidgetTester tester) async {
late BuildContext savedContext;
......
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