When the keyboard appears, the Flutter widgets resize. How to prevent this?

165,815

Solution 1

Updated Answer

resizeToAvoidBottomPadding is now deprecated.

The updated solution is to set resizeToAvoidBottomInset property to false.


Original Answer

In your Scaffold, set resizeToAvoidBottomPadding property to false.

Solution 2

Most other answers suggest using resizeToAvoidBottomPadding=false. In my experience this allows the keyboard to cover up text fields if they are underneath where the keyboard would appear.

My current solution is to force my column to be the same height as the screen, then place it in a SingleChildScrollView so that Flutter automatically scrolls my screen up just enough when the keyboard is used.

Widget build(BuildContext context) {
  return Scaffold(
    body: SingleChildScrollView(
      physics: NeverScrollableScrollPhysics(),
      child: ConstrainedBox(
        constraints: BoxConstraints(
          minWidth: MediaQuery.of(context).size.width,
          minHeight: MediaQuery.of(context).size.height,
        ),
        child: IntrinsicHeight(
          child: Column(
            mainAxisSize: MainAxisSize.max,
            children: <Widget>[
              // CONTENT HERE
            ],
          ),
        ),
      ),
    ),
  );
}

I use NeverScrollableScrollPhysics so that the user cannot scroll around themselves.

Solution 3

Set resizeToAvoidBottomInset to false instead of resizeToAvoidBottomPadding which is deprecated.

    return Scaffold(
      resizeToAvoidBottomInset : false,
      body: YourWidgets(),
    );

Solution 4

My approach is to use SingleChildScrollView with the ClampingScrollPhysics physics.

SingleChildScrollView(
  physics: ClampingScrollPhysics(),
  child: Container(),
)

Solution 5

My suggestion is to use resizeToAvoidBottomInset: false anyway to prevent widgets from resizing if the keyboard suddenly appears on the screen. For example, if a user uses Facebook chat heads while in your app.

To prevent the keyboard from overlaying widgets, on screens where you need it, I suggest the following approach, where is the height of SingleChildScrollView reduced to the height of the available space. In this case, SingleChildScrollView also scrolls to the focused widget.

final double screenHeight = MediaQuery.of(context).size.height;
final double keyboardHeight = MediaQuery.of(context).viewInsets.bottom;
return Scaffold(
  resizeToAvoidBottomInset: false,
  body: SizedBox(
    height: screenHeight - keyboardHeight,
    child: SingleChildScrollView(
      child: Column(
        children: [
          const SizedBox(height: 200),
          for (var i = 0; i < 10; i++) const TextField()
        ],
      ),
    ),
  ),
);
Share:
165,815

Related videos on Youtube

Mary
Author by

Mary

Updated on March 29, 2022

Comments

  • Mary
    Mary about 2 years

    I have a Column of Expanded widgets like this:

     return new Container(
          child: new Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: <Widget>[
              new Expanded(
                flex: 1,
                child: convertFrom,
              ),
              new Expanded(
                flex: 1,
                child: convertTo,
              ),
              new Expanded(
                flex: 1,
                child: description,
              ),
            ],
          ),
        );
    

    It looks like this:

    enter image description here

    convertFrom, includes a TextField. When I tap on this text field, the Android keyboard appears on the screen. This changes the screen size, so the widgets resize like this:

    enter image description here

    Is there a way to have the keyboard "overlay" the screen so that my Column doesn't resize? If I don't use Expanded widgets and hardcode a height for each widget, the widgets don't resize, but I get the black-and-yellow striped error when the keyboard appears (because there isn't enough space). This also isn't flexible for all screen sizes.

    I'm not sure if this is an Android-specific or Flutter-specific.

  • Nathan Bird
    Nathan Bird about 6 years
    Is there any way to produce a similar effect to android:windowSoftInputMode="adjustPan"? If I add resizeToAvoidBottomPadding to the scaffold it ends up covering the TextField.
  • Boy
    Boy about 6 years
    But this still doesn't make the TextField you selected to be visible, the keyboard will still overlap it. You have to scroll it yourself. Not used to as an Android developer / user
  • Shady Aziza
    Shady Aziza almost 6 years
    I do not know about android, but it is generally a good practice to wrap your layout inside a ListView in this case
  • stuckedoverflow
    stuckedoverflow over 5 years
    @KishanVyas same with me image is gone.
  • Val
    Val about 5 years
    @aziza Solid answer
  • ArtiomLK
    ArtiomLK almost 5 years
    resizeToAvoidBottomPadding is deprecated, use resizeToAvoidBottomInset check this Answer
  • Bisclavret
    Bisclavret almost 4 years
    This does nothing of the sort suggested in the question. All widgets underneath the keyboard still resize.
  • Sajad Jaward
    Sajad Jaward almost 4 years
    I tried your way without NeverScrollableScrollPhysics and all looks fine except for user can try to swipe up and down and they can see the overscroll glow. When I use the NeverScrollableScrollPhysics it gives me the same behavior as resizeToAvoidBottomInset
  • Shubham Sharma
    Shubham Sharma almost 4 years
    resizeToAvoidBottomPadding removes the default functionality to keep UI above the keyboard so if you set it false then UI will be covered by the keyboard checkout solution here stackoverflow.com/a/62245570/9955978
  • ArtiomLK
    ArtiomLK almost 4 years
    They are the same answers @Ojonugwa, maybe the editor updated the accepted answer after I posted mine so now the difference is that mine includes an example?
  • VLXU
    VLXU over 3 years
    Set the primary property to false.
  • Christian X
    Christian X over 3 years
    you are aware of the fact that this will immediately throw a mass of errors because the expanded widget will have infinite space to fill given by the singlechildscrollview
  • Christian X
    Christian X over 3 years
    this will be only working for android as it appears...
  • hewa jalal
    hewa jalal over 3 years
    but using NeverScrollableScrollPhysics makes it so it doesn't get scrolled up with the keyboard too.
  • Supun Dewapriya
    Supun Dewapriya over 3 years
    remove, NeverScrollableScrollPhysics() line of the SingleChildScrollView Widget, or replace ClampingScrollPhysics() to there. then it will scroll up with the keyboard.
  • henriqueor
    henriqueor about 3 years
    I had the same behavior with or without the IntrinsicHeight Widget. The documentation says to avoid using it: "This class is relatively expensive. Avoid using it where possible."
  • Nijat Mursali
    Nijat Mursali almost 3 years
    This did not help in my case.
  • geisterfurz007
    geisterfurz007 over 2 years
    From the docs of IntrinsicHeight (emphasis mine): "This class is relatively expensive, because it adds a speculative layout pass before the final layout phase. Avoid using it where possible. In the worst case, this widget can result in a layout that is O(N²) in the depth of the tree.". Advertising it as perfect using a widget that is recommended to be avoided if possible with plenty alternatives around might be a bit misleading.
  • geisterfurz007
    geisterfurz007 over 2 years
    Posting screenshots of code is discourated as it doesn't allow members to copy and play around with it themselves in easy fashion.
  • Rudr Thakur
    Rudr Thakur over 2 years
    Hey, I was new to stackoverflow that time and I did not know how to add code to your answer. I would have edited the answer later, but I do not have the code anymore.
  • JChen___
    JChen___ over 2 years
    SingleChildScrollView perfectly solved my problem that keyboard cover my TextField which lead to can not see what is inputing.
  • DarkMikey
    DarkMikey over 2 years
    You cannot use either one, the latter is deprecated with Flutter v1.1.9. docs.flutter.dev/release/breaking-changes/…
  • West
    West over 2 years
    Would be more useful if you mentioned where that goes
  • Amimul Ihsan
    Amimul Ihsan over 2 years
    @West You can set the value to inside Scaffold Widget
  • Amimul Ihsan
    Amimul Ihsan over 2 years
    @DarkMikey You are right. Now, you need to set the value for resizeToAvoidBottomInset.
  • Anteino
    Anteino about 2 years
    Yes! This solved the issue for me perfectly, thanks :)
  • Amimul Ihsan
    Amimul Ihsan about 2 years
    @Anteino You are most welcome. Keep rocking with Flutter and share your learning.
  • Zahra
    Zahra about 2 years
    You saved my day :D