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>({ ...@@ -722,6 +722,9 @@ Future<T?> showModalBottomSheet<T>({
/// persistent bottom sheets (see the documentation for these on [BottomSheet] /// persistent bottom sheets (see the documentation for these on [BottomSheet]
/// for more details). /// 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 /// To rebuild the bottom sheet (e.g. if it is stateful), call
/// [PersistentBottomSheetController.setState] on the controller returned by /// [PersistentBottomSheetController.setState] on the controller returned by
/// this method. /// this method.
...@@ -759,6 +762,7 @@ PersistentBottomSheetController<T> showBottomSheet<T>({ ...@@ -759,6 +762,7 @@ PersistentBottomSheetController<T> showBottomSheet<T>({
ShapeBorder? shape, ShapeBorder? shape,
Clip? clipBehavior, Clip? clipBehavior,
BoxConstraints? constraints, BoxConstraints? constraints,
bool? enableDrag,
AnimationController? transitionAnimationController, AnimationController? transitionAnimationController,
}) { }) {
assert(context != null); assert(context != null);
...@@ -772,6 +776,7 @@ PersistentBottomSheetController<T> showBottomSheet<T>({ ...@@ -772,6 +776,7 @@ PersistentBottomSheetController<T> showBottomSheet<T>({
shape: shape, shape: shape,
clipBehavior: clipBehavior, clipBehavior: clipBehavior,
constraints: constraints, constraints: constraints,
enableDrag: enableDrag,
transitionAnimationController: transitionAnimationController, transitionAnimationController: transitionAnimationController,
); );
} }
...@@ -2318,6 +2318,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin, Resto ...@@ -2318,6 +2318,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin, Resto
ShapeBorder? shape, ShapeBorder? shape,
Clip? clipBehavior, Clip? clipBehavior,
BoxConstraints? constraints, BoxConstraints? constraints,
bool? enableDrag,
bool shouldDisposeAnimationController = true, bool shouldDisposeAnimationController = true,
}) { }) {
assert(() { assert(() {
...@@ -2367,7 +2368,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin, Resto ...@@ -2367,7 +2368,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin, Resto
bottomSheet = _StandardBottomSheet( bottomSheet = _StandardBottomSheet(
key: bottomSheetKey, key: bottomSheetKey,
animationController: animationController, animationController: animationController,
enableDrag: !isPersistent, enableDrag: enableDrag ?? !isPersistent,
onClosing: () { onClosing: () {
if (_currentBottomSheet == null) { if (_currentBottomSheet == null) {
return; return;
...@@ -2468,6 +2469,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin, Resto ...@@ -2468,6 +2469,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin, Resto
ShapeBorder? shape, ShapeBorder? shape,
Clip? clipBehavior, Clip? clipBehavior,
BoxConstraints? constraints, BoxConstraints? constraints,
bool? enableDrag,
AnimationController? transitionAnimationController, AnimationController? transitionAnimationController,
}) { }) {
assert(() { assert(() {
...@@ -2494,6 +2496,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin, Resto ...@@ -2494,6 +2496,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin, Resto
shape: shape, shape: shape,
clipBehavior: clipBehavior, clipBehavior: clipBehavior,
constraints: constraints, constraints: constraints,
enableDrag: enableDrag,
shouldDisposeAnimationController: transitionAnimationController == null, shouldDisposeAnimationController: transitionAnimationController == null,
); );
}); });
......
...@@ -88,6 +88,150 @@ void main() { ...@@ -88,6 +88,150 @@ void main() {
await tester.pumpWidget(Container()); 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 { testWidgets('Tapping on a modal BottomSheet should not dismiss it', (WidgetTester tester) async {
late BuildContext savedContext; 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