lynxu
lynxu

Reputation: 803

Scrollable Container inside a Column

I tried a few different approaches but I can't get this to work. The layout I want to achieve is really simple and it's a breeze to implement in native Android:

I tried to use SingleChildScrollView, but it doesn't seem to work inside a Column. Maybe I'm doing something wrong or I'm not using the right widgets...

My result:

enter image description here

Scaffold(
  body: Column(
    children: <Widget>[
      Container(
        height: 100.0,
        color: Colors.blue,
      ),
      SingleChildScrollView(
        child: Container(
          color: Colors.red,
          padding: EdgeInsets.all(20.0),
          child: Column(
            children: <Widget>[
              Text('Red container should be scrollable'),
              Container(
                width: double.infinity,
                height: 700.0,
                padding: EdgeInsets.all(10.0),
                color: Colors.white.withOpacity(0.7),
                child: Text('I will have a column here'),
              )
            ],
          ),
        ),
      ),
    ],
  ),
)

Upvotes: 79

Views: 46128

Answers (4)

If you don't want to expand your column to maximal size, wrap your SingleChildScrollView into Flexible:

return Column(
  mainAxisSize: MainAxisSize.min,
  children: [
    //header
    Container(
      color: Colors.red,
      height: 50,
      child: const Text("Header"),
    ),
    Flexible(
        child: SingleChildScrollView(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          //top
          Container(
            color: Colors.blue,
            height: 100,
            child: const Text("Top"),
          ),
          Container(
            color: Colors.yellow,
            height: 5000,
          ),
          //bottom
          Container(
            color: Colors.green,
            height: 100,
            child: const Text("Bottom"),
          ),
        ],
      ),
    )),
    //footer
    Container(color: Colors.red, height: 50, child: const Text("Footer")),
  ],
);

Upvotes: 3

Ernest Collection
Ernest Collection

Reputation: 2292

I think that maybe after a year you have managed to do that.

But for others searching for the same problem, the easiest way is to wrap the SingleChildScrollView inside an Expanded widget.

Widget build(BuildContext context) =>
Scaffold(
  body: Column(
    children: <Widget>[
      Container(
        height: 100.0,
        color: Colors.blue,
      ),
      Expanded(
        child: SingleChildScrollView(
          child: Container(
            color: Colors.red,
            padding: EdgeInsets.all(20.0),
            child: Column(
              children: <Widget>[
                Text('Red container should be scrollable'),
                Container(
                  width: double.infinity,
                  height: 700.0,
                  padding: EdgeInsets.all(10.0),
                  color: Colors.white.withOpacity(0.7),
                  child: Text('I will have a column here'),
                )
              ],
            ),
          ),
        ),
      ),
    ],
  ),
);

Upvotes: 203

lynxu
lynxu

Reputation: 803

I managed to implement a working layout using a Stack, the only down-side being that if I have a TextField and I scroll down, the cursor 'bubble' shows up above my top container... which is kind of ugly. The order of my widgets in the Stack doesn't affect this.

See screenshot

  Widget build(BuildContext context) =>
  Scaffold(
    body: Stack(
      children: <Widget>[
        Container(
          height: 100.0,
          color: Colors.blue,
        ),
        Container(
          margin: EdgeInsets.only(top: 100.0),
          child: SingleChildScrollView(
            child: Container(
              color: Colors.red,
              padding: EdgeInsets.all(20.0),
              child: Column(
                children: <Widget>[
                  Container(
                    width: double.infinity,
                    height: 700.0,
                    padding: EdgeInsets.all(10.0),
                    color: Colors.white.withOpacity(0.7),
                    child: TextField(),
                  )
                ],
              ),
            ),
          ),
        ),
      ],
    ),
  );

Upvotes: 1

olexa.le
olexa.le

Reputation: 1807

The problem is that Column widget does not support scrolling. In order to make it work you may switch to ListView, but current implementation lack of some sort of header for sections. In order to get them you may use sticky_headers package like that:

Widget build(BuildContext context) => Scaffold(
      body: new ListView.builder(
          itemCount: 1,
          padding: EdgeInsets.zero,
          itemBuilder: (context, index) {
            return new StickyHeader(
                header: Container(
                  height: 100.0,
                  color: Colors.blue,
                ),
                content: Container(
                  color: Colors.red,
                  padding: EdgeInsets.all(20.0),
                  child: Column(
                    children: <Widget>[
                      Text('Red container should be scrollable'),
                      Container(
                        width: double.infinity,
                        height: 700.0,
                        padding: EdgeInsets.all(10.0),
                        color: Colors.white.withOpacity(0.7),
                        child: Text('I will have a column here'),
                      )
                    ],
                  ),
                ));
          }));

Upvotes: 3

Related Questions