How to make two containers within one column scrollable?

Viewed 30

I am building an app using Flutter, and I encountered this mistake:

I am making a column, that has two Containers inside it. The top Container has a fixed height, 40% of screen. The bottom Container's height is changed. Its height is dependent on the amount of containers it has inside. If the amount of inner containers is more than 6, then I have an overflow. Yet, I want a scrollable behavior (only on second widget). This is the minimal reproducible code:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Stateful Clicker Counter',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Clicker Counter Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  final String title;
  const MyHomePage({Key? key, required this.title}) : super(key: key);
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    Size size = MediaQuery.of(context).size;
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Container(
                width: size.width,
                height: size.height * 0.4,
                color: Colors.black,
              ),
              Container(
                  width: size.width,
                  color: Colors.red,
                  child: Column(
                    children: [
                      Text("Hello"),
                      GridView.count(
                        crossAxisCount: 3,
                        children: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((el) => Text(el.toString())).toList() as List<Widget>,
                        shrinkWrap: true,
                      ),
                    ],
                  )),
            ],
          ),
        ));
  }
}

As you may see, I use GridView.count in the second container to create this inner containers. It has by default scrollable behaviour. But it still gives overflow. How do I fix this?

3 Answers

GridView has scroll behavior but when using shrinkWarp scrolling doesn't work.

as on https://youtu.be/LUqDNnv_dh0?t=117 when defination shrinkWarp:

to completely evaluate itself and figure out its full size up front and then proceed by your top-level viewport behaving as if they're all just one widget

that means when using shrinkWarp gridview will take a full size.

you can solve your code by doing like:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Stateful Clicker Counter',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Clicker Counter Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  final String title;
  const MyHomePage({Key? key, required this.title}) : super(key: key);
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    Size size = MediaQuery.of(context).size;
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Container(
                width: size.width,
                height: size.height * 0.4,
                color: Colors.black,
              ),
              Expanded(  // Added
                child: Container(
                    width: size.width,
                    color: Colors.red,
                    child: Column(
                      children: [
                        Text("Hello"),
                        Expanded(  // Added
                          child: GridView.count(
                            crossAxisCount: 3,
                            children: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((el) => Text(el.toString())).toList() as List<Widget>,
                            // shrinkWrap: true, // changed
                          ),
                        ),
                      ],
                    )),
              ),
            ],
          ),
        ));
  }
}

You should wrap your main column in an expanded or flexible format so that it uses the available screen space. Then add a SingleChildScrollView on your child column to get a simple scroll. Example:

              Expanded(
               child: 
                Container(
                  width: size.width,
                  color: Colors.red,
                  child: SingleChildScrollView(
                    child: Column(
                     children: [
                       Text("Hello"),
                       GridView.count(
                         crossAxisCount: 3,
                         children: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((el) => Text(el.toString())).toList() as List<Widget>,
                         shrinkWrap: true,
                        ),
                      ],
                    )
                  ),
                )  
              )

wrap your second Container & column with expanded and remove shrinkwrap from GridView.count:

 Expanded(
                // Added
                child: Container(
                    width: size.width,
                    color: Colors.red,
                    child: Column(
                      children: [
                        Text("Hello"),
                        Expanded(
                          // Added
                          child: GridView.count(
                            crossAxisCount: 3,
                            children: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
                                .map((el) => Text(el.toString()))
                                .toList() as List<Widget>,
                            // shrinkWrap: true, // changed
                          ),
                        ),
                      ],
                    )),
              ),
Related