From ListView to GridView in Flutter, first steps

I will show you how to use the GridView system in Flutter starting from a ListView.

I'm going to show you how you can migrate your viw to a grip viw and I think the reason for this would be especially when we have a large screen, that is to say it's not a phone and in this case we want to go, excuse the redundancy, from a ListView to a GridView to adapt the number of items on the screen based on the size of the screen.

ListView

We have a list, the name doesn't matter here, it's a list of anything we ask for it and this is to know the number of elements that we are going to build, then here we have the item builder in which we receive the context, I'm not interested in this case, and the position, and here finally a widget that builds our item, in this case what we have here, this is not very difficult and it's the same one that I'm using here, simply here some conditions to know if the image exists:

ListView.builder(
 itemCount: tutorialResponseModel.tutorials.length,
 itemBuilder: (_, int position) {
 return _itemTutorial(position, context);
 }),

And the rest is up to you, a column to glue our elements together, which in this case is the title, some spacing, and the image. Here I used ClipRRect to round the corners. Otherwise, there's nothing strange about it. And a little button to go to the action, to buy or whatever. We can expand this without any changes to either element, whether it's a ListView or a GridView:

Widget _itemTutorial(int position, BuildContext context) {
    final appModel = Provider.of<AppModel>(context, listen: false);
    final tutorial = tutorialResponseModel.tutorials[position];

    if (!tutorial.show) {
      return const SizedBox();
    }

    String image = '';
    if (tutorial.image != '') {
      image = '${AcademyHelper.baseUrlImage}${tutorial.path}/${tutorial.image}';
    }

    return Column(
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        Text(
          tutorial.title.toUpperCase(),
          style: Theme.of(context).textTheme.displayMedium,
        ),
        const SizedBox(
          height: 15,
        ),
        image != ''
            ? ClipRRect(
                borderRadius: BorderRadius.circular(15),
                child: Image.network(
                          image,
                          errorBuilder: (context, error, stackTrace) =>
                              const SizedBox(),
                          loadingBuilder: (context, child, loadingProgress) {
                            if (loadingProgress == null) return child;
                            return Container(
                              width: double.infinity,
                              height: 120,
                              color: Colors.grey,
                            );
                          },
                        ),
                      ))
            : const SizedBox(),
        const SizedBox(
          height: 15,
        ),
        Padding(
          padding: const EdgeInsets.only(right: 15, left: 15),
          child: Text(
            truncate(tutorial.description),
            style: Theme.of(context).textTheme.bodyMedium,
          ),
        ),
        const SizedBox(
          height: 15,
        ),
         Text(
                    '${tutorial.priceOffers}\$',
                    style: Theme.of(context).textTheme.bodyLarge!.copyWith(
                        color: Colors.green, fontWeight: FontWeight.bold),
                  ),

GridView

Just as I was showing you then what we have here in the GridView since we know what we have here in the ListView:

GridView.builder(
                 shrinkWrap: true,
                 physics:
                     const BouncingScrollPhysics(), // evita problema de doble scroll
                 padding: const EdgeInsets.all(8),
                 itemCount: tutorialResponseModel.tutorials.length,
                 gridDelegate:
                     //     SliverGridDelegateWithFixedCrossAxisCount(
                     //   crossAxisCount: countItem,
                     // ),
                     SliverGridDelegateWithFixedCrossAxisCount(
                         crossAxisCount: countItem,
                         crossAxisSpacing: 8.0,
                         mainAxisExtent: 520,
                         mainAxisSpacing: 8.0),
                 itemBuilder: (_, position) {
                   return _itemTutorial(position, context);
                 })

And we can compare this to make it a little more efficient as indicated here this would be a little optional but in this case as in several views I have double scroll, that is to say on the one hand in this view I think I don't have it but if this I am using as a parent element a single child scroll View and this also has its own scroll then to avoid precisely a problem with the double scroll:

physics: const BouncingScrollPhysics(), // evita problema de doble scroll

This is to define the size of our gripView cell:

mainAxisExtent: 520,

It would be from the item element how you want to see it some spacing:

crossAxisSpacing: 8.0,
mainAxisSpacing: 8.0

So that they do not appear all stuck together, this would be your personal matter and here we pass the position so that it builds based on the list that we obviously have defined at the class level, it builds the element just as I showed you here, the part I think that stands out the most is the Main Access extended which is to indicate the size of the cell:

mainAxisExtent: 520,

Note that even though it has more space available here than they are occupying, which I think would be recommended here because each cell has to at the end or each row has to be aligned in this way. So we do this by defining, as they say, a minimum size that will be available if I put less, the problems we are going to have are basically overflow since now the cell or the drawer where we are going to place our elements is going to be much smaller and we are going to have all this mess that Even the content part drags up, which obviously we do not want, so there you have to play with the size that you have to put. Obviously this would be optional, but if you do not put it, you will have the problem that I just showed you. Note that it does not give any good here, an error is given, sorry, obviously here there are some optional things, for example this one, you can look for more information on the internet and see what other parameters you can configure, but for example here if you do not put this one, notice that it does not give any error but everything will appear cut off since it will occupy the minimum space, which we do not want. What was mentioned before and well basically from what you can see we have an overflow there so we define it and with that we solve it.

- Andrés Cruz

En español

Andrés Cruz

Develop with Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter

Andrés Cruz In Udemy

I agree to receive announcements of interest about this Blog.

!Courses from!

10$

On Udemy

There are 4d 00:16!


Udemy

!Courses from!

4$

In Academy

View courses

!Books from!

1$

View books
¡Become an affiliate on Gumroad!