Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TextField is hidden by keyboard inside of a Modal Bottom Sheet #18564

Closed
IhorKlimov opened this issue Jun 18, 2018 · 55 comments
Closed

TextField is hidden by keyboard inside of a Modal Bottom Sheet #18564

IhorKlimov opened this issue Jun 18, 2018 · 55 comments
Labels
a: text input Entering text in a text field or keyboard related problems f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels.

Comments

@IhorKlimov
Copy link

IhorKlimov commented Jun 18, 2018

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: ''),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('')),
      body: Container(),
      floatingActionButton: FloatingActionButton(onPressed: () {
        showModalBottomSheet(
            context: context,
            builder: (context) {
              return SizedBox(
                height: 300.0,
                child: Scaffold(
                  body: ListView.builder(
                    itemBuilder: (context, index) {
                      return TextField(
                        decoration:
                            InputDecoration(labelText: index.toString()),
                      );
                    },
                    itemCount: 30,
                  ),
                ),
              );
            });
      }),
    );
  }
}

Result

screenshot_1529336524

Clicked on 4th item

screenshot_1529336530

Perfectly, Modal Bottom Sheet should be lifted up till a TextField is visible, just like FAB

Flutter Doctor

[√] Flutter (Channel master, v0.5.5-pre.46, on Microsoft Windows [Version 10.0.17134.112], locale en-US)
\Error retrieving device properties for ro.product.cpu.abi:
error: closed
                                                                                                                                                                                                       [
!] Android toolchain - develop for Android devices (Android SDK 27.0.3)
    X Android license status unknown.
[√] Android Studio (version 3.1)
[√] VS Code, 64-bit edition (version 1.24.0)
[√] Connected devices (1 available)

! Doctor found issues in 1 category.

@zoechi
Copy link
Contributor

zoechi commented Jun 18, 2018

Please add the output of flutter doctor

@IhorKlimov
Copy link
Author

@zoechi Done, also updated the code. TextField is visible if the bottom sheet is high enough, else it's covered, like on a screenshot

@zoechi zoechi added framework flutter/packages/flutter repository. See also f: labels. f: material design flutter/packages/flutter/material repository. labels Jun 18, 2018
@zoechi
Copy link
Contributor

zoechi commented Jun 18, 2018

@goderbauer

@andrelsmoraes
Copy link

I'm not sure if it's related, but take a look at this gist: https://gist.github.com/andrelsmoraes/9e4af0133bff8960c1feeb0ead7fd749

Behavior after fix: https://youtu.be/ESiCr0juFG8

@mohith7548
Copy link

Any fixes? The problem still persists. Please do Fix it because we Love #Flutter.

@IhorKlimov
Copy link
Author

IhorKlimov commented Jul 9, 2018

@mohith7548 As of now, make sure your ModalBottomSheet is high enough (at least keyboard height + TextView height), then TextField will be visible. Else don't use MBS for your input. Also, try andrelsmoraes' solution

@mohith7548
Copy link

Hey did you use showDialog method. When there is a text field in it. The keyboard automatically shifts the dialog up and appears on screen when the text field is tapped. Why it doesn't happen in case of ModalBottom sheet. This is a bug and it needs to be fixed soon

@lucasjinreal
Copy link

@andrelsmoraes Could u provide more codes for your youtube demo? This is exactly what I want achieve.

@andrelsmoraes
Copy link

@jinfagang Added some comments in my gist, please check it out and tell me if you need more details.

@zoechi zoechi added the a: text input Entering text in a text field or keyboard related problems label Jul 15, 2018
@lukepighetti
Copy link

Please fix this. See #20638

@jbg
Copy link

jbg commented Sep 10, 2018

This may not work for all situations, but I have a modalBottomSheet that contains only a TextField, and it was quite simple to make it move up with the keyboard:

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

@shinayser
Copy link

None update on that yet ?

@crimsonsuv
Copy link

I made a modification and the issue is fixed you can check it out here: https://gist.github.com/crimsonsuv/b25d5ebd04236f9be2aa66accba19446

@zoechi zoechi added this to the Goals milestone Nov 29, 2018
@lifenautjoe
Copy link

lifenautjoe commented Dec 16, 2018

Hi @crimsonsuv , your temporarily solution almost worked perfectly. The modal is not dismissed by clicking outside the content anymore 😢 .

Edit:

Just changed

bool get barrierDismissible => false;

to true.

@diegopap

This comment has been minimized.

@HansMuller
Copy link
Contributor

When the keyboard appears, the body of the Scaffold that contains the input focus is resized. So to ensure that the focused list item scrolls into view when the keyboard appears it made sense to put the bottom sheet in a Scaffold. Unfortunately, fixing the scaffold's height to 300 prevented it from being resized.

Here's a version of the example (I've just removed the SizedBox constraint) that does work:

https://gist.github.com/HansMuller/9c0c89623650d55e84ba55d78f384fad

@creativefull
Copy link

just add resizeToAvoidBottomPadding: true in scaffold widget

@BANG88
Copy link

BANG88 commented May 13, 2019

I hope the BottomSheet can scroll to the focused TextField automatically.

@nishanthoblirajan
Copy link

nishanthoblirajan commented May 26, 2019

Hi, I was looking around for the solution for a while. I was use resizeToAvoidBottomInset: true, inside the Scaffold Widget. I also have my forms under the SingleChildScrollView. Here is my example code for login

return Scaffold(
      resizeToAvoidBottomInset: true,
      appBar: AppBar(
        title: Text('$title'),
      ),
      body: SingleChildScrollView(
        child: Container(
          child: Column(
            children: <Widget>[
              login()
            ],
          ),
        ),
      ),
    );

@raajeshmani
Copy link

Hi, I found the solution to be scattered.

I fixed this issue where my the bottom Sheet expands towards top dynamically when input with multiple lines.
Thanks to @jbg. I used @jbg way of implementing the padding

I tried @andrelsmoraes gist but i couldn't edit shapes in that.

Finally without using fully customised bottom_sheet.dart,

Changing the value of 9.0 to 10.0 in bottom_sheet.dart , I achieved what i actually wanted.
maxHeight: isScrollControlled ? constraints.maxHeight : constraints.maxHeight * 9.0 / 16.0,

Thanks to @crimsonsuv , setting the maxHeight this way gives full screen on demand.
maxHeight: constraints.maxHeight

@drewpayment
Copy link

Not sure about all of the repercussions yet, but this is the solution I came up with for now.

https://gist.github.com/drewpayment/08e963f8cf0fa715711408a2bf33d899

@kaifiappsmaven
Copy link

bug and it need

Is this fixed now as I am stuck with it and got no solution so far.
Can you please update.

@cgowthamanmca
Copy link

cgowthamanmca commented Sep 27, 2019

showModalBottomSheet(
            isScrollControlled: true, // Important: Makes content maxHeight = full device height
            context: context,
            builder: (context) {
              // Does not work
              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"),
                      ),
                    ],
                  )));

@devjeff
Copy link

devjeff commented Nov 16, 2019

Thank you very much, this was the only solution that worked for me in case of a non-scrollable content on the bottom sheet.

@omarmir
Copy link

omarmir commented Dec 12, 2019

This may not work for all situations, but I have a modalBottomSheet that contains only a TextField, and it was quite simple to make it move up with the keyboard:

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

Yep worked!

@lukepighetti
Copy link

lukepighetti commented Feb 9, 2020

I'm going to say this issue should not be closed. I have a modal bottom sheet with a text field and there is plenty of room on the screen for it to move up but it does not. If Material spec says that no bottom sheets should have editable text then I'd be curious to know how material spec says we should handle these types of scenarios.

ezgif-1-ba30f5c5ef26

@lukepighetti
Copy link

@HansMuller Requesting that this gets reopened

@tewshi
Copy link

tewshi commented Feb 14, 2020

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)

@ariefannur
Copy link

image
image

I was fixed, let's check it, It's very simple::
showModalBottomSheet(
isScrollControlled: true,
builder: (BuildContext context) {
return SingleChildScrollView(
child:Container(
padding:
EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
child: AnyChild(),
)
);
});

use context instead BuildContext so the code

showModalBottomSheet(
isScrollControlled: true,
context: context,
builder: (context) {
return SingleChildScrollView(
child:Container(
padding:
EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
child: AnyChild(),
)
);
});

@jasprit
Copy link

jasprit commented Apr 18, 2020

this link works super fine try this one
https://gist.github.com/denniske/d00cd0ffa44b1d7a14fccaece96a1fbc

@ChrisMukasa
Copy link

image
image

I was fixed, let's check it, It's very simple::
showModalBottomSheet(
isScrollControlled: true,
builder: (BuildContext context) {
return SingleChildScrollView(
child:Container(
padding:
EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
child: AnyChild(),
)
);
});

Work like a charm, you save my day. 👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏👏

@lucasarrudadev
Copy link

I'm not sure if it's related, but take a look at this gist: https://gist.github.com/andrelsmoraes/9e4af0133bff8960c1feeb0ead7fd749

Behavior after fix: https://youtu.be/ESiCr0juFG8

Hi @andrelsmoraes , if I use the key property in the TextField a glitch happens, if possible, could you check it and fix it ?

@BlackStriker99
Copy link

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

@AdamTrybus
Copy link

With height in container it doesnt work

@cuong292
Copy link

none of this work for me.working on Samsung Galaxy S8 flutter sdk: ">=2.7.0 <3.0.0".there's no change ( which i though must have ) when the keyboard is opened

@jaganmohang
Copy link

jaganmohang commented Sep 17, 2020

@cuong292 This solution worked for me on Samsung Galaxy S7, calculating the bottom padding during runtime when keyboard is open else default padding if keyboard is not open.
return SingleChildScrollView(
child: Container(
padding: EdgeInsets.only(
bottom: (MediaQuery.of(context).viewInsets.bottom == 0)
? 50.0
: MediaQuery.of(context).viewInsets.bottom,
top: 16.0,
left: 16.0,
right: 16.0),
child: Column(
),
),
);
along with isScrollControlled: true,

@cuong292
Copy link

@jaganmohang it's feel like it's always padding 50 from bottom or padding equal to viewInsets.bottom.that doesnt make sense i guess.so i'm change to dialog

@jaganmohang
Copy link

@jaganmohang it's feel like it's always padding 50 from bottom or padding equal to viewInsets.bottom.that doesnt make sense i guess.so i'm change to dialog

default bottom padding 50 is my requirement. And since the content is inside the SingleChildScrollView there will be no issue. Anyway you already opted for a different solution so no issues.

@PriyaSindkar
Copy link

image
image
I was fixed, let's check it, It's very simple::
showModalBottomSheet(
isScrollControlled: true,
builder: (BuildContext context) {
return SingleChildScrollView(
child:Container(
padding:
EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
child: AnyChild(),
)
);
});

use context instead BuildContext so the code

showModalBottomSheet(
isScrollControlled: true,
context: context,
builder: (context) {
return SingleChildScrollView(
child:Container(
padding:
EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
child: AnyChild(),
)
);
});

Thanks a lot.. this helped my use case (form with 3-4 TextFormField, including a comments box). With your solution my modal bottom sheet sticks to the statusbar (acts like Scaffold with resizeToAvoidBottomInset: false) and allows to view the form fields and scroll through the form if it is still needed to view bottom text fields.

@AliEasy
Copy link

AliEasy commented Nov 14, 2020

I was fixed, let's check it, It's very simple::
showModalBottomSheet(
isScrollControlled: true,
builder: (BuildContext context) {
return SingleChildScrollView(
child:Container(
padding:
EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
child: AnyChild(),
)
);
});

setting height for Container will prevent the fix

@suyog06
Copy link

suyog06 commented Nov 28, 2020

This may not work for all situations, but I have a modalBottomSheet that contains only a TextField, and it was quite simple to make it move up with the keyboard:

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

What if I have a textfield and a submit button with it?

@suyog06
Copy link

suyog06 commented Nov 28, 2020

This is how I tackled it!!
showModalBottomSheet(
context: context,
builder: (context) => AddTaskScreen());
},

The AddTaskScreen class

class AddTaskScreen extends StatelessWidget {
@OverRide
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: true,
body: Container(
color: Color(0xFF757575),
child: SingleChildScrollView(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(topLeft: Radius.circular(20.0), topRight: Radius.circular(20.0)),
color: Colors.white,
),
padding: EdgeInsets.all(45.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
'Add Task',
style: TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.w500,
color: Colors.lightBlueAccent,
),
),
TextField(
autofocus: true,
textAlign: TextAlign.center,
cursorColor: Colors.lightBlueAccent,

            ),
            SizedBox(height: 10.0,),
            FlatButton(
              color: Colors.lightBlueAccent,
              onPressed: (){

              },
              child: Padding(
                padding: EdgeInsets.all(20.0),
                child: Center(
                  child: Text(
                    'Add',
                    style: TextStyle(
                      color: Colors.white,
                      fontSize: 20.0,
                    ),
                  ),
                ),
              )
            )
          ],
        ),
      ),
    ),
  ),
);

}
}

@agersea
Copy link

agersea commented Dec 27, 2020

Scaffold did not work for me as it caused my modal bottom sheet to top align.

Instead, I used a combination of SingleChildScrollView and dynamic padding based on the viewInsets.bottom.

  showModalBottomSheet(
    backgroundColor: Colors.transparent,
    builder: (ctx) => ModalBottomSheet(),
    context: ctx,
    isScrollControlled: true,
  );
  
  // Modal Bottom Sheet logic
  double bottomPadding(BuildContext ctx) {
    var result = MediaQuery.of(ctx).viewInsets.bottom ?? 0;
    if (result == 0) result = 10;
    return result;
  }
  
  @override
  Widget build(BuildContext ctx) {
    return SingleChildScrollView(
      child: Container(
        child: Padding(
          padding: EdgeInsets.fromLTRB(20, 30, 20, bottomPadding(ctx)),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              ...
            ],
          ),
        ),
      ),
    );
  }

@vantrung8794
Copy link

My solution is to put a child widget inside Scaffold and this worked.

@hasitha3rd
Copy link

none of these suggestions worked. :(

@IkhwanSI13
Copy link

isScrollControlled and padding solve this problem. For everyone still having this problem, make sure you provide the correct context to showModalBottomSheet

@github-actions
Copy link

This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jul 30, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
a: text input Entering text in a text field or keyboard related problems f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels.
Projects
None yet
Development

Successfully merging a pull request may close this issue.