125

showModalBottomSheet does not provide any styling or decorations. I want to create something like the Google Tasks bottomsheet.

google tasks bottomsheet

Herman
  • 1,882
  • 3
  • 14
  • 17

17 Answers17

304

UPDATED ON 2019-08-05

You can now do it using the default showModalBottomSheet method that now supports adding a ShapeBorder and also backgroundColor!

showModalBottomSheet(
  shape: RoundedRectangleBorder(
     borderRadius: BorderRadius.circular(10.0),
  ),
  backgroundColor: Colors.white,
  ...
);

--

Instead of overriding the entire theme of the app (which caused problems in various parts of my app) as suggested by other answers, I decided to take a look at the implementation for showModalBottomSheet and find the problem myself. Turns out that all that was needed was wrapping the main code for the modal in a Theme widget that contains the canvasColor: Colors.transparent trick. I also made it easier to customize the radius and also the color of the modal itself.

You can use either the package on pub or a gist containing the same code. Don't forget to import the proper package/file.

showRoundedModalBottomSheet(
    context: context,
    radius: 20.0,  // This is the default
    color: Colors.white,  // Also default
    builder: (context) => ???,
);
Gildásio Filho
  • 3,117
  • 2
  • 10
  • 6
  • 1
    +1. For me it was not sufficient to wrap only the button which contained the method for showing the modal bar. But wrapping the Scaffold which contained the screen with such a Theme worked. `@override Widget build(BuildContext context) { return Theme( // We need this theme override so that the corners of the bottom sheet modal can be rounded data: ThemeData(canvasColor: Colors.transparent), child: Scaffold( ....` – Simon Olsen Apr 01 '19 at 11:28
  • 1
    For me I also needed to add `clipBehaviour: Clip.hardEdge` to make to corners round – Fah May 08 '23 at 10:44
127
showModalBottomSheet(
context:context
shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.vertical(
          top: Radius.circular(20),
        ),
      ),
      clipBehavior: Clip.antiAliasWithSaveLayer,
)
Xcode
  • 129
  • 1
  • 11
Sharjeel Ali
  • 1,459
  • 1
  • 11
  • 8
118

This is the modalBottomSheet function needed.

    void _modalBottomSheetMenu(){
        showModalBottomSheet(
            context: context,
            builder: (builder){
              return new Container(
                height: 350.0,
                color: Colors.transparent, //could change this to Color(0xFF737373), 
                           //so you don't have to change MaterialApp canvasColor
                child: new Container(
                    decoration: new BoxDecoration(
                        color: Colors.white,
                        borderRadius: new BorderRadius.only(
                            topLeft: const Radius.circular(10.0),
                            topRight: const Radius.circular(10.0))),
                    child: new Center(
                      child: new Text("This is a modal sheet"),
                    )),
              );
            }
        );
      }

Also the most important part of this working properly is, in MaterialApp set canvasColor to transparent like the one shown below.

return new MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Tasks',
      theme: new ThemeData(
        primarySwatch: Colors.teal,
        canvasColor: Colors.transparent,
      ),
      home: new TasksHomePage(),
    );
  }

I have tested the code and it works fine as I was also making a clone of the Google Tasks app which will be opensourced in my github.

Satyabrat Sahoo
  • 1,351
  • 1
  • 10
  • 7
  • 13
    Changing global `canvasColor` for a bottomSheet round corner is not a good tradeoff. use `Theme` wrapper instead. Also if you widgets inside the bottom sheet is theme depended then use `data: yourTheme().copyWith(canvasColor: Colors.transparent)` just to apply canvas color only to its child. Best option would be the Updated one. – sh0umik Oct 14 '19 at 09:17
  • Thanks @sh0umik that was a great tip! – Delicia Fernandes Nov 25 '20 at 22:08
  • 1
    Doing this will change canvas color for all the app, which means that, for example, the 'Select/Copy/Paste' native tooltip will have a transparent background color instead of the default white. I think this should be the correct answer: https://stackoverflow.com/a/62457068/7691350 – Jose Jet Dec 11 '20 at 12:03
  • 1
    Theme wrapper with canvasColor not worked. So I used `bottomSheetTheme: BottomSheetThemeData(backgroundColor: Colors.transparent)` in MaterialApp theme. – temirbek Aug 17 '21 at 07:40
  • 1
    I think using bottomSheetTheme as @temirbek's answer is the best way in this case. – apieceofcode1801 Apr 22 '22 at 04:18
41

I think the best way to do a rounded-corner modal is to use a RoundedRectangleBorder with a vertical BorderRadius, setting only its top property:

showModalBottomSheet(
        context: context,
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.vertical(top: Radius.circular(25.0)),
        ),
        builder: (BuildContext context) {
          // return your layout
        });

Using separate radii for top left and top right is a bit more verbose and error-prone.

npace
  • 4,218
  • 1
  • 25
  • 35
22

i have this code and work well for me. please check it and let me know you'r opinion.

showBottomSheet(
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.vertical(
              top: Radius.circular(20),
            ),
          ),
          context: context,
          builder: (context) => Container(
                height: 250,

                child: new Container(
                    decoration: new BoxDecoration(
                        color: Theme.of(context).primaryColor,
                        borderRadius: new BorderRadius.only(
                            topLeft: const Radius.circular(20.0),
                            topRight: const Radius.circular(20.0))),
                    child: new Center(
                      child: new Text("This is a modal sheet"),
                    )),
              ))
19

You can now simply set the shape argument. Example:

showModalBottomSheet(
  shape: RoundedRectangleBorder(
    borderRadius: BorderRadius.all(Radius.circular(10.0)),
  ),
  context: context,
  builder: (context) => MyBottomSheet(),
);
Sven
  • 3,204
  • 1
  • 20
  • 28
11

one way is by usingshowModalBottomSheet shape property,

showModalBottomSheet(
  context:context
  shape: const RoundedRectangleBorder(
    borderRadius: BorderRadius.only(
      topLeft: Radius.circular(10.0),
      topRight: Radius.circular(10.0),
    ),
  ),
)
Andra
  • 111
  • 1
  • 3
10

Set the shape to RoundedRectangleBorder should work, but sometimes the content overflows making round corners missing, when this happens set clipBehavior to Clip.antiAlias to resolve.

showModalBottomSheet(
    isScrollControlled: true,
    backgroundColor: colorOnPrimary,
    // set this when inner content overflows, making RoundedRectangleBorder not working as expected
    clipBehavior: Clip.antiAlias,
    // set shape to make top corners rounded
    shape: const RoundedRectangleBorder(
        borderRadius: BorderRadius.only(
            topLeft: Radius.circular(16), 
            topRight: Radius.circular(16),
        ),
    ),
    context: context,
    builder: (context) {
        return SingleChildScrollView(
            child: Container(),
        );
    },
)
linxie
  • 1,849
  • 15
  • 20
7

Putting together all the answers before, I could achieve the best result possible (in my opinion) for this.

showModalBottomSheet(
        context: context,
        backgroundColor: Colors.white,
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.only(topLeft: Radius.circular(15.0), topRight: Radius.circular(15.0)),
        ),
        builder: (context) {
          return Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[     
              ListTile(
                leading: Icon(Icons.email),
                title: Text('Send email'),
                onTap: () {
                  print('Send email');
                },
              ),
              ListTile(
                leading: Icon(Icons.phone),
                title: Text('Call phone'),
                 onTap: () {
                    print('Call phone');
                  },
               ),                  
            ],
          );
        });
5

You can add a RoundedRectangleBorder widget inside the showModalBottomSheet:

showModalBottomSheet<void>(
    shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.only(
            topLeft: Radius.circular(10.0),
            topRight: Radius.circular(10.0)
        ),
    ),
)
ib.
  • 27,830
  • 11
  • 80
  • 100
3
    showModalBottomSheet(
     backgroundColor: Colors.transparent,
     context: context,
     builder: (ctx) {
      return Container( 
      decoration: BoxDecoration(
      color: Colors.green, // or some other color
      borderRadius: BorderRadius.only(
      topLeft: Radius.circular(10.0),
      topRight: Radius.circular(10.0)
       ) 
     );
    });
prosoitos
  • 6,679
  • 5
  • 27
  • 41
2

You can give borderRadius in decoration container also.

 showModalBottomSheet(
                context: context,
                builder: (builder){
                  return  Container(
                        decoration: BoxDecoration(
                            color: Colors.white,
                            borderRadius: BorderRadius.only(
                                topLeft: const Radius.circular(15.0),
                                topRight: const Radius.circular(15.0))),
                        child: Center(
                          child: Text("This is a modal sheet"),
                        ),
                  );
                }
            );
Shrey Jain
  • 73
  • 1
  • 5
2

for persistent bottom sheet, add the following code in the material app widget's theme property

ThemeData(          
          bottomSheetTheme: BottomSheetThemeData(
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(10.0),
            ),
          ),
        ),
Mureinik
  • 297,002
  • 52
  • 306
  • 350
Unais IB
  • 69
  • 3
1
showModalBottomSheet(
  context:context
  shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.vertical(
          top: Radius.circular(20),
        ),
      ),
  clipBehavior: Clip.hardEdge,
)

It will be much better to use Clip.hardEdge. As it is faster than other clipping modes but slower than [none].

Talha Javed Khan
  • 380
  • 1
  • 10
0

Just answered a related question

You can add corners to your bottomSheet and expand your bottomSheet according to content present inside it (not restricted to half size of screen)

check out the answer here

https://stackoverflow.com/a/59541927/9236994

Vicky Salunkhe
  • 9,869
  • 6
  • 42
  • 59
0

you can now do it with the showModelBottomSheet() widget parameter shape

showModalBottomSheet<void>(
           shape: const RoundedRectangleBorder(
                  borderRadius:  BorderRadius.only(topLeft: 
                      Radius.circular(24),topRight:Radius.circular(24) ),),
                          context: context,
                          builder: (BuildContext context) {}
0

use the showModalBottomSheet

shape:

property which takes ShapeBorder as shown below

 shape: const RoundedRectangleBorder(
      borderRadius: BorderRadius.vertical(top: Radius.circular(25.0)),
    ),

enter image description here

Code with Benji
  • 666
  • 9
  • 17