Unverified Commit 0f0cc449 authored by Hans Muller's avatar Hans Muller Committed by GitHub

Scaffold bottomSheet parameter: persistent, not a route (#18379)

parent aecb7d96
...@@ -24,7 +24,8 @@ const double _kCloseProgressThreshold = 0.5; ...@@ -24,7 +24,8 @@ const double _kCloseProgressThreshold = 0.5;
/// supplements the primary content of the app. A persistent bottom sheet /// supplements the primary content of the app. A persistent bottom sheet
/// remains visible even when the user interacts with other parts of the app. /// remains visible even when the user interacts with other parts of the app.
/// Persistent bottom sheets can be created and displayed with the /// Persistent bottom sheets can be created and displayed with the
/// [ScaffoldState.showBottomSheet] function. /// [ScaffoldState.showBottomSheet] function or by specifying the
/// [Scaffold.bottomSheet] constructor parameter.
/// ///
/// * _Modal_. A modal bottom sheet is an alternative to a menu or a dialog and /// * _Modal_. A modal bottom sheet is an alternative to a menu or a dialog and
/// prevents the user from interacting with the rest of the app. Modal bottom /// prevents the user from interacting with the rest of the app. Modal bottom
...@@ -32,8 +33,8 @@ const double _kCloseProgressThreshold = 0.5; ...@@ -32,8 +33,8 @@ const double _kCloseProgressThreshold = 0.5;
/// function. /// function.
/// ///
/// The [BottomSheet] widget itself is rarely used directly. Instead, prefer to /// The [BottomSheet] widget itself is rarely used directly. Instead, prefer to
/// create a persistent bottom sheet with [ScaffoldState.showBottomSheet] and a modal /// create a persistent bottom sheet with [ScaffoldState.showBottomSheet] or
/// bottom sheet with [showModalBottomSheet]. /// [Scaffold.bottomSheet], and a modal bottom sheet with [showModalBottomSheet].
/// ///
/// See also: /// See also:
/// ///
...@@ -49,9 +50,11 @@ class BottomSheet extends StatefulWidget { ...@@ -49,9 +50,11 @@ class BottomSheet extends StatefulWidget {
const BottomSheet({ const BottomSheet({
Key key, Key key,
this.animationController, this.animationController,
this.enableDrag = true,
@required this.onClosing, @required this.onClosing,
@required this.builder @required this.builder
}) : assert(onClosing != null), }) : assert(enableDrag != null),
assert(onClosing != null),
assert(builder != null), assert(builder != null),
super(key: key); super(key: key);
...@@ -74,6 +77,12 @@ class BottomSheet extends StatefulWidget { ...@@ -74,6 +77,12 @@ class BottomSheet extends StatefulWidget {
/// [Material] widget. /// [Material] widget.
final WidgetBuilder builder; final WidgetBuilder builder;
/// If true, the bottom sheet can dragged up and down and dismissed by swiping
/// downards.
///
/// Default is true.
final bool enableDrag;
@override @override
_BottomSheetState createState() => new _BottomSheetState(); _BottomSheetState createState() => new _BottomSheetState();
...@@ -124,13 +133,14 @@ class _BottomSheetState extends State<BottomSheet> { ...@@ -124,13 +133,14 @@ class _BottomSheetState extends State<BottomSheet> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return new GestureDetector( final Widget bottomSheet = new Material(
key: _childKey,
child: widget.builder(context),
);
return !widget.enableDrag ? bottomSheet : new GestureDetector(
onVerticalDragUpdate: _handleDragUpdate, onVerticalDragUpdate: _handleDragUpdate,
onVerticalDragEnd: _handleDragEnd, onVerticalDragEnd: _handleDragEnd,
child: new Material( child: bottomSheet,
key: _childKey,
child: widget.builder(context)
)
); );
} }
} }
...@@ -289,24 +299,30 @@ Future<T> showModalBottomSheet<T>({ ...@@ -289,24 +299,30 @@ Future<T> showModalBottomSheet<T>({
/// Shows a persistent material design bottom sheet in the nearest [Scaffold]. /// Shows a persistent material design bottom sheet in the nearest [Scaffold].
/// ///
/// Returns a controller that can be used to close and otherwise manipulate the
/// bottom sheet.
///
/// To rebuild the bottom sheet (e.g. if it is stateful), call
/// [PersistentBottomSheetController.setState] on the controller returned by
/// this method.
///
/// The new bottom sheet becomes a [LocalHistoryEntry] for the enclosing
/// [ModalRoute] and a back button is added to the appbar of the [Scaffold]
/// that closes the bottom sheet.
///
/// To create a persistent bottom sheet that is not a [LocalHistoryEntry] and
/// does not add a back button to the enclosing Scaffold's appbar, use the
/// [Scaffold.bottomSheet] constructor parameter.
///
/// A persistent bottom sheet shows information that supplements the primary /// A persistent bottom sheet shows information that supplements the primary
/// content of the app. A persistent bottom sheet remains visible even when the /// content of the app. A persistent bottom sheet remains visible even when
/// user interacts with other parts of the app. A [Scaffold] is required in the /// the user interacts with other parts of the app.
/// given `context`; its [ScaffoldState.showBottomSheet] method is used to
/// actually show the bottom sheet.
/// ///
/// A closely related widget is a modal bottom sheet, which is an alternative /// A closely related widget is a modal bottom sheet, which is an alternative
/// to a menu or a dialog and prevents the user from interacting with the rest /// to a menu or a dialog and prevents the user from interacting with the rest
/// of the app. Modal bottom sheets can be created and displayed with the /// of the app. Modal bottom sheets can be created and displayed with the
/// [showModalBottomSheet] function. /// [showModalBottomSheet] function.
/// ///
/// Returns a controller that can be used to close and otherwise manipulate the
/// bottom sheet.
///
/// To rebuild the bottom sheet (e.g. if it is stateful), call
/// [PersistentBottomSheetController.setState] on the value returned from this
/// method.
///
/// The `context` argument is used to look up the [Scaffold] for the bottom /// The `context` argument is used to look up the [Scaffold] for the bottom
/// sheet. It is only used when the method is called. Its corresponding widget /// sheet. It is only used when the method is called. Its corresponding widget
/// can be safely removed from the tree before the bottom sheet is closed. /// can be safely removed from the tree before the bottom sheet is closed.
......
...@@ -133,4 +133,62 @@ void main() { ...@@ -133,4 +133,62 @@ void main() {
), ),
); );
}); });
testWidgets('Scaffold.bottomSheet', (WidgetTester tester) async {
final Key bottomSheetKey = new UniqueKey();
await tester.pumpWidget(
new MaterialApp(
home: new Scaffold(
body: const Placeholder(),
bottomSheet: new Container(
key: bottomSheetKey,
alignment: Alignment.center,
height: 200.0,
child: new Builder(
builder: (BuildContext context) {
return new RaisedButton(
child: const Text('showModalBottomSheet'),
onPressed: () {
showModalBottomSheet<void>(
context: context,
builder: (BuildContext context) => const Text('modal bottom sheet'),
);
},
);
},
),
),
),
),
);
expect(find.text('showModalBottomSheet'), findsOneWidget);
expect(tester.getSize(find.byKey(bottomSheetKey)), const Size(800.0, 200.0));
expect(tester.getTopLeft(find.byKey(bottomSheetKey)), const Offset(0.0, 400.0));
// Show the modal bottomSheet
await tester.tap(find.text('showModalBottomSheet'));
await tester.pumpAndSettle();
expect(find.text('modal bottom sheet'), findsOneWidget);
// Dismiss the modal bottomSheet
await tester.tap(find.text('modal bottom sheet'));
await tester.pumpAndSettle();
expect(find.text('modal bottom sheet'), findsNothing);
expect(find.text('showModalBottomSheet'), findsOneWidget);
// Remove the persistent bottomSheet
await tester.pumpWidget(
new MaterialApp(
home: const Scaffold(
bottomSheet: null,
body: const Placeholder(),
),
),
);
await tester.pumpAndSettle();
expect(find.text('showModalBottomSheet'), findsNothing);
expect(find.byKey(bottomSheetKey), findsNothing);
});
} }
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