How to Move bottomsheet along with keyboard which has textfield(autofocused is true)?

DartFlutterFlutter Layout

Dart Problem Overview


I'm trying to make a bottomsheet that has a text field and autofocus is set to true so that the keyboard pops up. But, bottomsheet is overlapped by the keyboard. Is there a way to move bottomsheet above the keyboard?

Padding(
  padding:
      EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
  child: Column(children: <Widget>[
    TextField(
      autofocus: true,
      decoration: InputDecoration(hintText: 'Title'),
    ),
    TextField(
      decoration: InputDecoration(hintText: 'Details!'),
      keyboardType: TextInputType.multiline,
      maxLines: 4,
    ),
    TextField(
      decoration: InputDecoration(hintText: 'Additional details!'),
      keyboardType: TextInputType.multiline,
      maxLines: 4,
    ),]);

Dart Solutions


Solution 1 - Dart

Add isScrollControlled = true to BottomSheetDialog it'll allow the bottom sheet to take the full required height which gives more insurance that TextField is not covered by the keyboard.

Add Keyboard padding using MediaQuery.of(context).viewInsets.bottom

Note

If your BottomSheetModel is Column make sure you add mainAxisSize: MainAxisSize.min, otherwise the sheet will cover the whole screen.

Example

 showModalBottomSheet(
    shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.vertical(top: Radius.circular(25.0))),
    backgroundColor: Colors.black,
    context: context,
    isScrollControlled: true,
    builder: (context) => Padding(
      padding: const EdgeInsets.symmetric(horizontal:18 ),
      child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              Padding(
                padding: const EdgeInsets.symmetric(horizontal: 12.0),
                child: Text('Enter your address',
                    style: TextStyles.textBody2),
              ),
              SizedBox(
                height: 8.0,
              ),
              Padding(
                padding: EdgeInsets.only(
                    bottom: MediaQuery.of(context).viewInsets.bottom),
                child: TextField(
                  decoration: InputDecoration(
                    hintText: 'adddrss'
                  ),
                  autofocus: true,
                  controller: _newMediaLinkAddressController,
                ),
              ),

              SizedBox(height: 10),
            ],
          ),
    ));

Please note that:

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

It's not required. It's just that I'm creating a rounded bottom sheet.

padding: MediaQuery.of(context).viewInsets

UPDATED Flutter 2.2 breaks the changes again!” Now you need to give bottom padding once again so keyboard don't overlaps bottomsheet.

Solution 2 - Dart

Just add:

  • isScrollControlled: true to showModalBottomSheet
  • padding: MediaQuery.of(context).viewInsets to widget in builder
  • column/wrap both works
showModalBottomSheet<void>(
  isScrollControlled: true,
  context: context,
  shape: RoundedRectangleBorder(
    borderRadius: BorderRadius.only(
        topLeft: Radius.circular(30.0),
        topRight: Radius.circular(30.0)),
  ),
  builder: (BuildContext context) {
    return Padding(
        padding: MediaQuery.of(context).viewInsets,
        child: Container(
            child: Wrap(
          children: <Widget>[
            TextField(
              decoration: InputDecoration(
                  border: InputBorder.none,
                  hintText: 'Enter a search term'),
            ),
            TextField(
              decoration: InputDecoration(
                  border: InputBorder.none,
                  hintText: 'Enter a search term'),
            ),
            TextField(
              decoration: InputDecoration(
                  border: InputBorder.none,
                  hintText: 'Enter a search term'),
            ),
            TextField(
              decoration: InputDecoration(
                  border: InputBorder.none,
                  hintText: 'Enter a search term'),
            )
          ],
        )));
  },
);

Update Feb 25 2020 better solution

showModalBottomSheet(
 isScrollControlled: true,
 builder: (BuildContext context) {

    return SingleChildScrollView(
      child: Container(
        padding:
            EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
        child: Padding(
          padding: const EdgeInsets.fromLTRB(20.0, 20.0, 20.0, 0.0), // content padding
          child: Form(...)) // From with TextField inside


});

Solution 3 - Dart

In Order to focus on the Keyboard in BottomSheet - Wrap TextField in Padding Widget as like Below e.g Code:

showModalBottomSheet(
              context: context,
              builder: (context) {
                return Container(
                  child: Padding(
                    padding: EdgeInsets.only(
                        bottom: MediaQuery.of(context).viewInsets.bottom),
                    child: TextField(
                      autofocus: true,
                    ),
                  ),
                );
              }); 

Solution 4 - Dart

In the latest version of flutter, you can move your bottomSheet using isScrollControlled property/named parameter. Suppose i have a function(_showModal) which will invoke when a button is pressed. And i define the bottom sheet functionality on that function.

void _showModal() {
  showModalBottomSheet(
    isScrollControlled: true,
    context: context,
    builder: (BuildContext context) {
      return Column(
        children: <Widget>[
          TextField(// your other code),
          SizedBox(height: 5.0),
          TextField(// your other code),
          SizedBox(height: 5.0),
          TextField(// your other code),
        ]
      );
    },
  );
}

Here a ModalBottomSheet will appear but with fullscreen of height. And you don't need that height. So, you need to Column's mainAxisSize to min.

Column(
  mainAxisSize: MainAxisSize.min,
  // your other code
)

Fullscreen of height problem is solved, but ModalBottomSheet doesn't move to top when keyboard is appeared. Ok, to solve this issue you need to set viewInsets bottom padding to your ModalBottomSheet. So to set padding we need to wrap our Column with Container or Padding and then set the padding. The final code will look like this

void _showModal() {
  showModalBottomSheet(
    isScrollControlled: true,
    context: context,
    builder: (BuildContext context) {
      return Container(
        padding: EdgeInsets.only(
          bottom: MediaQuery.of(context).viewInsets.bottom,
        ),
        // You can wrap this Column with Padding of 8.0 for better design
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            TextField(// your other code),
            SizedBox(height: 5.0),
            TextField(// your other code),
            SizedBox(height: 5.0),
            TextField(// your other code),
          ]
        ),
      );
    },
  );
}

Hope your issue is fixed. Thank's 

Solution 5 - Dart

Try this

My Solution is

  • Use isScrollControlled: true
  • Add Padding
    padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom)
    
  • Wrap your layout in SingleChildScrollView

SAMPLE CODE

Future<void> future = showModalBottomSheet(
  context: context,
  isDismissible: true,
  isScrollControlled: true,
  backgroundColor: Colors.white.withOpacity(0.2),
  builder: (context) => SingleChildScrollView(
    child: GestureDetector(
      child: Padding(
        padding: EdgeInsets.only(
          bottom: MediaQuery.of(context).viewInsets.bottom
        ),
        child: Container(
          width: MediaQuery.of(context).size.width,
          height: MediaQuery.of(context).size.height,
          child: Column(
            children: <Widget>[
              // add your widget here
            ],
          ),
        ),
      )
    ),
  )
);

Solution 6 - Dart

Package: https://pub.dev/packages/modal_bottom_sheet

Wrap your widget into Padding and set padding like this ==>

padding: MediaQuery.of(context).viewInsets // viewInsets will decorate your screen

You can use showMaterialModalBottomSheet or showModalBottomSheet or showCupertinoModalBottomSheet

showModalBottomSheet(
        context: context,
        barrierColor: popupBackground,
        isScrollControlled: true, // only work on showModalBottomSheet function
        shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.only(
                topLeft: Radius.circular(borderRadiusMedium),
                topRight: Radius.circular(borderRadiusMedium))),
        builder: (context) =>  Padding(
            padding: MediaQuery.of(context).viewInsets,
            child: Container(
                   height: 400, //height or you can use Get.width-100 to set height
                   child: <Your Widget here>
             ),)),)

before

after

Solution 7 - Dart

I got it fixed by increasing the height of the child widget when the keyboard gets opened. initially value of MediaQuery.of(context).viewInsets.bottom will be 0 it will change when the keyboard gets focused.

showModalBottomSheet<void>(
      enableDrag: true,
      isScrollControlled: true,
      context: context,
      builder: (BuildContext context) {
        return Card(
          color: Colors.white,
          child: Container(
            height: MediaQuery.of(context).size.height / 2 +
                MediaQuery.of(context).viewInsets.bottom,
            child: Column(
              children: <Widget>[
                TextField(),
                TextField(),
              ],
            ),
          ),
        );
      },
    );

Solution 8 - Dart

UPDATED 2021 May flutter 2.2! Now you need to give bottom padding. The below written was a bug.

UPDATED 2020!

This answer is true, but you don't have to give bottom padding now! Find and delete this line:

padding: MediaQuery.of(context).viewInsets

Solution 9 - Dart

For people who can't solve their problem trying all the answers. These answers are correct but not so clear.

When using

MediaQuery.of(context).viewInsets.bottom)

make sure your context variable is using the one provided by bottom sheet builder property.

builder :(**c**)=>MediaQuery.of(**c**)

Solution 10 - Dart

Try this.

showModalBottomSheet(
        isScrollControlled: true,
        context: context,
        builder: (context) {
          return AnimatedPadding(
              padding: MediaQuery.of(context).viewInsets,
              duration: const Duration(milliseconds: 100),
              curve: Curves.decelerate,
              child: Container(
                  child: Wrap(
                children: [
                  TextField(
                    decoration: InputDecoration(labelText: "1"),
                  ),
                  TextField(
                    decoration: InputDecoration(labelText: "2"),
                  ),
                  TextField(
                    decoration: InputDecoration(labelText: "3"),
                  ),
                ],
              )));
        },
      )

Solution 11 - Dart

If you have full screen or fixed size showModalBottomSheet don't use padding it will not solve your problem. Use margin instead of padding like this :

  showModalBottomSheet(
          context: context,
          builder: (context) {
            return Container(
                marign: EdgeInsets.only(
                    bottom: MediaQuery.of(context).viewInsets.bottom),
                child: TextField()
            );
          }); 

Solution 12 - Dart

You should to use this then,

showModalBottomSheet(
    isScrollControlled: true,
    context: context,
    shape: RoundedRectangleBorder(
      // <-- for border radius
      borderRadius: BorderRadius.only(
        topLeft: Radius.circular(10.0),
        topRight: Radius.circular(10.0),
      ),
    ),
    builder: (BuildContext context) {
      return SingleChildScrollView(
        padding:
            EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
        child: drunkenWidget()...

//BTW, Never ever Drink

Solution 13 - Dart

Add this after the last widget of your bottom sheet

Padding(padding: EdgeInsets.only(bottom:MediaQuery.of(context).viewInsets.bottom))

Solution 14 - Dart

After combining different solutions I got this:

if you don't want it to be Full screen and don't want to use the Padding workaround use

  showModalBottomSheet(
      context: context,
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
      ),
      enableDrag: true,
      isDismissible: true,
      useRootNavigator: true,
      builder: (BuildContext ctx) {
        return Scaffold( // use CupertinoPageScaffold for iOS
          backgroundColor: Colors.transparent,
          resizeToAvoidBottomInset: true, // important
          body: SingleChildScrollView(
            child: Form(
              child: Container(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.stretch,
                  children: <Widget>[
                    TextFormField(),
                    TextFormField(),
                  ],
                ),
              ),
            ),
          ),
        );
      },
    );

on Flutter (Channel master, v1.15.3-pre.37, on Mac OS X 10.15.2 19C57, locale en-US)

Solution 15 - Dart

Instead of using builder: (BuildContext context) { } in the builder, use builder: (context) { }

With this solution my modal bottom sheet sticks to the statusbar (acts like Scaffold with resizeToAvoidBottomInset: false) and allows to view all the form fields and scroll through the form if it is still needed to view bottom text fields.

For more details, here's the link from where I found the solution- https://github.com/flutter/flutter/issues/18564#issuecomment-602604778

Solution 16 - Dart

Fount this on github

Padding(
  padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
  child: TextField()
)

Solution 17 - Dart

Wrap the Form with a Scaffold widget, and then wrap the TextFormField with a SingleChildScrollView :


 return Container(
          height: screenHeight * .66,
          child: Scaffold(
             body: Form(
               key: _form,
               child: SingleChildScrollView(
                 child:TextFormField()
               )
              )
             )
           )

Solution 18 - Dart

showModalBottomSheet(
 isScrollControlled: true,
 builder: (BuildContext context) {

    return SingleChildScrollView(
      child: Container(
        padding:
            EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
        child: Padding(
          padding: const EdgeInsets.all(15.0), // content padding
          child: Container())});

Note : This line does all the magic

Solution 19 - Dart

If you still have not found your issue. So I think you have missed in your BuilderContext. Sometimes when you implement modalBottomSheet it will give you only the context parameter. So add context with BuildContext.

 builder: (BuildContext context) {  //-Here is your issue add BuilderContext class name as it as 
          return Padding(
            padding: MediaQuery.of(context).viewInsets,
            child: SingleChildScrollView(
              child: Padding(
                padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
                child: new Container(

Solution 20 - Dart

Simple Solution, you can customize this :

Container(
          margin: EdgeInsets.only(left: 15),
          child: InkWell(
              onTap: () {
                showModalBottomSheet(
                    isScrollControlled : true,
                    context: context,
                    backgroundColor: Colors.transparent,
                    builder: (context) {
                      return Container(
                        padding: EdgeInsets.only(top: 15, left: 15, right: 15, bottom: 10),
                        width: double.infinity,
                        decoration: BoxDecoration(
                          color: AppTheme.leadItemColor1,
                          borderRadius: BorderRadius.only(topLeft: Radius.circular(12), topRight: Radius.circular(12)),
                        ),
                        child: Column(
                          children: [
                            _assignTo(widget.viewModel, context),
                            SizedBox(height: 12,),
                            txtComment(widget.viewModel),
                            SizedBox(height: 12,),
                            CRMButton(
                              title: 'Select',
                              onTap: () async {
                                Navigator.pop(context);
                                await widget.viewModel.updateStatus(7, why: "${ConstantData.lostOptions[_selectedNumber]}");
                              },
                            )
                          ],
                        ),
                      );
                    },
                );
              },
              child: CustomTabBarItem1(
                image: widget.viewModel.leadDetail.success.lStatus == 7 ? 'assets/appimages/LeadDetail/icons-03-01.png' : 'assets/appimages/LeadDetail/icons-04-01.png',
                bottomTitle: 'Lost',
                topTitle: widget.viewModel.leadDetail.success.lStatus > 7 ? 'assets/appimages/LeadDetail/Ellipse [email protected]' : widget.viewModel.leadDetail.success.lStatus == 7 ? 'assets/appimages/LeadDetail/Group 486-1.png' : 'assets/appimages/LeadDetail/[email protected]',
                height : widget.viewModel.leadDetail.success.lStatus == 7 ? "0" : "1",
              )),
        ),

Solution 21 - Dart

showModalBottomSheet(
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(15.0),
      ),
      context: context,
      isScrollControlled: true,
      builder: (builder) {
        return Container(
          height: MediaQuery.of(context).size.height - 40,
          padding: MediaQuery.of(context).viewInsets,
          child: <Your Widget Here>,
        );
      },
    );

enter image description here

Solution 22 - Dart

Just add

if (_isEditing) SizedBox(height: MediaQuery.of(context).viewInsets.bottom),

under the keyboard and hide all other content below the textfield with

if (!_isEditing) Widget(...),

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionManjunath RaoView Question on Stackoverflow
Solution 1 - DartAbedView Answer on Stackoverflow
Solution 2 - DartcapuView Answer on Stackoverflow
Solution 3 - Dartanmol.majhailView Answer on Stackoverflow
Solution 4 - DartRobinView Answer on Stackoverflow
Solution 5 - DartAskNileshView Answer on Stackoverflow
Solution 6 - DartRasel KhanView Answer on Stackoverflow
Solution 7 - DartBRIJESH SAKARIYAView Answer on Stackoverflow
Solution 8 - DartAkbar PulatovView Answer on Stackoverflow
Solution 9 - DartZony ZhaoView Answer on Stackoverflow
Solution 10 - DartBoris KamtouView Answer on Stackoverflow
Solution 11 - DartRahul sharmaView Answer on Stackoverflow
Solution 12 - DartPro CoView Answer on Stackoverflow
Solution 13 - DartYuriView Answer on Stackoverflow
Solution 14 - DarttewshiView Answer on Stackoverflow
Solution 15 - DartPriya SindkarView Answer on Stackoverflow
Solution 16 - DartNipun RavisaraView Answer on Stackoverflow
Solution 17 - DartMFC creationsView Answer on Stackoverflow
Solution 18 - DartAkashGiriView Answer on Stackoverflow
Solution 19 - DartHandyPawanView Answer on Stackoverflow
Solution 20 - DartJawad AbbasiView Answer on Stackoverflow
Solution 21 - DartNecessary LionView Answer on Stackoverflow
Solution 22 - DartwelfvhView Answer on Stackoverflow