'Flutter - Adding Container (widget) in GridView when click a button?

I wanted to add a container widget in the GridView when a button is clicked. I was able to do this with the column widget but could not do it with GridView.

import 'package:flutter/material.dart';

List<Widget> gridChild = [
  Container(
    margin: EdgeInsets.all(8.0),
    width: 30.0,
    height: 50.0,
    color: Colors.green,
  ),
  Container(
    margin: EdgeInsets.all(8.0),
    width: 30.0,
    height: 50.0,
    color: Colors.green,
  ),
  Container(
    margin: EdgeInsets.all(8.0),
    width: 30.0,
    height: 50.0,
    color: Colors.green,
  ),
  Container(
    margin: EdgeInsets.all(8.0),
    width: 30.0,
    height: 50.0,
    color: Colors.green,
  ),
  Container(
    margin: EdgeInsets.all(8.0),
    width: 30.0,
    height: 50.0,
    color: Colors.green,
  ),
];

class Grid extends StatefulWidget {
  @override
  _GridState createState() => _GridState();
}

class _GridState extends State<Grid> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      floatingActionButton: FloatingActionButton(
        backgroundColor: Colors.red,
        child: Icon(Icons.add),
        onPressed: () {
          setState(() {
            gridChild.add(Container(
              margin: EdgeInsets.all(8.0),
              width: 30.0,
              height: 50.0,
              color: Colors.green,
            ));
            print(gridChild.length);
          });
        },
      ),
      body: Container(
        child: GridView.count(
          crossAxisCount: 2,
          children: gridChild,
        ),
      ),
    );
  }
}

What I did was that I added a container in the widget list. The length of the list increases as I click the botton but the container was not added on the screen. It didn't work even though I put the function inside the setState().

I would really appreciate your help.



Solution 1:[1]

This works...

class Grid extends StatefulWidget {
  @override
  _GridState createState() => _GridState();
}

class _GridState extends State<Grid> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      floatingActionButton: FloatingActionButton(
        backgroundColor: Colors.red,
        child: Icon(Icons.add),
        onPressed: () {
          setState(() {
            gridChild.add(Container(
              margin: EdgeInsets.all(8.0),
              width: 30.0,
              height: 50.0,
              color: Colors.green,
            ));
          });
        },
      ),
      body: Container(
        child: GridView.count(
          crossAxisCount: 2,
          children: List.generate(gridChild.length, (index) => gridChild[index]),
        ),
      ),
    );
  }
}

Output:

enter image description here

Solution 2:[2]

Use GridView.builder in the body. It should fix your problem. I don't really know why, but I know it works. Hopefully someone can update this answer and provide an explanation.

GridView.builder(
        itemCount: gridChild.length,
        gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
          crossAxisCount: 2,
        ),
        itemBuilder: (BuildContext context, int index){
          return gridChild[index];
        },
      ),

Solution 3:[3]

You can do it by calling the setstate method.

while clicking on the button just add a widget to the list and use the setstate after adding to the list. Basically setstate will rebuild the screen.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Josteve
Solution 2 aldobaie
Solution 3 DharmanBot