14

I have some widgets inside of a Stack.

When the keyboard appears, the widgets in the Stack that were explicitly Positioned at the bottom using Positioned(bottom: 0) widget, get shifted to the top of keyboard.

How can I prevent this, and make some widgets retain their position, whether or not the keyboard is in the view?

For example, I want the "Offline Mode" label to be under the keyboard, not over it.

enter image description here

Here is a rough sketch of what this page's widgets look like:

Scaffold(
   body: Stack(
       children: [
           LoginImage(),
           LoginForm(),
           ConnectedToInternet(),
       ],
   ),
)

Here is what the ConnectedToInternet widget looks like-

Positioned(
  bottom: 0,
  child: Container(
    width: MediaQuery.of(context).size.width,
    color: Colors.grey[900],
    child: Padding(
      padding: const EdgeInsets.all(4.0),
      child: Center(
        child: Text(
          "Offline mode",
          style: TextStyle(color: Colors.white, fontSize: 12),
        ),
      ),
    ),
  ),
);
Dev Aggarwal
  • 7,627
  • 3
  • 38
  • 50

5 Answers5

22

The way I solve this problem by setting resizeToAvoidBottomInset: false,

Scaffold(
  appBar: AppBar()
  drawer: AppDrawer(),
  resizeToAvoidBottomInset: false,
  body: Stack(
    children:[
          // widgets 
        ]
       )
 )
Avnish Nishad
  • 1,634
  • 1
  • 17
  • 18
11

I faced similar problem while positioning a background image with Positioned(bottom: 0.0) widget in the stack. When the keyboard appeared the image shifted to the top of the keyboard. Solved the problem by doing the following.

Widget build(BuildContext context) {
    return Container(
      color: Colors.white,
      child: Stack(
        children: <Widget>[
          _bottomImageStack(),
          Scaffold(
            appBar: AppBar(),
            backgroundColor: Colors.transparent,
            body: _mainBody(),
          ),
        ],
      ),
    );
  }

Widget _bottomImageStack() {
    return Positioned(
      bottom: 0.0,
      child: Container(
        height: 235,
        width: MediaQuery.of(context).size.width,
        child: SvgPicture.asset(
          AssetPaths.LOGIN_SCREEN_BG_SVG,
          alignment: Alignment.bottomRight,
        ),
      ),
    );
  }

Widget _mainBody() {
    return ListView(
      children: <Widget>[..Other widgets go here..],
    );
  }
zfnadia
  • 331
  • 3
  • 8
  • This worked for me. Thank you so much. The only change I made was that I had to place my Positioned Widget after the Scaffold in the stack because of my use case. Thanks a lot! – Ayush Shekhar Oct 03 '19 at 12:10
  • Why r u so smart dude, this helps my final year project alot – Son Nguyen Oct 25 '21 at 14:32
0

You Can Place Your stack as a child of a listview, this way the keyboard won't shift your widgets to the top:

     Scaffold(
       body: ListView(
               children: <Widget>[
                 Stack(
                 children: [
                    LoginImage(),
                    LoginForm(),
                    ConnectedToInternet(),
                 ],
               ),
             ]
           ),
         )
Mazin Ibrahim
  • 7,433
  • 2
  • 33
  • 40
  • That won't exactly work because the login form has ListView inside it as well. The use of `Expanded` or `shrinkwrap` won't fix the `BoxConstraints forces an infinite height.` message either. – Dev Aggarwal Feb 22 '19 at 13:43
0

Try to set height of Container to match page height like this:

Positioned(
  bottom: 0,
  child: Container(
    width: MediaQuery.of(context).size.width,
    height: MediaQuery.of(context).size.height,
    color: Colors.grey[900],
    child: Padding(
      padding: const EdgeInsets.all(4.0),
      child: Center(
        child: Text(
          "Offline mode",
          style: TextStyle(color: Colors.white, fontSize: 12),
        ),
      ),
    ),
  ),
);

Also you may need to change position in stack like this:

Scaffold(
   body: Stack(
       children: [
           LoginImage(),
           ConnectedToInternet(),
           LoginForm(),
       ],
   ),
)
Djanko
  • 80
  • 1
  • 5
0

You could use Positioned(top) to solve it if you can specify the height of your widget. ConnectedToInternet could look like:

var widgetHeight = 40.0; //replaced with your height
Positioned(
  top: MediaQuery.of(context).size.height - widgetHeight,
  child: Container(
    height: widgetHeight,
    child: SizedBox(height: widgetHeight), //replaced with your widget
  )
)
Whis
  • 1
  • 2