1

I have a column with a container that acts as a header and a gridview of widgets below. I want only the gridview to be scrollable and that the header will not move and always be displayed.

This is my code:

class HomePage extends StatelessWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Column(
          children: [
            Container(
              margin: EdgeInsets.only(left: 24, right: 24),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  SizedBox(height: 22),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      Message("Hello, Guest!", size: 32),
                      Icon(
                        CustomIcons.statistics,
                        color: AppColors.blue,
                        size: 32.0,
                      ),
                    ],
                  ),
                  SizedBox(height: 14),
                  Message("What worries you now? Select or Add.", size: 14),
                ],
              ),
            ),
            SizedBox(height: 16),
            GridView.count(
              primary: true,
              shrinkWrap: true,
              crossAxisCount: 2,
              crossAxisSpacing: 40.0,
              mainAxisSpacing: 40.0,
              padding: const EdgeInsets.all(20.0),
              children: _items,
            ),
          ],
        ),
      ),
    );
  }
}

When it runs I get a renderflex overflowed error: enter image description here

When I wrap my gridview in an expanded widget as some answers suggested, the scroll gets out of bounds: enter image description here

Appreciate the help!

4 Answers4

0

Remove expnaded and wrap your safe area With SingleChildScrollView, and also add phyiscs:ScrollPhysics() in gridview

Wali Khan
  • 586
  • 1
  • 5
  • 13
  • But then when I scroll my header container will scroll away and won't be visible any more. This isn't what I want. I want only the grid to be scrollable and for the header to stay in place. – daniel eidlin Sep 25 '21 at 18:11
0

Wrap your Column with a SingleChildScrollView, A Column will always try to shrink-wrap its children, using Expanded tells the GridView to only take up the available space.

Another alternative is if your GridView doesn't grow in too much size is to use the shrink-wrap: true and use physics: const NeverScrollablePhyscis(), that way the GridView won't try to grow to infinite size.

sameer kashyap
  • 1,121
  • 1
  • 9
  • 14
  • But then when I scroll my header container will scroll away and won't be visible any more. This isn't what I want. I want only the grid to be scrollable and for the header to stay in place. – daniel eidlin Sep 25 '21 at 18:11
0

You can wrap your Column inside a SingleChildScrollView widget to make the whole column scrollable. The Code Should be :

class HomePage extends StatelessWidget {


const HomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child:Column(
          children: [
            Container(
              margin: EdgeInsets.only(left: 24, right: 24),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  SizedBox(height: 22),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      Message("Hello, Guest!", size: 32),
                      Icon(
                        CustomIcons.statistics,
                        color: AppColors.blue,
                        size: 32.0,
                      ),
                    ],
                  ),
                  SizedBox(height: 14),
                  Message("What worries you now? Select or Add.", size: 14),
                ],
              ),
            ),
            SizedBox(height: 16),
            SingleChildScrollView(
              child: GridView.count(
              primary: true,
              shrinkWrap: true,
              crossAxisCount: 2,
              crossAxisSpacing: 40.0,
              mainAxisSpacing: 40.0,
              padding: const EdgeInsets.all(20.0),
              children: _items,
            ),
            ),
          ],
        ),
      ),
    );
  }
}
Khushal
  • 541
  • 5
  • 13
  • But then when I scroll my header container will scroll away and won't be visible any more. This isn't what I want. I want only the grid to be scrollable and for the header to stay in place. – daniel eidlin Sep 25 '21 at 18:11
  • @danieleidlin Okay, then just wrap your gridview inside singlechildscrollview, see the edited answer. – Khushal Sep 25 '21 at 18:13
  • Didn't work :( I still get the 'A RenderFlex overflowed by 378 pixels on the bottom.' error. – daniel eidlin Sep 25 '21 at 18:21
0

You need to use a combination of Stack, ListView and Column widgets. Here's how to do it:

return Scaffold(
      body: SafeArea(
        child: Stack(
          children: [
            SizedBox(height: 16),
            ListView(
              shrinkWrap: true,
              children: [
                GridView.count(
                  primary: true,
                  shrinkWrap: true,
                  crossAxisCount: 2,
                  crossAxisSpacing: 40.0,
                  mainAxisSpacing: 40.0,
                  padding: const EdgeInsets.all(20.0),
                  children: [
                    Container(
                      margin: EdgeInsets.all(20),
                      color: Colors.red,
                      height: 200,
                      width: 200,
                    ),
                    Container(
                      margin: EdgeInsets.all(20),
                      color: Colors.amber,
                      height: 200,
                      width: 200,
                    ),
                    Container(
                      margin: EdgeInsets.all(20),
                      color: Colors.blue,
                      height: 200,
                      width: 200,
                    ),
                    Container(
                      margin: EdgeInsets.all(20),
                      color: Colors.green,
                      height: 200,
                      width: 200,
                    ),
                  ],
                ),
              ],
            ),
            Container(
              color: Colors.white,
              height: MediaQuery.of(context).size.height * 0.2,
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  SizedBox(height: 22),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      Text("Hello, Guest!"),
                      Icon(
                        Icons.ac_unit,
                        color: Colors.blue,
                        size: 32.0,
                      ),
                    ],
                  ),
                  SizedBox(height: 14),
                  Text("What worries you now? Select or Add."),
                ],
              ),
            ),
          ],
        ),
      ),
    );