showBottomSheet method

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

Shows a Material Design bottom sheet in the nearest Scaffold. 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.

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.

The transitionAnimationController controls the bottom sheet's entrance and exit animations. It's up to the owner of the controller to call AnimationController.dispose when the controller is no longer needed.

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 persistent bottom sheet shows information that supplements the primary content of the app. A persistent bottom sheet remains visible even when the user interacts with other parts of the app.

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.

This example demonstrates how to use showBottomSheet to display a bottom sheet when a user taps a button. It also demonstrates how to close a bottom sheet using the Navigator.

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

import 'package:material_ui/material_ui.dart';

/// Flutter code sample for [ScaffoldState.showBottomSheet].

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

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

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

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

  @override
  Widget build(BuildContext context) {
    return Center(
      child: ElevatedButton(
        child: const Text('showBottomSheet'),
        onPressed: () {
          Scaffold.of(context).showBottomSheet((BuildContext context) {
            return Container(
              height: 200,
              color: Colors.amber,
              child: Center(
                child: Column(
                  mainAxisAlignment: .center,
                  mainAxisSize: .min,
                  children: <Widget>[
                    const Text('BottomSheet'),
                    ElevatedButton(
                      child: const Text('Close BottomSheet'),
                      onPressed: () {
                        Navigator.pop(context);
                      },
                    ),
                  ],
                ),
              ),
            );
          });
        },
      ),
    );
  }
}

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 [ScaffoldState.showBottomSheet].

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

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

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

enum AnimationStyles { defaultStyle, custom, none }

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

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

  @override
  State<ShowBottomSheetExample> createState() => _ShowBottomSheetExampleState();
}

class _ShowBottomSheetExampleState extends State<ShowBottomSheetExample> {
  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: () {
              Scaffold.of(context).showBottomSheet(
                sheetAnimationStyle: _animationStyle,
                (BuildContext context) {
                  return SizedBox(
                    height: 200,
                    child: Center(
                      child: Column(
                        mainAxisAlignment: .center,
                        mainAxisSize: .min,
                        children: <Widget>[
                          const Text('BottomSheet'),
                          ElevatedButton(
                            child: const Text('Close'),
                            onPressed: () {
                              Navigator.pop(context);
                            },
                          ),
                        ],
                      ),
                    ),
                  );
                },
              );
            },
          ),
        ],
      ),
    );
  }
}

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/scaffold/scaffold_state.show_bottom_sheet.0.dart#body}
///
/// </callout-box>
///
/// 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].
///
/// <callout-box>
///
/// This sample showcases how to override the [showBottomSheet] animation
/// duration and reverse animation duration using [AnimationStyle].
///
// 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/scaffold/scaffold_state.show_bottom_sheet.1.dart#body}
///
/// </callout-box>
///
/// See also:
///
///  * [BottomSheet], which becomes the parent of the widget returned by the
///    `builder`.
///  * [showBottomSheet], which calls this method given a [BuildContext].
///  * [showModalBottomSheet], which can be used to display a modal bottom
///    sheet.
///  * [Scaffold.of], for information about how to obtain the [ScaffoldState].
///  * 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 modal bottom sheet
///    animation duration and reverse animation duration.
PersistentBottomSheetController showBottomSheet(
  WidgetBuilder builder, {
  Color? backgroundColor,
  double? elevation,
  ShapeBorder? shape,
  Clip? clipBehavior,
  BoxConstraints? constraints,
  bool? enableDrag,
  bool? showDragHandle,
  AnimationController? transitionAnimationController,
  AnimationStyle? sheetAnimationStyle,
}) {
  assert(() {
    if (widget.bottomSheet != null) {
      throw FlutterError(
        'Scaffold.bottomSheet cannot be specified while a bottom sheet '
        'displayed with showBottomSheet() is still visible.\n'
        'Rebuild the Scaffold with a null bottomSheet before calling showBottomSheet().',
      );
    }
    return true;
  }());
  assert(debugCheckHasMediaQuery(context));

  _closeCurrentBottomSheet();
  final AnimationController controller =
      (transitionAnimationController ??
            BottomSheet.createAnimationController(this, sheetAnimationStyle: sheetAnimationStyle))
        ..forward();
  setState(() {
    _currentBottomSheet = _buildBottomSheet(
      builder,
      isPersistent: false,
      animationController: controller,
      backgroundColor: backgroundColor,
      elevation: elevation,
      shape: shape,
      clipBehavior: clipBehavior,
      constraints: constraints,
      enableDrag: enableDrag,
      showDragHandle: showDragHandle,
      shouldDisposeAnimationController: transitionAnimationController == null,
    );
  });
  return _currentBottomSheet!;
}