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

KeyboardResizeWidgetTextfieldFlutter

Keyboard Problem Overview


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.

Keyboard Solutions


Solution 1 - Keyboard

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

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

Set resizeToAvoidBottomInset to false instead of resizeToAvoidBottomPadding which is deprecated.

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

Solution 4 - Keyboard

My approach is to use SingleChildScrollView with the ClampingScrollPhysics physics.

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

Solution 5 - Keyboard

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

Solution 6 - Keyboard

The best solution to avoid resizing widgets and also focus on the text field is to use SingleChildScrollView() with ClampingScrollPhysics() physics. Also, remember to set height for its child (ex: use container()), so you can use your widgets through Column():

return Scaffold(
   body: SingleChildScrollView(
      physics: ClampingScrollPhysics(),
      child: Container(
         height: size.height,
         child: Column(
            children:[
               TextFormField()
            ],
         ),
      ),
   ),
);

Solution 7 - Keyboard

Method 1: Remove android:windowSoftInputMode="adjustResize" from AndroidManifest.xml file (Otherwise it will override flutter code) and add resizeToAvoidBottomPadding: false in Scaffold like below:

Scaffold(
      resizeToAvoidBottomPadding: false,
      appBar: AppBar()
)

Method 2(Not Recommended): Just Add android:windowSoftInputMode="stateVisible" in android AndroidManifest.xml in activity it will only work for Android an Not for IOS like.

<activity
       ...
        android:windowSoftInputMode="stateVisible">

Note: Don't set it to android:windowSoftInputMode="adjustResize"

Solution 8 - Keyboard

Setting the value false for resizeToAvoidBottomInset worked fine for me.

Also, resizeToAvoidBottomPadding worked fine for me. You can use either one.

Solution 9 - Keyboard

Depending on the use case you could also consider using a listview. That would ensure that the contents scroll when there is not enough room. As an example, you can look at the textfield demo in the gallery app

Solution 10 - Keyboard

Feature:

  • Background image does not resize when keyboard is opened
  • Ability to scroll elements hidden behind the keyboard
import 'package:flutter/material.dart';

SizedBox addPaddingWhenKeyboardAppears() {
  final viewInsets = EdgeInsets.fromWindowPadding(
    WidgetsBinding.instance!.window.viewInsets,
    WidgetsBinding.instance!.window.devicePixelRatio,
  );

  final bottomOffset = viewInsets.bottom;
  const hiddenKeyboard = 0.0; // Always 0 if keyboard is not opened
  final isNeedPadding = bottomOffset != hiddenKeyboard;

  return SizedBox(height: isNeedPadding ? bottomOffset : hiddenKeyboard);
}

/// The size of the screen.
class ScreenSizeService {
  final BuildContext context;

  const ScreenSizeService(
    this.context,
  );

  Size get size => MediaQuery.of(context).size;
  double get height => size.height;
  double get width => size.width;
}

class LoginPage extends StatelessWidget {
  final _imageUrl =
      'https://images.unsplash.com/photo-1631823460501-e0c045fa716f?ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwyNHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60';

  const LoginPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final screenWidth = ScreenSizeService(context).width;
    final screenHeight = ScreenSizeService(context).height;

    return Scaffold(
      resizeToAvoidBottomInset: false,
      body: Container(
        decoration: BoxDecoration(
          image: DecorationImage(
            image: NetworkImage(_imageUrl),
            fit: BoxFit.cover,
          ),
        ),
        child: SingleChildScrollView(
          child: ConstrainedBox(
            constraints: BoxConstraints(
              minWidth: screenWidth,
              minHeight: screenHeight,
            ),
            child: Column(
              children: [
                ...List.generate(6, (index) {
                  return Column(
                    children: [
                      Container(
                        height: 60,
                        width: double.maxFinite,
                        color: Colors.pink[100],
                        child: Center(child: Text('$index')),
                      ),
                      const SizedBox(height: 40),
                    ],
                  );
                }),
                Container(color: Colors.white, child: const TextField()),
                addPaddingWhenKeyboardAppears(),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

Solution 11 - Keyboard

Well I think if we implement @Aman's solution it will make our app behaves ugly as when the keyboard appears, it will not adjust our viewport of the screen as per available height and it will make out other fields hide behind the keyboard. So I would suggest useSingleChildScrollView instead.

Wrap your code with SingleChildScrollView as given below,

 return new Container(
  child: SingleChildScrollView(
    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,
      ),
    ],
  ),
 ),
);

Solution 12 - Keyboard

For me changing below item property from true to false

<item name="android:windowFullscreen">false</item>

in file

android/app/src/main/res/values/styles.xml

has made Flutter drag all page content upwards on input focus

Flutter drag all page content upwards on input focus

Solution 13 - Keyboard

This is the perfect solution that gives you the ability to have a full-screen column inside of a SingleChildScrollView. This allows you to create a perfect layout for all screen sizes + the ability to have a scrollable screen that only scrolls if you open the keyboard or if the screen overflows after rendering (e.g. text input field validation)

class PerfectFullScreen extends StatelessWidget {
  const PerfectFullScreen({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return SafeArea(
        child: Scaffold(
      backgroundColor: Theme.of(context).backgroundColor,
      appBar: AppBar(),
      body: Builder(
        builder: (context) => SingleChildScrollView(
            child: ConstrainedBox(
                constraints: BoxConstraints(
                    minHeight: MediaQuery.of(context).size.height -
                        (MediaQuery.of(context).padding.top + kToolbarHeight)),
                child: IntrinsicHeight(
                    child: Column(
                  children: [
                    Container(
                      height: randomImageHeight,
                      child: Image.asset(
                        "assets/images/change_password.png",
                        fit: BoxFit.cover,
                      ),
                    ),
                    Expanded(
                        child: WidgetThatShouldTakeRemainingSpace() )
                  ],
                )))),
      ),
    ));
  }
}

The important part is the ConstrainedBox with the correct BoxConstraints and the InstrinsicHeight Widget.

PS: (MediaQuery.of(context).padding.top + kToolbarHeight) == Height of the Appbar

Solution 14 - Keyboard

Might Be too late to answer but the following worked for me

Scaffold(
  body: SingleChildScrollView(
    physics: ClampingScrollPhysics(parent: NeverScrollableScrollPhysics()),
      child: Container(

Clamping will auto scroll to make textfield visible, its parent NeverScrollable will not allow the user to scroll.

Solution 15 - Keyboard

I was facing the same issue and I started to try random solutions to fix it and suddenly this fixed it. enter image description here

Wrap the main parent container within a SingleChildScrollView() and give it the device height i.e device_height = MediaQuery.of(context).size.height.

This will make the entire page scrollable but does not resize any widget.

Solution 16 - Keyboard

This will scroll with your keypad and collapse size when keyboard disappears.

showModalBottomSheet(
      isScrollControlled: true,
      context: context,
      builder: (context) {
        return Padding(
            padding: MediaQuery.of(context).viewInsets,
            child:SingleChildScrollView(
            physics: ClampingScrollPhysics(),
            child: Container(.......)));

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
QuestionMaryView Question on Stackoverflow
Solution 1 - KeyboardShady AzizaView Answer on Stackoverflow
Solution 2 - KeyboardDuncan JonesView Answer on Stackoverflow
Solution 3 - KeyboardArtiomLKView Answer on Stackoverflow
Solution 4 - KeyboardDenView Answer on Stackoverflow
Solution 5 - Keyboardbirca123View Answer on Stackoverflow
Solution 6 - KeyboardSamanView Answer on Stackoverflow
Solution 7 - Keyboardyatin deokarView Answer on Stackoverflow
Solution 8 - KeyboardAmimul IhsanView Answer on Stackoverflow
Solution 9 - KeyboardaptikView Answer on Stackoverflow
Solution 10 - KeyboardYauheni PrakapenkaView Answer on Stackoverflow
Solution 11 - KeyboardDeepak JhaView Answer on Stackoverflow
Solution 12 - KeyboardJaveed IshaqView Answer on Stackoverflow
Solution 13 - KeyboardPumuckeloView Answer on Stackoverflow
Solution 14 - KeyboardPhani PavanView Answer on Stackoverflow
Solution 15 - KeyboardRudr ThakurView Answer on Stackoverflow
Solution 16 - Keyboarduser18530386View Answer on Stackoverflow