I am using MaterialApp and Scaffold + SafeArea for screens. All works well until I try to use persistent BottomSheet. BottomSheet content igores SafeArea and are shown below system controls, for example in iPhone X.
I tried to wrap BottomSheet contents in another SafeArea element, but it did not help.
Is there a way to get the same functionality as SafeArea to work in BottomSheet? If yes then how?
Solution 1: Matt S.
I tried out this simple code and it works as intended in the iOS Simulator with an iPhone X:
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new SafeArea(
child: new Scaffold(
appBar: new AppBar(
title: new Text('SafeArea demo'),
),
body: new Center(
child: new TapMe(),
),
),
));
}
}
class TapMe extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new RaisedButton(
child: new Text('Tap Me'),
onPressed: () => Scaffold
.of(context)
.showBottomSheet((context) => new Text('I\'ve been tapped')),
);
}
}
What version of Flutter are you using?
Solution 2: user976746
Just make the root Widget of the showModalBottomSheet be a SafeArea Widget
showModalBottomSheet<void>(
context: context,
builder: (BuildContext context) {
return SafeArea(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[...
Solution 3: miso01
I have faced this issue too. When I changed code from showModalBottomSheet
to _scaffoldKey.currentState.showBottomSheet
my SafeArea
stopped working.
You can solve it with these steps:
- create key for your Scaffold
GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey();
- assign created key to your Scaffold
key: _scaffoldKey,
- set bottom padding to your bottom sheet
padding: EdgeInsets.only(bottom: MediaQuery.of(_scaffoldKey.currentState.context).viewPadding.bottom)
Here is a result, I also added 15 padding to top, left and right.
Solution 4: Demian S
In my case the top safe area was the problem and a practical workaround was to set padding to the height of the app bar with AppBar().preferredSize.height
Padding(
padding: EdgeInsets.fromLTRB(0,AppBar().preferredSize.height,0,0),
child: Text(
'Your Order',
style: headingMediumBlack,
),
),
Solution 5: Arenukvern
Faced this issue too with top-notch.
Resolved using dart:ui.window.viewPadding.top / ui.window.devicePixelRatio
How it works:
The dart:ui.window.viewPadding
is the number of physical pixels on each side of the display rectangle into which the view can render.
By dividing to ui.window.devicePixelRatio
we should receive logic pixels.
So in summary code is
showModalBottomSheet<bool>(
context: context,
builder: (BuildContext context) => Container(
height: MediaQuery.of(context).size.height,
padding: EdgeInsets.only(
top: ui.window.viewPadding.top / ui.window.devicePixelRatio,
),
),
);
Solution 6: Khamidjon Khamidov
I solved the problem by adding container and padding inside with: MediaQueryData.fromWindow(WidgetsBinding.instance.window).padding.top
Container(
padding: EdgeInsets.only(
top: MediaQueryData.fromWindow(WidgetsBinding.instance.window).padding.top),
child: MyOriginalWidgetForBottomSheet(),
)
Don't get from the context (like MediaQuery.of(context).padding.top
) as the padding always returns 0
Solution 7: us3r01
IMHO, The cleanest workaround is to set InitialChildSize
to 0.9
DraggableScrollableSheet(
initialChildSize: 0.9,
minChildSize: 0.2,
maxChildSize: 0.9,
expand: false,
builder: (BuildContext context, ScrollController scrollController) {
}
)