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 {
  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 {
  Widget build(BuildContext context) {
    return new RaisedButton(
      child: new Text('Tap Me'),
      onPressed: () => Scaffold
          .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

    context: context,
    builder: (BuildContext context) {
      return SafeArea(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[...

enter image description here

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:

  1. create key for your Scaffold GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey();
  2. assign created key to your Scaffold key: _scaffoldKey,
  3. 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.

enter image description here

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: 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

  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

      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

  initialChildSize: 0.9,
  minChildSize: 0.2,
  maxChildSize: 0.9,
  expand: false,
  builder: (BuildContext context, ScrollController scrollController) {