111

My code for a page is like this. i need to scroll part below appbar.

@override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(... ),
      body: new Stack(
        children: <Widget>[
          new Container(
            decoration: BoxDecoration(
                image: DecorationImage(...),
          new Column(children: [
            new Container(...),
            new Container(...... ),
            new Padding(
              child: SizedBox(
                child: RaisedButton(..),
            ),
            new Divider(),
            new Column(
              children: <Widget>[
                new Container(
                  child: new Row(
                    children: <Widget>[
                      new Expanded(
                        child: new Text(  ),
                      ),
                      new IconButton(
                        icon: IconButton(..),
                        onPressed: () {
                          _changed(true, "type");
                        },
                      ),
                    ],
                  ),
                ),
                visibilityPropertyType
                    ? new Container(
                        margin: EdgeInsets.all(24.0),
                        child: new Column(
                          children: <Widget>[
                            new Row(
                              children: <Widget>[
                                new Expanded(... ),
                                new RaisedButton(..)
                              ],
                            ),
                            new Padding(
                              padding: const EdgeInsets.only(top: 10.0),
                              child: new Row(
                                mainAxisAlignment:
                                    MainAxisAlignment.spaceEvenly,
                                children: <Widget>[
                                  new Column(
                                    children: <Widget>[
                                      new Row(  
                                        children: <Widget>[.. ]),
                                      new Row(
                                        children: <Widget>[]),
                                      new Row(
                                        children: <Widget>[]),
                                      new Row(
                                        children: <Widget>[],
                                  ),
                                  new Column(
                                    children: <Widget>[
                                      new Row(
                                        children: <Widget>[],
                                      ),
                                    ],
                                  ),
                                ],
                              ),
                            ),
                          ],
                        ))
                    : new Container(),
              ],
            ),
            new Divider(
              color: Colors.white,
            )
          ])
        ],
      ),
    );
  }

I need to make body part scrollable. How can i implement that scroll. If there is any custom scroll method existing. i have tried Scrollable and SingleChildScrollView but does not meet up with my needs. When i used SinglechildScrollView it occurs an error BoxConstraints forces an infinite height. if i removed LayoutBuilder it causes A RenderFlex overflowed by 22 pixels on the bottom error

Vineeth Mohan
  • 2,584
  • 4
  • 17
  • 31

9 Answers9

223

Wrap your widget tree inside a SingleChildScrollView:

 body: SingleChildScrollView(
child: Stack(
    children: <Widget>[
      new Container(
        decoration: BoxDecoration(
            image: DecorationImage(...),
      new Column(children: [
        new Container(...),
        new Container(...... ),
        new Padding(
          child: SizedBox(
            child: RaisedButton(..),
        ),
....
...
 ); // Single child scroll view

Remember, SingleChildScrollView can only have one direct widget (Just like ScrollView in Android).

MendelG
  • 14,885
  • 4
  • 25
  • 52
Jaswant Singh
  • 9,900
  • 8
  • 29
  • 50
  • 36
    Crashes for me with `RenderFlex children have non-zero flex but incoming height constraints are unbounded.` – Twometer Jul 21 '19 at 13:17
  • 2
    Are you using ListView or something scrollable inside the SingleChildScrollView? If yes, setting that widget's shringWrap property to true might fix the issue. – Jaswant Singh Jul 02 '20 at 10:11
  • 7
    Try removing Expanded if you have one. – Rony Tesler Aug 28 '20 at 15:05
  • Glad I went with stack overflow. Google suggested using DraggableScrollableSheet. That looked a bit like much more work and not quite what was needed. +1 for stack overflow. – Nick N Dec 31 '21 at 21:27
  • A `Spacer()` will also cause the `RenderFlex children have non-zero flex but incoming height constraints are unbounded.` issue – kris Jul 03 '22 at 10:43
38

With your suggestions, I reached a solution like this:

new LayoutBuilder(
        builder:
            (BuildContext context, BoxConstraints viewportConstraints) {
          return SingleChildScrollView(
            child: ConstrainedBox(
              constraints:
                  BoxConstraints(minHeight: viewportConstraints.maxHeight),
              child: Column(children: [
             // remaining stuffs
              ]),
            ),
          );
        },
      )
MendelG
  • 14,885
  • 4
  • 25
  • 52
Vineeth Mohan
  • 2,584
  • 4
  • 17
  • 31
  • 6
    LayoutBuilder + BoxConstraints + ConstrainedBox - makes miracles! For example, in my case, I wanted a horizontal scroll nested in a column. And the problem was that by default horizontal scroll centers its content no matter what you do. So I had to put SingleChildScrollView inside a ConstrainedBox with maxWidth: viewportConstraints.maxWidth, minWidth: viewportConstraints.maxWidth. So that if there is a few content - it aligns left, and if there's a lot of content (more than a screen width) it starts scrolling. – Kirill Karmazin Nov 11 '19 at 15:12
  • This solution is working, but the layout builder keep building all the all the widgets when there is any interaction with the page, for example scroll list, click button. Is it good? If you want check it rebuild, you get load randomColor library from pub and assign it to any widget in your page. You try interact with any of your widget under layout builder. You can see the widget which have randomColor assign will change color every time. Is it good?? Expert advice required. – Thiyraash David Jul 20 '20 at 08:51
  • Layout Builder re-randers the child whenever there is any interaction with any of the child widget. – Jaswant Singh Sep 16 '20 at 16:39
  • This answer is a small miracle for me. I've been trying really hard to get a scrollable list stretch to match the height of the bigest child of a stack. Your code sample was instrumental to get this done. Thank you! – Adrian Moisa May 16 '21 at 10:08
33

Two ways to add Scroll in page

1. Using SingleChildScrollView :

     SingleChildScrollView(
          child: Column(
            children: [
              Container(....),
              SizedBox(...),
              Container(...),
              Text(....)
            ],
          ),
      ),
      

2. Using ListView: ListView is the default provided Scroll no need to add an extra widget for scrolling

     ListView(
          children: [
            Container(..),
            SizedBox(..),
            Container(...),
            Text(..)
          ],
      ),
      
MendelG
  • 14,885
  • 4
  • 25
  • 52
Sanjayrajsinh
  • 15,014
  • 7
  • 73
  • 78
8

You can try CustomScrollView. Put your CustomScrollView inside Column Widget.

Just for example -

class App extends StatelessWidget {

 App({Key key}): super(key: key);

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: AppBar(
          title: const Text('AppBar'),
      ),
      body: new Container(
          constraints: BoxConstraints.expand(),
          decoration: new BoxDecoration(
            image: new DecorationImage(
              alignment: Alignment.topLeft,
              image: new AssetImage('images/main-bg.png'),
              fit: BoxFit.cover,
            )
          ),
          child: new Column(
            children: <Widget>[               
              Expanded(
                child: new CustomScrollView(
                  scrollDirection: Axis.vertical,
                  shrinkWrap: false,
                  slivers: <Widget>[
                    new SliverPadding(
                      padding: const EdgeInsets.symmetric(vertical: 0.0),
                      sliver: new SliverList(
                        delegate: new SliverChildBuilderDelegate(
                          (context, index) => new YourRowWidget(),
                          childCount: 5,
                        ),
                      ),
                    ),
                  ],
                ),
              ),
            ],
          )),
    );
  }
}

In above code I am displaying a list of items ( total 5) in CustomScrollView. YourRowWidget widget gets rendered 5 times as list item. Generally you should render each row based on some data.

You can remove decoration property of Container widget, it is just for providing background image.

WitVault
  • 23,445
  • 19
  • 103
  • 133
6

You can use this one and it's best practice.

SingleChildScrollView(
  child: Column(
    children: <Widget>[
      //Your Widgets
      //Your Widgets,
      //Your Widgets
    ],
  ),
);
Rohit Soni
  • 1,300
  • 6
  • 12
5

Very easy if you are already using a statelessWidget checkOut my code

class _MyThirdPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Understanding Material-Cards'),
      ),
      body: SingleChildScrollView(
          child: Column(
        children: <Widget>[
          _buildStack(),
          _buildCard(),
          SingleCard(),
          _inkwellCard()
        ],
      )),
    );
  }
}
Code with Benji
  • 666
  • 9
  • 17
1

Look to this, may be help you.

class ScrollView extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new LayoutBuilder(
      builder:
          (BuildContext context, BoxConstraints viewportConstraints) {
        return SingleChildScrollView(
          scrollDirection: Axis.vertical,
          child: ConstrainedBox(
            constraints: BoxConstraints(minHeight: viewportConstraints.maxHeight),
            child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text("Hello world!!"),
                  //You can add another children
            ]),
          ),
        );
      },
    );
  }
}
Paul Roub
  • 36,322
  • 27
  • 84
  • 93
AMMAR ELHAMDO
  • 519
  • 4
  • 12
0

you can scroll any part of content in two ways ...

  1. you can use the list view directly
  2. or SingleChildScrollView

most of the time i use List view directly when ever there is a keybord intraction in that specific screen so that the content dont get overlap by the keyboard and more over scrolls to top ....

this trick will be helpful many a times....

Aravind Siruvuru
  • 1,019
  • 12
  • 7
0

Adding this may solve your problem set the Height to max(screenSize.height, 1024)