Building a photo grid view in Flutter

I'm a full-stack developer from South Africa 🇿🇦. I love writing about JavaScript, HTML and CSS.
Search for a command to run...

I'm a full-stack developer from South Africa 🇿🇦. I love writing about JavaScript, HTML and CSS.
No comments yet. Be the first to comment.
Most of you know me for my consistency, a golden arrow in my blog series. I've written 1000 articles in 1008 days! Almost an article a day, and my honeymoon was the only holiday I ever took. I'm super proud of this achievement; it has been a fantasti...

It's not the first time I'll be talking about community. I think it's an essential aspect of any successful tool. This shows in my previous explorations of Astro, Medusa, and now Vendure as well. All these products thrive in a super open, welcoming, ...

The cool part about Vendure is how easy it is to set up and how abstract each layer is. Basically, we get the following elements: External database Server Worker Admin UI Frontend While this is amazing, it also brings a bit of complexity when it co...

The previous article looked at customizing Vendure on a data and process level. In this article, we'll look at customizing emails, as they are often a big part of a webshop system. We'll be looking at two different layers of customization for customi...

Even though Vendure is a pretty significant project out of the box, in some cases, we might want to go in and modify some elements to work to our specific use case. In this article, I'll take a high-level look at some elements we can customize within...

In today's article, I'll be making a photo grid view in Flutter. It's much like you see in, for example, the Instagram app.
By the end of the article, you end up with a result like this:

To start with this, I'm using my previous article where we had a list view as the starting point.
Before we go and build this awesome app, let's first define our class that will keep our photo object.
class PhotoItem {
final String image;
final String name;
PhotoItem(this.image, this.name);
}
Nothing fancy. It will just keep an image and the name of the author. Feel free to add some more details to this.
Let's also create a list of photo items we can use in our grid view.
You can place the following code in the RouteOne widget.
final List<PhotoItem> _items = [
PhotoItem(
"https://images.pexels.com/photos/1772973/pexels-photo-1772973.png?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260",
"Stephan Seeber"),
PhotoItem(
"https://images.pexels.com/photos/1758531/pexels-photo-1758531.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=750&w=1260",
"Liam Gant"),
];
These are two items in our array. You can add as many as you need.
Now let's have a look at how we can render these items inside a grid view.
As the body of our RouteOne widget, we use a Gridview.builder, with that, we can use its own item builder to render each element.
body: GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisSpacing: 0,
mainAxisSpacing: 0,
crossAxisCount: 3,
),
itemCount: _items.length,
itemBuilder: (context, index) {
// Item rendering
},
),
Let's quickly see what's going on here. The builder can use a delegate that holds the setup of the grid. As you can see, I opted for no space, so all elements are touching each other. And set the count to three elements, meaning each row will hold three items.
Then we define the item count, as we also did for the Flutter list view.
And lastly, we have the item builder, which will loop over each item and can return a widget.
The return for this widget for us will look like this:
return new GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => RouteTwo(
image: _items[index].image,
name: _items[index].name),
),
);
},
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
fit: BoxFit.cover,
image: NetworkImage(_items[index].image),
),
),
),
);
As you can see, I'm wrapping my widget in a gesture detector. We want this to make each element clickable.
The child will be a container widget including the image for each photo item we defined.
As you can see above, we included a gesture detector to add a tap function. Meaning when we click an item in our grid view, it pushes to the navigation stack. We then pass the image and name to route two.
I've modified route two to be able to receive these two elements.
class RouteTwo extends StatelessWidget {
final String image;
final String name;
RouteTwo({Key? key, required this.image, required this.name})
: super(key: key);
}
As well as in the named route definition:
MaterialApp(debugShowCheckedModeBanner: false, initialRoute: '/', routes: {
'/': (context) => RouteOne(),
'/detail': (context) => RouteTwo(image: '', name: ''),
}),
Now all that's left is to render the image bigger and show the person's name who's picture this is.
body: Column(
children: [
AspectRatio(
aspectRatio: 1,
child: Container(
width: double.infinity,
child: Image(
image: NetworkImage(image),
),
),
),
Container(
margin: const EdgeInsets.all(20.0),
child: Center(
child: Text(
name,
style: TextStyle(fontSize: 40),
),
),
),
],
),
I'm using a column widget to render two child elements. One being an aspect ratio to maintain our image size, and one is the name of the person who owns this picture.
So with this article, we learned how to create a list of custom items, created a grid view in Flutter, and have the option to navigate to a detailed screen with more information.
If you want to view the full code example, visit the GitHub repo for this code.
Thank you for reading my blog. Feel free to subscribe to my email newsletter and connect on Facebook or Twitter