In today’s episode we will be showing how to add a GridView to our video game catalog app a.k.a our first Flutter app. If you missed our last episode make sure you check Basic Setup before you continue. Let’s begin!

Open the file named main.dart inside the /lib folder and remove all the sample code that Flutter provides. We want a stripped app. After you finish removing the code your file should look like this:

import 'package:flutter/material.dart';

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

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

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Container(),
    );
  }
}

As you can see, we ended up with 2 containers MyApp and MyHomePage. MyApp is a Stateless Widget and returns a Material Component (another widget) with our second component MyHomePage. MyHomePage, on the other hand, is a Stateful Widget meaning the widget will have a state that could change through the lifecycle of the container. In our case _MyHomePageState will return an empty container.

Now that we have our clean app is time for us to add our first widget. The idea behind the app is that an user can browse all the games available in their catalog. What’s the best way to display all the games that a user holds? The answer to that is a grid! Thankfully material components provides a GridView out of the box.

Don’t worry in the future we will be building our own custom widgets. Just keep visiting the series for updates.

To add a GridView to our application, let’s create a new stateless widget, which will return the GridView.

Create a folder inside /lib and name it /containers. Inside that folder create a new file a call it game_grid.dart. Add the following code:

import 'package:flutter/material.dart';

class GameGrid extends StatelessWidget {
  GameGrid(this.gameList);
  final List<String> gameList;

  @override
  Widget build(BuildContext context) {
    return GridView.count(
      crossAxisCount: 2,
      mainAxisSpacing: 30,
      children: List.generate(gameList.length, (index) {
        return Center(child: Text(gameList[index]));
      }),
    );
  }
}

Let me explain what’s going on in this class GameGrid :

Your folder structure should look like this:

├── video_game_catalog/
   ├── android/
   ├── ios/
   ├── lib/
      ├── containers/
   ├── res/
   ├── test/

Now that we have our own game grid, lets go ahead and replace the empty container in main.dart. Also, let’s change the title of the app from Flutter Demo to Video Game Catalog and the title of the MyHomePage from Flutter Demo Home Page to My Games. Your code should look like this:

import 'package:flutter/material.dart';
import 'package:video_game_catalog/containers/game_grid.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Video Game Catalog',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'My Games'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: GameGrid(null),
    );
  }
}

Now all with need is some sample data. For that, let’s add a mocked game list. At the top of the main.dart file add:

const List<String> initialGames = [
  'Minecraft',
  'Fortnite',
  'Call of Duty',
  'Overwatch',
  'Rocket League',
  'Uncharted 4',
  'Forza Horizon 4',
  'Cuphead',
];

Replace body: GameGrid(null), by body: GameGrid(initialGames), in order to pass our mocked list down to the GameGrid. Your main.dart code should look like this:

import 'package:flutter/material.dart';
import 'package:video_game_catalog/containers/game_grid.dart';

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

const List<String> initialGames = [
  'Minecraft',
  'Fortnite',
  'Call of Duty',
  'Overwatch',
  'Rocket League',
  'Uncharted 4',
  'Forza Horizon 4',
  'Cuphead',
];

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Video Game Catalog',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'My Games'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: GameGrid(initialGames),
    );
  }
}

If we run the app…

flutter gridview

Voila! We have a grid to display all our games!

If you instead want to clone the source of the app until now go ahead and try:

git clone --branch v0.0.2 https://github.com/fluttersensei/video_game_catalog.git
cd video_game_catalog
flutter packages get
flutter run

Wrapping it up

Today, we have learned how to add a GridView to our Flutter app and how to mock some date. On the next episode, we will be covering how to create a video game cover. Stay tuned! If you liked the tutorial, please, make sure you subscribe to our mailing list or follow us on any of our social media… this way you won’t miss any lessons… See you on the next episode!