showBottomSheet function

PersistentBottomSheetController showBottomSheet({
  1. required BuildContext context,
  2. required WidgetBuilder builder,
  3. Color? backgroundColor,
  4. double? elevation,
  5. ShapeBorder? shape,
  6. Clip? clipBehavior,
  7. BoxConstraints? constraints,
  8. bool? enableDrag,
  9. bool? showDragHandle,
  10. AnimationController? transitionAnimationController,
  11. AnimationStyle? sheetAnimationStyle,
})

Shows a Material Design bottom sheet in the nearest Scaffold ancestor. To show a persistent bottom sheet, use the Scaffold.bottomSheet.

Returns a controller that can be used to close and otherwise manipulate the bottom sheet.

The optional backgroundColor, elevation, shape, clipBehavior, constraints and transitionAnimationController parameters can be passed in to customize the appearance and behavior of 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.

The sheetAnimationStyle parameter is used to override the bottom sheet animation duration and reverse animation duration.

If AnimationStyle.duration is provided, it will be used to override the bottom sheet animation duration in the underlying BottomSheet.createAnimationController.

If AnimationStyle.reverseDuration is provided, it will be used to override the bottom sheet reverse animation duration in the underlying BottomSheet.createAnimationController.

To disable the bottom sheet animation, use AnimationStyle.noAnimation.

This sample showcases how to override the showBottomSheet animation duration and reverse animation duration using AnimationStyle.

To see it in action, copy and run this code snippet on DartPad.

import 'package:material_ui/material_ui.dart';

/// Flutter code sample for [showBottomSheet].

void main() => runApp(const BottomSheetExampleApp());

class BottomSheetExampleApp extends StatelessWidget {
  const BottomSheetExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('Bottom Sheet Sample')),
        body: const BottomSheetExample(),
      ),
    );
  }
}

enum AnimationStyles { defaultStyle, custom, none }

const List<(AnimationStyles, String)> animationStyleSegments =
    <(AnimationStyles, String)>[
      (AnimationStyles.defaultStyle, 'Default'),
      (AnimationStyles.custom, 'Custom'),
      (AnimationStyles.none, 'None'),
    ];

class BottomSheetExample extends StatefulWidget {
  const BottomSheetExample({super.key});

  @override
  State<BottomSheetExample> createState() => _BottomSheetExampleState();
}

class _BottomSheetExampleState extends State<BottomSheetExample> {
  Set<AnimationStyles> _animationStyleSelection = <AnimationStyles>{
    AnimationStyles.defaultStyle,
  };
  AnimationStyle? _animationStyle;

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: .center,
        children: <Widget>[
          SegmentedButton<AnimationStyles>(
            selected: _animationStyleSelection,
            onSelectionChanged: (Set<AnimationStyles> styles) {
              setState(() {
                _animationStyle = switch (styles.first) {
                  AnimationStyles.defaultStyle => null,
                  AnimationStyles.custom => const AnimationStyle(
                    duration: Duration(seconds: 3),
                    reverseDuration: Duration(seconds: 1),
                  ),
                  AnimationStyles.none => AnimationStyle.noAnimation,
                };
                _animationStyleSelection = styles;
              });
            },
            segments: animationStyleSegments
                .map<ButtonSegment<AnimationStyles>>((
                  (AnimationStyles, String) shirt,
                ) {
                  return ButtonSegment<AnimationStyles>(
                    value: shirt.$1,
                    label: Text(shirt.$2),
                  );
                })
                .toList(),
          ),
          const SizedBox(height: 10),
          ElevatedButton(
            child: const Text('showBottomSheet'),
            onPressed: () {
              showBottomSheet(
                context: context,
                sheetAnimationStyle: _animationStyle,
                builder: (BuildContext context) {
                  return SizedBox.expand(
                    child: Center(
                      child: Column(
                        mainAxisAlignment: .center,
                        mainAxisSize: .min,
                        children: <Widget>[
                          const Text('Bottom sheet'),
                          ElevatedButton(
                            child: const Text('Close'),
                            onPressed: () => Navigator.pop(context),
                          ),
                        ],
                      ),
                    ),
                  );
                },
              );
            },
          ),
        ],
      ),
    );
  }
}

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 app bar 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 app bar, use the Scaffold.bottomSheet constructor parameter.

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 of the app. Modal bottom sheets can be created and displayed with the showModalBottomSheet function.

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 can be safely removed from the tree before the bottom sheet is closed.

See also:

Implementation

// TODO(framework): Replace the following block with a @dartpad directive
// when it's supported. https://github.com/dart-lang/dartdoc/issues/4123
/// {@macro material_ui.dartpad_guide}
///
/// {@example /example/lib/bottom_sheet/show_bottom_sheet.0.dart#body}
///
/// </callout-box>
///
/// 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 app bar 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 app bar, use the
/// [Scaffold.bottomSheet] constructor parameter.
///
/// 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
/// of the app. Modal bottom sheets can be created and displayed with the
/// [showModalBottomSheet] function.
///
/// 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
/// can be safely removed from the tree before the bottom sheet is closed.
///
/// See also:
///
///  * [BottomSheet], which becomes the parent of the widget returned by the
///    `builder`.
///  * [showModalBottomSheet], which can be used to display a modal bottom
///    sheet.
///  * [Scaffold.of], for information about how to obtain the [BuildContext].
///  * The Material 2 spec at <https://m2.material.io/components/sheets-bottom>.
///  * The Material 3 spec at <https://m3.material.io/components/bottom-sheets/overview>.
///  * [AnimationStyle], which is used to override the bottom sheet animation
///    duration and reverse animation duration.
PersistentBottomSheetController showBottomSheet({
  required BuildContext context,
  required WidgetBuilder builder,
  Color? backgroundColor,
  double? elevation,
  ShapeBorder? shape,
  Clip? clipBehavior,
  BoxConstraints? constraints,
  bool? enableDrag,
  bool? showDragHandle,
  AnimationController? transitionAnimationController,
  AnimationStyle? sheetAnimationStyle,
}) {
  assert(debugCheckHasScaffold(context));

  return Scaffold.of(context).showBottomSheet(
    builder,
    backgroundColor: backgroundColor,
    elevation: elevation,
    shape: shape,
    clipBehavior: clipBehavior,
    constraints: constraints,
    enableDrag: enableDrag,
    showDragHandle: showDragHandle,
    transitionAnimationController: transitionAnimationController,
    sheetAnimationStyle: sheetAnimationStyle,
  );
}