Flutter BottomSheet change width
Solution 1
UPDATE : Flutter now support constraints property in showModalBottomSheet
showModalBottomSheet(
context: context,
constraints: BoxConstraints(
maxWidth: Responsive.isMobile(context) ? Get.width : 600,
),
builder: ...
),
Solution 2
UPDATE
Flutter added constraints to showModalBottomSheet and it's available on master, dev and beta :)
Solution 3
You can wrap your widget with an Align
widget and set the alignment to bottom center, then you can set box constraints if you want to have a maximum width
Align(
alignment: Alignment.bottomCenter,
child: ConstrainedBox(
constraints: BoxConstraints(...),
child: ...
),
)
Dennis Barzanoff
Updated on December 01, 2022Comments
-
Dennis Barzanoff over 1 year
I want the bottom sheet to look like the one in Angular Material.
The sheet instead expands to the maximum width. The problem is that I cannot configure the width of the bottom sheet. It currently looks like thisMy code looks like this:
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue), debugShowCheckedModeBanner: false, home: Scaffold( body: ..., floatingActionButton: FloatingActionButton( child: Icon(Icons.add), tooltip: 'Add File', onPressed: () => showModalBottomSheet( context: context, builder: (context) => AddFileBottomSheet(), shape: RoundedRectangleBorder( borderRadius: BorderRadius.only( topLeft: Radius.circular(10), topRight: Radius.circular(10), ), ), // backgroundColor: Colors.transparent, isScrollControlled: true, ), ), ), ); } } class AddFileBottomSheet extends StatelessWidget { @override Widget build(BuildContext context) { return Column( mainAxisSize: MainAxisSize.min, children: <Widget>[ Container( padding: EdgeInsets.symmetric(vertical: 20, horizontal: 5), alignment: Alignment.center, child: Text( 'Create New File', style: Theme.of(context).textTheme.headline5, ), ), GridView.count( shrinkWrap: true, crossAxisCount: 3, children: [ _gridTile( context: context, icon: Icon(Icons.file_upload), text: 'Upload File', callback: () => print('lel'), ), _gridTile( context: context, icon: Icon(Icons.create), text: 'Create Text File', callback: () => print('lel'), ), ], ), ], ); } Widget _gridTile({ @required BuildContext context, @required Icon icon, @required String text, @required void callback(), }) { return InkWell( onTap: () => callback(), child: Container( padding: EdgeInsets.all(15), alignment: Alignment.center, height: double.infinity, width: double.infinity, child: Column( mainAxisSize: MainAxisSize.min, children: <Widget>[ icon, Text(text, style: Theme.of(context).textTheme.subtitle2), ], ), ), ); } }
I know I can fake it having a smaller width when making some of it transparent, but I have round edges and they won't get preserved.
Workaround #1
I managed to do it by changing the
canvasColor
to transparent and making the borders rounded in the widget: This way, however I need to do additional logic to dismiss it when the user clicks the fake transparent area.First add the
canvasColor
to the context somehow:... floatingActionButton: Theme( data: Theme.of(context).copyWith(canvasColor: Colors.transparent), child: Builder( builder: (context) => FloatingActionButton( child: Icon(Icons.add), tooltip: 'Add File', onPressed: () => showModalBottomSheet( context: context, builder: (context) => AddFileBottomSheet(), // shape: RoundedRectangleBorder( // borderRadius: BorderRadius.only( // topLeft: Radius.circular(10), // topRight: Radius.circular(10), // ), // ), // backgroundColor: Colors.transparent, isScrollControlled: true, ), ), ), ), ...
Then fake the width
return Container( padding: EdgeInsets.symmetric(horizontal: 300), child: Container( decoration: BoxDecoration( color: Colors.white, shape: BoxShape.rectangle, borderRadius: BorderRadius.only( topLeft: Radius.circular(10), topRight: Radius.circular(10), ), ), // backgroundColor: Colors.transparent, child: Column( mainAxisSize: MainAxisSize.min, children: <Widget>[ Container( padding: EdgeInsets.symmetric(vertical: 20, horizontal: 5), alignment: Alignment.center, child: Text( 'Create New File', style: Theme.of(context).textTheme.headline5, ), ), GridView.count( shrinkWrap: true, crossAxisCount: 3, children: [ _gridTile( context: context, icon: Icon(Icons.file_upload), text: 'Upload File', callback: () => print('lel'), ), _gridTile( context: context, icon: Icon(Icons.create), text: 'Create Text File', callback: () => print('lel'), ), ], ), ], ), ), );
I wonder if there is a standard approach to this and I need your help. I tried making a DartPad example, but it gives me
Script error
.My idea was to try and make it mobile friendly with something like this:
final isMobile = MediaQuery.of(context).size.width < 700; return Container( padding: EdgeInsets.symmetric(horizontal: isMobile ? 0: 300), child: ... )
This will make it full-width when mobile and with some padding when desktop.
-
James Poulose about 2 yearsAs of now adding a
constraint
toshowModalBottomSheet
is the right way to go.
-
-
Dennis Barzanoff over 3 yearslooks promising, but I cannot test it rn. I will accept your answer if you are sure it works
-
Pantelis Tsak over 3 yearsYeah, I had the same problem as you, as I wanted not to have full width bottom sheet on tablets. You can try it your self some day, thanks
-
Rebar almost 3 yearsThis solution is not working. I've created a feature request on Flutter repo. Hope for the best.