'How to create a modal bottomsheet with circular corners in Flutter?

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

google tasks bottomsheet



Solution 1:[1]

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.

Solution 2:[2]

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) => ???,
);

Solution 3:[3]

showModalBottomSheet(
context:context
shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.vertical(
          top: Radius.circular(20),
        ),
      ),
      clipBehavior: Clip.antiAliasWithSaveLayer,
)

Solution 4:[4]

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.

Solution 5:[5]

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"),
                    )),
              ))

Solution 6:[6]

You can now simply set the shape argument. Example:

showModalBottomSheet(
  shape: RoundedRectangleBorder(
    borderRadius: BorderRadius.all(Radius.circular(10.0)),
  ),
  context: context,
  builder: (context) => MyBottomSheet(),
);

Solution 7:[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');
                  },
               ),                  
            ],
          );
        });

Solution 8:[8]

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)
        ),
    ),
)

Solution 9:[9]

    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)
       ) 
     );
    });

Solution 10:[10]

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),
    ),
  ),
)

Solution 11:[11]

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"),
                        ),
                  );
                }
            );

Solution 12:[12]

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(),
        );
    },
)

Solution 13:[13]

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

Solution 14:[14]

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),
            ),
          ),
        ),

Solution 15:[15]

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].