Center widget vertically inside a SingleChildScrollView

FlutterDartScrollview

Flutter Problem Overview


I'm new to Flutter so I train myself by making a simple form. I realized while I was debugging on my iPhone the virtual keyboard triggered an error: "A RenderFlex overflowed by 29 pixels on the bottom". I fixed this issue by wrapping my Container inside a SingleChildScrollView.

The problem now is my Column's content is no longer centered. I can't figure out why ...

Here's my code to help you to understand :

List<Widget> _buildBody() {
    var listWidget = List<Widget>();

    SingleChildScrollView singleChild = SingleChildScrollView(
        padding: EdgeInsets.only(top: 1.0),
        child: Container(
          alignment: Alignment.center,
          margin: EdgeInsets.all(30.0),
          padding: EdgeInsets.all(10.0),
          child: Form(
            key: _formKey,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Container(
                  margin: EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 50.0),
                  child: Image.asset(
                    'assets/github.png',
                    width: 100.0,
                    height: 100.0,
                  ),
                ),
                Container(
                    margin: EdgeInsets.only(bottom: 10.0),
                    child: TextFormField(
                        controller: _usernameController,
                        autofocus: true,
                        decoration: InputDecoration(
                            hintText: 'Username',
                            suffixIcon: Icon(Icons.account_circle)))),
                Container(
                  child: TextFormField(
                    controller: _passwordController,
                    obscureText: true,
                    decoration: InputDecoration(
                        hintText: 'Password', suffixIcon: Icon(Icons.vpn_key)),
                  ),
                ),
                Container(
                  margin: EdgeInsets.only(top: 10.0),
                  child: RaisedButton(
                    splashColor: Colors.greenAccent,
                    color: Colors.blue,
                    child: Text('Submit'),
                    onPressed: () {
                      _handleSubmit();
                    },
                  ),
                )
              ],
            ),
          ),
        ));

    listWidget.add(singleChild);

    if (_requesting) {
      var modal = new Stack(
        children: [
          new Opacity(
            opacity: 0.3,
            child: const ModalBarrier(dismissible: false, color: Colors.grey),
          ),
          new Center(
            child: new CircularProgressIndicator(),
          ),
        ],
      );
      listWidget.add(modal);
    }

    return listWidget;
  }

  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Github Login'),
        ),
        body: Stack(
          children: _buildBody(),
        ));
  }

I added the property "mainAxisAlignment: MainAxisAlignment.center" to my Column. It worked well before I wrapped it into the SingleChildScrollView.

If someone could help me and explain me why it doesn't work anymore I would really appreciated it :)

Flutter Solutions


Solution 1 - Flutter

ArtiomLK Suggested a solution in comments which helped me:

wrap SingleChildScrollView in a Center. The widgets tree is:

Center( child: SingleChildScrollView( child: Column(...)))

None of the others helped.

Solution 2 - Flutter

Solution:

Put your top level Stack inside Center widget.

body: Center(child: Stack(
      children: _buildBody(),
    )));

Tip to debug:

Use Flutter Inspector to find where the layout is going wrong.

I edited your code a bit(to make to work in my local) and then I inspected. It showed like below

enter image description here

We have a Stack and SingleChildScrollView as per code(refer to the right side of the diagram where the stack of widgets are displayed). As size is determined by SingleChildScrollView(contents inside it), Stack occupies only a little space and by default, it aligned at top. So put it under Center, the whole Stack view will come in the center.

Solution 3 - Flutter

You can use "Center" widget like as

return Center( child: SingleChildScrollView() )

Solution 4 - Flutter

There's a section about it in the official docs:

> Using SingleChildScrollView with a Column

Source: https://api.flutter.dev/flutter/widgets/SingleChildScrollView-class.html

However I found that using a combination of the above worked better. Namely confining the Column to the minimum size possible (MainAxisSize.min). This should be fine, as the SingleChildScrollView will take up as much space as is possible on screen, before scrolling can happen.

Widget _buildPortraitPage() {
    return Center(
      child: SingleChildScrollView(
        child: Column(
          mainAxisSize: MainAxisSize.min, // <-- notice 'min' here. Important
          children: [
            Flexible(
              child: Image.asset('assets/images/my-image.png'),
            ),
            Flexible(
              child: Text('My content'),
            ),
          ],
        ),
      ),
    );
  }

The layout engine in Flutter is pretty hard to figure out.

Solution 5 - Flutter

use LayoutBuilder widget to wrap all the widget and use Spacer widget before and after your centered widget inside the Column

    class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('AppBar'),
        ),
        body: LayoutBuilder(builder: (context, constraints) {
          return SingleChildScrollView(
              child: ConstrainedBox(
                  constraints: BoxConstraints(minWidth: constraints.maxWidth, minHeight: constraints.maxHeight),
                  child: IntrinsicHeight(
                    child: Column(
                        mainAxisSize: MainAxisSize.max,
                        children: [
                          Spacer(),
                          Container(
                             child: //your widget
                          ),
                          Spacer()
                        ]
                    ),
                  )
              )
          );
        })
    );
  }
}

Solution 6 - Flutter

Just wrap the Column in a Center. I used that for my apps and it seems to center the contents of my Column even inside a SingleChildScrollView.

Solution 7 - Flutter

There's another way to achieve this:

Center(
    child: ListView(
        shrinkWrap: true,
        children: []
    )

)

Solution 8 - Flutter

wrap SingleChildScrollView with center

child: Center(
   child: SingleChildScrollView(
      child: Column(
         mainAxisAlignment: MainAxisAlignment.center,
         mainAxisSize: MainAxisSize.max,

center in SingleChildScrollView

Solution 9 - Flutter

You can use SingleChildScrollView -> ConstrainedBox(with min height and width) -> Center

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
QuestionHurobakiView Question on Stackoverflow
Solution 1 - FlutterAndrewSView Answer on Stackoverflow
Solution 2 - FlutterDinesh BalasubramanianView Answer on Stackoverflow
Solution 3 - FlutterMusfiq ShantaView Answer on Stackoverflow
Solution 4 - FlutterDarkNeuronView Answer on Stackoverflow
Solution 5 - FlutterAmera AbdallahView Answer on Stackoverflow
Solution 6 - FlutterCoderView Answer on Stackoverflow
Solution 7 - FlutterMattView Answer on Stackoverflow
Solution 8 - FlutterSonu kumarView Answer on Stackoverflow
Solution 9 - FlutterAtharv DalviView Answer on Stackoverflow