Flutter - How to make a column screen scrollable

AndroidDartFlutter

Android Problem Overview


I'm building a flutter app with a Login Screen. On focus on the text field(s), the screen is overflowed and i cannot scroll. I've tried using a ListView.builder, but that just gives a renderBox error, and the regular ListView doesn't work

Screen Screen on Text Input

The widget structure is like this

-scafold
   - body
     - container
       - column    
           - form
              - column
                  - textInput
                  - textInput
                  - container    
           - container
              - row      
           - raisedButton

Thank You in advance !!

Android Solutions


Solution 1 - Android

The ListView solution should work, but at the time of writing, it suffers from the crash listed here. Another way to achieve the same thing without this crash is to use a SingleChildScrollView:

return new Container(
  child: new SingleChildScrollView(
    child: new Column(
      children: <Widget>[
        _showChild1(),
        _showChild2(),
        ...
        _showChildN()
      ]
    )
  )
);

Solution 2 - Android

try this Code: Its Using ListView

    class Home extends StatelessWidget {
  @override
     Widget build(BuildContext context) {
        // TODO: implement build
        return Scaffold(
          body: Center(
            child: ListView(
              shrinkWrap: true,
              padding: EdgeInsets.all(15.0),
              children: <Widget>[
                Center(
                  child: Card(
                    elevation: 8.0,
                    child: Container(
                      padding: EdgeInsets.all(10.0),
                      child: Column(
                        children: <Widget>[
                          TextField(
                            decoration: InputDecoration(
                              prefixIcon: Icon(Icons.person),
                              labelText: "Username or Email",
                            ),
                          ),
                          SizedBox(
                            height: 15.0,
                          ),
                          TextField(
                            decoration: InputDecoration(
                              prefixIcon: Icon(Icons.lock),
                              labelText: "Password",
                            ),
                          ),
                          SizedBox(
                            height: 15.0,
                          ),
                          Material(
                            borderRadius: BorderRadius.circular(30.0),
                            //elevation: 5.0,
                            child: MaterialButton(
                              onPressed: () => {},
                              minWidth: 150.0,
                              height: 50.0,
                              color: Color(0xFF179CDF),
                              child: Text(
                                "LOGIN",
                                style: TextStyle(
                                  fontSize: 16.0,
                                  color: Colors.white,
                                ),
                              ),
                            ),
                          )
                        ],
                      ),
                    ),
                  ),
                ),
                SizedBox(
                  height: 25.0,
                ),
                Row(
                  children: <Widget>[
                    Expanded(child: Text("Don't Have a Account?")),
                    Text("Sign Up",
                        style: TextStyle(
                          color: Colors.blue,
                        )),
                  ],
                ),
              ],
            ),
          ),
          bottomNavigationBar: Padding(
            padding: EdgeInsets.all(10.0),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Expanded(
                    child: RaisedButton(
                      padding: EdgeInsets.all(15.0),
                      onPressed: () {},
                      color: Colors.white,
                      shape: RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(
                            32.0,
                          ),
                          side: BorderSide(color: Color(0xFF179CDF))),
                      child: Text(
                        "SKIP SIGN UP FOR NOW",
                        style:
                        TextStyle(fontSize: 18.0, color: Color(0xFF179CDF)),
                      ),
                    )),
              ],
            ),
          ),
        );
      }
    }

Solution 3 - Android

There are two easy ways of doing it.

  1. Wrap your Column in a SingleChildScrollView

     SingleChildScrollView(
       child: Column(
         children: [
           Text('First'),
           //... other children
           Text('Last'),
         ],
       ),
     )
    
  2. Use ListView instead of Column.

     ListView(
       children: [
         Text('First'),
         //... other children
         Text('Last'),
       ],
     )
    

This approach is simple to use, but you lose features like crossAxisAlignment and other benefits provided by Column, in that case, you can wrap your children widget inside Align and set alignment property.


Now you may have nested children which are further scrollable, in that case, you need to provide a fixed height to your children, you may use SizedBox for that, that's it.

For example:

ListView(
  children: [
    Text('First'),
    SizedBox(
      height: 100,
      child: ListView(...), // nested ScrollView
    ),
    Text('Last'),
  ],
)

Solution 4 - Android

The column is used when we have to list widgets vertically on the screen and SingleChildScrollView widget provides scroll functionality for Column widgets.

When we used SingleChildScrollView+Column, the entire item list is rendered even if only a few items are visible.

So for complex layouts with a small number of items, the performance gain may not be worth the trouble, in which case we can use SingleChildScrollView.

Using SingleChildScrollView with Columns make your screen scrollable, and you can make your layout as above

Few Advantages:

  1. It will be useful when different widgets are needed with scroll functionality.
  2. For complex layouts, when items are less & performance, not a concern we can use it(Like when every other widget required some modification which is different from other)

Here is how can you do it

class MyHome extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
        backgroundColor: Colors.white,
        body: SafeArea(
          bottom: false,
          child: Container(
            padding: EdgeInsets.only(left: 15, right: 15),
            height: double.infinity,
            width: double.infinity,
            child: SingleChildScrollView(
                padding: EdgeInsets.only(bottom: 15),
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.end,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: <Widget>[
                    SizedBox(
                      height: 200.0,
                    ),
                    Card(
                      elevation: 8.0,
                      child: Container(
                        padding: EdgeInsets.all(10.0),
                        child: Column(
                          children: <Widget>[
                            TextField(
                              decoration: InputDecoration(
                                prefixIcon: Icon(Icons.person),
                                labelText: "Username or Email",
                              ),
                            ),
                            SizedBox(
                              height: 15.0,
                            ),
                            TextField(
                              decoration: InputDecoration(
                                prefixIcon: Icon(Icons.lock),
                                labelText: "Password",
                              ),
                            ),
                            SizedBox(
                              height: 30.0,
                            ),
                            MaterialButton(
                                height: 50.0,
                                elevation: 5,
                                minWidth: 300,
                                onPressed: () {},
                                shape: RoundedRectangleBorder(
                                  borderRadius: new BorderRadius.circular(30.0),
                                ),
                                color: Theme.of(context).primaryColor,
                                disabledColor: Theme.of(context)
                                    .primaryColor
                                    .withOpacity(0.50),
                                disabledElevation: 0,
                                child: Text('SIGN IN',
                                    textAlign: TextAlign.center, style: TextStyle(color: Colors.white),))
                          ],
                        ),
                      ),
                    ),
                    SizedBox(
                      height: 25.0,
                    ),
                    Row(
                      children: <Widget>[
                        Expanded(child: Text("Don't Have a Account?")),
                        Text("Sign Up",
                            style: TextStyle(
                              color: Colors.blue,
                            )),
                      ],
                    ),
                    SizedBox(
                      height: 50.0,
                    ),
                    Align(
                      alignment: Alignment.bottomCenter,
                      child: Row(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
                        Text(
                          'New to App?',
                          style: TextStyle(color: Colors.black87),
                        ),
                        SizedBox(
                          width: 5,
                        ),
                        GestureDetector(
                          onTap: () {
                          },
                          child: Text(
                            "REGISTER", style: TextStyle(
                            color: Colors.blue,
                          )
                          ),
                        ),
                      ]),
                    )
                  ],
                )),
          ),
        ));
  }
}

enter image description here

Solution 5 - Android

We can use the Expanded widget. It will add scrolling.

return new Expanded(
  child: new SingleChildScrollView(
    child: new Column(
      children: <Widget>[
        _showChild1(),
        _showChild2(),
        ...
        _showChildN()
      ]
    )
  )
);

Solution 6 - Android

Wrap your column in SingleChildScrollView and then wrap SingleChildScrollView in a Center widget to center the widgets in the column.

Center(
    child: SingleChildScrollView(
        child: Column(
        children: [
            Text('First'),
            //... other children
            Text('Last'),
        ],
    ),
)

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
QuestionKingsley CAView Question on Stackoverflow
Solution 1 - AndroidRob LyndonView Answer on Stackoverflow
Solution 2 - Androidanmol.majhailView Answer on Stackoverflow
Solution 3 - AndroidCopsOnRoadView Answer on Stackoverflow
Solution 4 - AndroidParesh MangukiyaView Answer on Stackoverflow
Solution 5 - AndroidPankajan05View Answer on Stackoverflow
Solution 6 - AndroidSheraz Hussain TuriView Answer on Stackoverflow