Flutter | Create advanced modal bottom sheets. Material, Cupertino or your own style

Last update: Jun 27, 2022

Flutter Modal Bottom Sheet

BREAKING CHANGE IN 1.0.0

In the builder param remove scrollController and use ModalScrollController.of(context) instead to access the modal's scrollController. Check the CHANGELOG for more information

Awesome Flutter Pub

Create awesome and powerful modal bottom sheets.

Cupertino Modal Multiple Modals Material Modal Bar Modal Create your own

Try it

Explore the Web Demo or clone the repository.

Why not showModalBottomSheet?

Inspired by showModalBottomSheet, it completes with some must-need features:

  • Support for inside scrollview + dragging down to close (showModalBottomSheet won't work correctly with scrollviews.
  • Support for WillPopScope to prevent closing the dialog.
  • Support for scroll to top when tapping status bar (iOS only)
  • Cupertino modal bottom sheet
  • Create custom modal bottom sheet

First Steps

How to install it? Follow Instructions

Material Modal BottomSheet

showMaterialModalBottomSheet(
  context: context,
  builder: (context) => Container(),
)

Generic params for all modal bottom sheets

Param Description
bool expand = false The expand parameter specifies id the modal bottom sheet will be full screen size or will fit the content child
bool useRootNavigator = false The useRootNavigator parameter ensures that the root navigator is used to display the bottom sheet when set to true. This is useful in the case that a modal bottom sheet needs to be displayed above all other content but the caller is inside another Navigator.
bool isDismissible = true The isDismissible parameter specifies whether the bottom sheet will be dismissed when user taps on the scrim.
Color barrierColor The barrierColor parameter controls the color of the scrim for this route
bool enableDrag = true The enableDrag parameter specifies whether the bottom sheet can be dragged up and down and dismissed by swiping downwards.
AnimationController secondAnimation The secondAnimation parameter allows you to provide an animation controller that will be used to animate push/pop of the modal route. Using this param is advised against and will be probably removed in future versions
bool bounce = false The bounce parameter specifies if the bottom sheet can go beyond the top boundary while dragging
Duration duration = const Duration(milliseconds: 400) The duration of modal opening
double closeProgressThreshold = 0.6 The closeProgressThreshold specifies when the bottom sheet will be dismissed when user drags it.

Material params

The optional backgroundColor, elevation, shape, and clipBehavior parameters can be passed in to customize the appearance and behavior of material bottom sheets.

Using it with a scroll view inside

Assign the ModalScrollController.of(context) to your primary modal to sync the scroll with the modal's drag

showMaterialModalBottomSheet(
  context: context,
  builder: (context) => SingleChildScrollView(
    controller: ModalScrollController.of(context),
    child: Container(),
  ),
);

Cupertino Modal BottomSheet

iOS 13 came with an amazing new modal navigation and now it is available to use with Flutter.

showCupertinoModalBottomSheet(
  context: context,
  builder: (context) => Container(),
)

See generic paramameter in the Material section above

Cupertino specific params

The optional backgroundColor parameters can be passed in to customize the backgroundColor cupertino bottom sheets. Useful if you want a blurred transparent background as the example Cupertino Photo Share

CAUTION!: To animate the previous route some changes are needed.

Why? MaterialPageRoute and CupertinoPageRoute do not allow animated translation to/from routes that are not the same type.

Replace your current route class with MaterialWithModalsPageRoute.

Notice this route type behaves the same as MaterialPageRoute and supports custom PageTransitionsBuilder and PageTransitionsTheme.

How can I replace my current route?
1.

Using Navigator.of(context).push

Navigator.of(context).push(MaterialPageRoute(builder: (context) => Container()));`

Replace it with

Navigator.of(context).push(MaterialWithModalsPageRoute(builder: (context) => Container()));
2.

Using onGenerateRoute parameter of MaterialApp, CupertinoApp or Navigator

onGenerateRoute: (settings) {
   ...
    return MaterialPageRoute(settings: settings, builder: (context) => Container());
},

Replace it to

onGenerateRoute: (settings) {
  ...
   return MaterialWithModalsPageRoute(settings: settings, builder: (context) => Container());
},
3.

Using pageRouteBuilder parameter of WidgetApp

pageRouteBuilder: <T>(RouteSettings settings, WidgetBuilder builder) => MaterialWithModalsPageRoute<T>(settings: settings, builder: builder)
4.

Using routes parameter from MaterialApp or CupertinoApp

Unfortunately this parameter uses MaterialPageRoute and CupertinoPageRoute respectively and cannot be changed. You can modify the way you call the previous route with one of the previous methods or try option 2

Is there an alternative in case I can't change my current route? Yes!

Learn how to animate previous route with CupertinoScaffold:
  1. Wrap previous route inside a CupertinoScaffold. Example with routes parameter from MaterialApp or CupertinoApp
  routes: <String, WidgetBuilder>{
    '/previous_route_where_you_push_modal': (BuildContext context) => CupertinoScaffold(body: Container()),
   },
  1. Push modal with this method
CupertinoScaffold.showCupertinoModalBottomSheet(context:context, builder: (context) => Container())

Don't use this solution at the same time as MaterialWithModalsPageRoute

It supports native features as bouncing, blurred background, dark mode, stacking modals and inside navigation.

Push new views inside the modal bottom sheet

a. If you want to push a new modal bottom sheet just call showCupertinoModalBottomSheet again (works with both options)

b. For inside navigaton add a new Navigator or CupertinoTabScaffold inside

c. Also it supports flutter features as WillPopScope to prevent the modal bottom to be closed.

Build other BottomSheets

Try showBarModalBottomSheet for a bottomSheet with the appearance used by Facebook or Slack

Check in the example project showAvatarModalBottomSheet for how to create your own ModalBottomSheet

Questions

Ask a question and ping me @jamesblasco

Found an issue or have a proposal?

Create an issue

Roadmap

  • Support closing by dragging fast on a modal with a scroll view.

  • Improve animation curves when user is not dragging.

  • Allow to set the initial size of the bottom sheet

  • Support hero animations Pull Request #2

GitHub

https://github.com/jamesblasco/modal_bottom_sheet
Comments
  • 1. showBarModalBottomSheet does not adjust size on keyboard open

    This is an my modal sheet:

        String _prevText =
            await Provider.of<FirebaseDataProvider>(context, listen: false)
                .getMarquee();
        TextEditingController _marqueeController =
            TextEditingController(text: _prevText);
        return showBarModalBottomSheet(
            context: context,
            expand: true,
            builder: (BuildContext context, ScrollController scrollController) {
              return Material(
                child: Container(
                  // height: MediaQuery.of(context).size.height * 0.3,
                  color: Theme.of(context).colorScheme.primary,
                  child: Padding(
                    padding: const EdgeInsets.all(12.0),
                    child: ListView(
                      controller: scrollController,
                      shrinkWrap: true,
                      children: <Widget>[
                        AutoSizeText(
                          title,
                          style: TextStyle(
                              color: Theme.of(context).colorScheme.onPrimary),
                        ),
                        TextField(
                          decoration: InputDecoration(hintText: 'escribe aquΓ­'),
                          controller: _marqueeController,
                          autofocus: true,
                        ),
                        FlatButton(
                          color: Colors.green,
                          child: AutoSizeText(
                            'OK',
                            style: TextStyle(color: Colors.white),
                          ),
                          onPressed: () {
                            Provider.of<FirebaseDataProvider>(context,
                                    listen: false)
                                .setMarquee(_marqueeController.text);
                            Navigator.of(context).pop();
                          },
                        ),
                        FlatButton(
                          color: Colors.red,
                          child: AutoSizeText(
                            'Cancelar',
                            style: TextStyle(color: Colors.white),
                          ),
                          onPressed: () {
                            Navigator.of(context).pop();
                          },
                        ),
                      ],
                    ),
                  ),
                ),
              );
            });
      }
    } 
    

    So right now I have to fix the height to mediaquery * 0.6 so that keyboard does not interfere with textfileld inside the modal sheet. But I would really like for the size to change depending on the keyboard size.

    I am going to attach a few pictures representing expand setting with and without keyboard...

    expand_false_no_kb expand_false_no_kb

    expand_false_with_kb expand_false_with_kb

    expand_true_no_kb expand_true_no_kb

    expand_true_with_kb expand_true_with_kb

    Reviewed by fenchai23 at 2020-05-06 02:30
  • 2. Doesn't go back to the top sometimes

    Almost perfect except :

    1. sometimes when I let ago while dragging, the sheet doesn't go back to the top and just stops there. It happens quite frequently.

    2. The animation curve is ugly. Please provide a parameter to pass the animation curve. Haven't read the code but is this related to PageRoute ?

    3. Provide a parameter for the dismiss threshold. Personally, I feel it's a bit hard to dismiss. I prefer it easier to dismiss.

    I am using dev channel of flutter.

    Gif: issue01

    Regards Hiroshi

    Reviewed by hiroshihorie at 2020-04-30 19:46
  • 3. version 0.2.0+1 breaks with Flutter Beta 1.22.0-12.1.pre

    flutter doctor shows:

    [βœ“] Flutter (Channel master, 1.22.0-10.0.pre.109, on Mac OS X 10.15.6 19G2021, locale en-GB)
    
    modal_bottom_sheet: ^0.2.0+1
    

    during compiling, it fail with:

    ../../../.pub-cache/hosted/pub.dartlang.org/modal_bottom_sheet-0.2.0+1/lib/src/bottom_sheet.dart:295:43: Error: Too few positional arguments: 1 required, 0 given.
            _velocityTracker = VelocityTracker();
                                              ^
    ../../../Sandbox/flutter/packages/flutter/lib/src/gestures/velocity_tracker.dart:152:3: Context: Found this candidate, but the arguments don't match.
      VelocityTracker(this.kind);
      ^^^^^^^^^^^^^^^
    

    Looks like flutter changed the interface:

    /// Computes a pointer's velocity based on data from [PointerMoveEvent]s.
    ///
    /// The input data is provided by calling [addPosition]. Adding data is cheap.
    ///
    /// To obtain a velocity, call [getVelocity] or [getVelocityEstimate]. This will
    /// compute the velocity based on the data added so far. Only call these when
    /// you need to use the velocity, as they are comparatively expensive.
    ///
    /// The quality of the velocity estimation will be better if more data points
    /// have been received.
    class VelocityTracker {
      /// Create a new velocity tracker for a pointer [kind].
      VelocityTracker(this.kind);
    
    Reviewed by soloman817 at 2020-09-09 13:31
  • 4. CupertinoUserInterfaceLevel and ColorFilter for CupertinoBottomSheet

    This PR adds the changes discussed in #41 .

    The previousRoute is now wrapped with a ColorFilter and has a CupertinoUserInterfaceLevel.elevated thus the CupertinoDynamicColors automatically uses the elevatedColor. This makes it unnecessary to detect if dark mode is activated. The changes are only applied when the transition is started. While making the changes I noticed that even when the animation isn't started the child is wrapped with Translate and ClipRect. This is not nessecary and therefore I adding a check if the animation.value is 0 then only the child itself is displayed and otherwise the widgets nessecary for the translation. This should improve the performance a bit.

    The seconds change I made was to wrap the child of the modal with CupertinoUserInterfaceLevel and give it also an CupertinoUserInterfaceLevel.elevated .

    Reviewed by bierbaumtim at 2020-07-11 17:46
  • 5. Expose on popped API on showCupertinoModalBottomSheet

    I need to run a specific function when the modal sheet is closed or return some value, So is it possible to expose some API from CupertinoModalBottomSheetRoute which is rendered in showCupertinoModalBottomSheet

    await showCupertinoModalBottomSheet(
    	context: context,
    	builder: (context, scrollController) => Container();
    	popped: () {
           print('Modal is closed')
    	}
    );
    

    or the return value from widget which is rendered

    T result = await showCupertinoModalBottomSheet<T>(
    	context: context,
    	builder: (context, scrollController) => Container();
    );
    
    Reviewed by Amerr at 2020-06-20 20:34
  • 6. Change black background color when cupertino modal fit opens.

    I'm using this with material scaffold and I wanted to achieve new ios style navigation. It works well except the background of my app is black. How do I change it ?

    Reviewed by westdabestdb at 2020-04-17 17:31
  • 7. Scaling down of the previous page

    Hey, thanks for the fantastic package!

    I'm successfully displaying a modal page like this: showCupertinoModalBottomSheet( expand: false, context: context, backgroundColor: Colors.transparent, builder: (context) => ItemFullView("Item") )

    However, unlike the demo app, the previous page doesn't dim and scale down. Could you please tell me what are the essential steps/changes to the page widget to get this effect?

    Reviewed by plavunov at 2021-03-28 12:36
  • 8. UI elements within Modal not rebuilding when state is changed

    I have a modal which displays a ListView and has RadioListTiles within. When I select a RadioListTile, the state data changes but the UI won't rebuild until the modal is closed and re opened. I have also noticed when changing the elements within the modal will not hot update when you save the source.dart file - you need to close and re open the modal.

    Any ideas how to get widgets within the modal to rebuild when state is changed?

    Reviewed by FickleLife at 2020-09-28 04:47
  • 9. Add PointerDeviceKind to VelocityTracker()

    Ola @jamesblasco ,

    As I have mentioned in #72 I have made a fix and please do verify it and pull ASAP, cause I need to build my app, It takes large size 😜.

    Regards.

    Closes #72

    Reviewed by yahu1031 at 2020-09-12 22:48
  • 10. Bottom Sheet loses data on move

    I tried the Bottom sheet with a simple increment integer with a + icon. If I change the state with incrementing a number and I move the bottom sheet, for example sliding a bit down and up, then the new state is lost. It shows me the initial number.

    Is this normal that event to close the dialog is fired on moving the sheet? Or is there an error in my code?

    By the way: Thanks for your great work!

    Reviewed by Asored-D at 2020-07-05 07:48
  • 11. Compile error after importing the library

    After installing the library and trying out the example simple show alert code, the code does not compile. I get the following error

    Compiler message: ../../../flutter/.pub-cache/hosted/pub.dartlang.org/modal_bottom_sheet-0.2.0+1/lib/src/bottom_sheet.dart:184:3: Error: Type 'ParametricCurve' not found. ParametricCurve<double> animationCurve; ^^^^^^^^^^^^^^^ ../../../flutter/.pub-cache/hosted/pub.dartlang.org/modal_bottom_sheet-0.2.0+1/lib/src/bottom_sheet.dart:184:3: Error: Expected 0 type arguments. ParametricCurve<double> animationCurve; ^ ../../../flutter/.pub-cache/hosted/pub.dartlang.org/modal_bottom_sheet-0.2.0+1/lib/src/bottom_sheet.dart:318:3: Error: Type 'ParametricCurve' not found. ParametricCurve<double> get _defaultCurve => ^^^^^^^^^^^^^^^ ../../../flutter/.pub-cache/hosted/pub.dartlang.org/modal_bottom_sheet-0.2.0+1/lib/src/bottom_sheet.dart:318:3: Error: Expected 0 type arguments. ParametricCurve<double> get _defaultCurve => ^ ../../../flutter/.pub-cache/hosted/pub.dartlang.org/modal_bottom_sheet-0.2.0+1/lib/src/utils/bottom_sheet_suspended_curve.dart:28:41: Error: Type 'ParametricCurve' not found. class BottomSheetSuspendedCurve extends ParametricCurve<double> { ^^^^^^^^^^^^^^^ ../../../flutter/.pub-cache/hosted/pub.dartlang.org/modal_bottom_sheet-0.2.0+1/lib/src/utils/bottom_sheet_suspended_curve.dart:28:41: Error: Expected 0 type arguments. class BottomSheetSuspendedCurve extends ParametricCurve<double> { ^ ../../../flutter/.pub-cache/hosted/pub.dartlang.org/modal_bottom_sheet-0.2.0+1/lib/src/bottom_sheet.dart:184:3: Error: 'ParametricCurve' isn't a type. ParametricCurve<double> animationCurve; ^^^^^^^^^^^^^^^ ../../../flutter/.pub-cache/hosted/pub.dartlang.org/modal_bottom_sheet-0.2.0+1/lib/src/bottom_sheet_route.dart:42:27: Error: Getter not found: 'linux'. case TargetPlatform.linux: ^^^^^ ../../../flutter/.pub-cache/hosted/pub.dartlang.org/modal_bottom_sheet-0.2.0+1/lib/src/bottom_sheet_route.dart:43:27: Error: Getter not found: 'macOS'. case TargetPlatform.macOS: ^^^^^ ../../../flutter/.pub-cache/hosted/pub.dartlang.org/modal_bottom_sheet-0.2.0+1/lib/src/bottom_sheet_route.dart:44:27: Error: Getter not found: 'windows'. case TargetPlatform.windows: ^^^^^^^ Target kernel_snapshot failed: Exception: Errors during snapshot creation: null Failed to build bundle. Error launching application on iPhone 8.

    This is how I am using it:

    showCupertinoModalBottomSheet( context: context, builder: (context, scrollController) => MySuperPage(), );

    Reviewed by kristijorgji at 2020-08-28 09:05
  • 12. Doesn't work with CupertinoTabScaffold

    Using onGenerateRoute and MaterialWithModalsPageRoute, if the builder returns a CupertinoPageScaffold everything works as in the examples, but if it returns a CupertinoTabScaffold the background doesn't animate (shrink). If I wrap the CupertinoTabScaffold with a CupertinoScaffold and use CupertinoTabScaffold.showCupertinoModalBottomSheet the background shrinks but the modal is contained within the shrunken background instead.

    Reviewed by traed at 2022-06-13 15:01
  • 13. Header color invalid when popping second modal

    Hello. I'm experiencing following bug: when I push modal twice, everything looks well. But when I pop second modal, the first modal have this bad looking white color under the header. Dragging modal by a little removes the problem.

    https://user-images.githubusercontent.com/21008961/173352111-afae1352-0f81-49bf-aceb-fbce95b72fcd.mov

    How can I fix it?

    Reviewed by matisiekpl at 2022-06-13 12:21
  • 14. fix: Revert removal of hasReachedWillPopThreshold check on drag end

    Removal of this check produced unwanted onWillPop calls on drag end even if the threshold was not reached.

    This should fix:

    • https://github.com/jamesblasco/modal_bottom_sheet/issues/229#issue-1176894265
    • https://github.com/jamesblasco/modal_bottom_sheet/issues/230#issue-1181064170 And maybe:
    • https://github.com/jamesblasco/modal_bottom_sheet/issues/233#issue-1183181552
    Reviewed by marcsanny at 2022-05-20 08:14
  • 15. Modal from the top to the bottom of the screen

    Hello,

    Thanks for your great work. I'm willing to implement modal_bottom_sheet in my company project however it has to support modal coming from the top of the screen. I'm not able to find any solution to do this without any changes to the source code, is it indeed possible ?

    Thanks, Jeff

    Reviewed by jeff-odopass at 2022-05-18 14:17

Related

An elastic material bottom sheet implementation for Flutter.
An elastic material bottom sheet implementation for Flutter.

An elastic material bottom sheet implementation for Flutter. This is still an early preview, some behaviors can change or being removed. Every feedbac

Jun 20, 2022
Instagram post style button/card made for flutter
Instagram post style button/card made for flutter

Instagram post style button/card made for flutter

Mar 30, 2022
A Very Flexible Widget that can Implement Material Sheets on all Directions, both modal and persistent, and consequently a Material Navigation Drawer

Flutter_MaterialSheetAndNavigationDrawer If this project helped you reduce developement time or you just want to help me continue making useful tools

Dec 4, 2021
Circular Bottom Navigation Iman KhoshabiCircular Bottom Navigation [368⭐] - Beautiful animated bottom navigation bar by Iman Khoshabi.
Circular Bottom Navigation Iman KhoshabiCircular Bottom Navigation [368⭐] - Beautiful animated bottom navigation bar by Iman Khoshabi.

Circular Bottom Navigation (or maybe a tab bar). This is implementation of an artwork in Uplabs Donate Support us by becoming a patron on Patreon Let'

Jun 18, 2022
Flutter modal bottom route - A flutter route animation
Flutter modal bottom route - A flutter route animation

flutter_modal_bottom_route This is a flutter route animation demo. See Chinouo J

Mar 16, 2022
Flutter 2.0 (Null safety) Snapping Modal Bottom Sheet made using sliding sheet package. πŸ”–
Flutter 2.0 (Null safety) Snapping Modal Bottom Sheet made using sliding sheet package. πŸ”–

Snapping Modal Bottom Sheet Developement Stack Getting Started This project is a starting point for a Flutter application. A few resources to get you

Sep 20, 2021
New trick on how to create your own custom icons in flutter with bottom bar navigation
New trick on how to create your own custom icons in flutter with bottom bar navigation

Customized Bottom Navigation Bar in Flutter | Tech With Sam Customized Bottom Navigation Bar in Flutter - Watch on youtube ✌   App Preview App Screens

Feb 25, 2022
Cupertino app codelab - Building a Cupertino App with Flutter
Cupertino app codelab - Building a Cupertino App with Flutter

Building a Cupertino App with Flutter Flutter allows us creating Cupertino (iOS-

Apr 18, 2022
Flutter cupertino style date picker.
Flutter cupertino style date picker.

Flutter Cupertino Date Picker [pub packages] | δΈ­ζ–‡θ―΄ζ˜Ž Flutter cupertino date picker. Usage 1. Depend Add this to you package's pubspec.yaml file: depend

Jun 17, 2022
Flutter cupertino style date picker.
Flutter cupertino style date picker.

Flutter Cupertino Date Picker [pub packages] | δΈ­ζ–‡θ―΄ζ˜Ž Flutter cupertino date picker. Usage 1. Depend Add this to you package's pubspec.yaml file: depend

Jun 17, 2022
Cupertino version of the Material Stepper in Flutter
Cupertino version of the Material Stepper in Flutter

Cupertino Stepper for Flutter Cupertino version of the stock Material Stepper in Flutter. NOTE: This is not the same as the UIStepper control on iOS.

Jun 7, 2022
Material & Cupertino SpinBox for Flutter
Material & Cupertino SpinBox for Flutter

SpinBox for Flutter SpinBox for Flutter is a numeric input widget with an input field for entering a specific value, and spin buttons for quick, conve

Jun 14, 2022
Customizable Material and Cupertino buttons with progress indicators and more
Customizable Material and Cupertino buttons with progress indicators and more

future_button Customizable Material and Cupertino buttons with progress indicators and more.

Mar 25, 2022
Loading indicator GIFs. Material and Cupertino (Android and iOS) loading indicators in assorted sizes. Use as placeholders for loading remote image assets. Demo: https://gallery.codelessly.com/flutterwebsites/loadinggifs/
Loading indicator GIFs. Material and Cupertino (Android and iOS) loading indicators in assorted sizes. Use as placeholders for loading remote image assets. Demo: https://gallery.codelessly.com/flutterwebsites/loadinggifs/

Loading GIFs High quality Android and iOS loading spinners. View Demo Loading GIFs is a collection of high fidelity loading animations in GIF format.

Jun 13, 2022
Target the specific design of Material for Android and Cupertino for iOS widgets through a common set of Platform aware widgets
Target the specific design of Material for Android and Cupertino for iOS widgets through a common set of Platform aware widgets

Flutter Platform Widgets This project is an attempt to see if it is possible to create widgets that are platform aware. Currently in order to render t

Jun 26, 2022
Target the specific design of Material for Android and Cupertino for iOS widgets through a common set of Platform aware widgets
Target the specific design of Material for Android and Cupertino for iOS widgets through a common set of Platform aware widgets

Flutter Platform Widgets This project is an attempt to see if it is possible to create widgets that are platform aware. Currently in order to render t

Jun 26, 2022
An open source encrypted peer-to-peer system. Own data, own privacy. (Rust+Flutter)
An open source encrypted peer-to-peer system. Own data, own privacy. (Rust+Flutter)

An open source encrypted peer-to-peer system. Own data, own privacy. (Rust+Flutter)

Oct 7, 2021
An advanced story viewer for Flutter. Quite easy & Quite advanced
An advanced story viewer for Flutter. Quite easy & Quite advanced

AdvStory ?? Quite simple & Quite advanced ?? Advanced Story viewer for Flutter. Supports image, video and custom stories. Full control over stories fo

Jun 21, 2022
An open source encrypted peer-to-peer system. Own data, own privacy.
An open source encrypted peer-to-peer system. Own data, own privacy.

An open source encrypted peer-to-peer system. Own data, own privacy.

Jun 22, 2022
Encrypted peer-to-peer system for data security. Own data, own privacy
Encrypted peer-to-peer system for data security. Own data, own privacy

ESSE (Encrypted Symmetrical Session Engine) An open source encrypted peer-to-pee

Jun 22, 2022