Kiz
Kiz

Reputation: 439

Flutter column with expanding widget inside a scroll view

I'm trying to create a column that has content at the top, some more content at the bottom like a footer, and filler space in between. Additionally it needs to scroll when the screen is too small for the top content + footer content (small devices, keyboard opened etc.)

Something like this

scrolling

when the content is larger than screen, it should scroll

flex no scroll

when the content is smaller than screen, flex in middle

Have tried a few different approaches found on SO but cannot figure out how to get this to work. With a singleChildScrollView giving a Column infinite height, the Flexible will throw an error as it's unbounded.

Code at the moment

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

class TestPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        color: Colors.grey,
        child: SafeArea(
            child: LayoutBuilder(
          builder: (BuildContext context, BoxConstraints constraints) => SingleChildScrollView(
              scrollDirection: Axis.vertical,
              child: Column(
                  crossAxisAlignment: CrossAxisAlignment.stretch,
                  mainAxisAlignment: MainAxisAlignment.start,
                  children: [
                    Container(
                        alignment: Alignment.center,
                        height: 150,
                        width: 250,
                        color: Colors.greenAccent,
                        margin: EdgeInsets.all(8),
                        child: Text('Content')),
                    Container(
                        alignment: Alignment.center,
                        height: 150,
                        width: 250,
                        color: Colors.pinkAccent,
                        margin: EdgeInsets.all(8),
                        child: Text('Content')),
                    Container(
                        alignment: Alignment.center,
                        height: 150,
                        width: 250,
                        color: Colors.pink.shade100,
                        margin: EdgeInsets.all(8),
                        child: TextField()),
                    Flexible(
                      child: Container(
                          alignment: Alignment.center,
                          color: Colors.blueAccent,
                          margin: EdgeInsets.all(8),
                          child: Text('Flex')),
                    ),
                    Container(
                        alignment: Alignment.center,
                        height: 100,
                        width: 250,
                        color: Colors.redAccent,
                        margin: EdgeInsets.all(8),
                        child: Text('Footer')),
                  ])),
        )),
      ),
    );
  }
}

Upvotes: 1

Views: 1665

Answers (1)

Kiz
Kiz

Reputation: 439

After much trial and error, and no success using things like LayoutBuilder and IntrinsicHeight I finally worked out the solution for the use case I have using CustomScrollView and a Sliver widget called SilverFillRemaining.

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

class TestPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        color: Colors.grey,
        child: SafeArea(
            child: CustomScrollView(
          slivers: [
            SliverFillRemaining(
              hasScrollBody: false,
              child: Column(
                  crossAxisAlignment: CrossAxisAlignment.stretch,
                  mainAxisAlignment: MainAxisAlignment.start,
                  children: [
                    Container(
                        alignment: Alignment.center,
                        height: 150,
                        width: double.infinity,
                        color: Colors.greenAccent,
                        margin: EdgeInsets.all(8),
                        child: Text('Content')),
                    Container(
                        alignment: Alignment.center,
                        height: 150,
                        width: 250,
                        color: Colors.pinkAccent,
                        margin: EdgeInsets.all(8),
                        child: Text('Content')),
                    Container(
                        alignment: Alignment.center,
                        height: 150,
                        width: 250,
                        color: Colors.pink.shade100,
                        margin: EdgeInsets.all(8),
                        child: TextField()),
                    Flexible(
                      fit: FlexFit.tight,
                      child: Container(
                          alignment: Alignment.center,
                          color: Colors.blueAccent,
                          margin: EdgeInsets.all(8),
                          child: Text('Flex')),
                    ),
                    Container(
                        alignment: Alignment.center,
                        height: 100,
                        width: 250,
                        color: Colors.redAccent,
                        margin: EdgeInsets.all(8),
                        child: Text('Footer')),
                  ]),
            ),
          ],
        )),
      ),
    );
  }
}

Hope that helps anyone else with a similar use case

Upvotes: 3

Related Questions