Image for post
Image for post

Flutter Widgets (Grid View) The Whole Picture

Murtaza Sulaihi
Nov 9 · 9 min read

I would like to take this opportunity to thank Flutter Community for adding me as a writer to their publication, I posted my last article on TabBar & TabBarView under Flutter Community publication and I received a lot more exposure to this article than previous ones that I had posted earlier. Now I feel the next step is that we Indian writers should be able to join the Medium Partner program soon, I read a lot about it in past few days that Medium uses Stripe as their payment method and Stripe is now available in India but still, for some reason, the Partner Program has not opened for Indian writers, hope that happens soon.

What is Grid View?

Image for post
Image for post

With the Grid View itself as an individual widget, there are 4 more options along with it which are…

  1. GridView.count
  2. GridView.builder
  3. GridView.custom
  4. GridView.extent

Let us first look at the GridView widget in itself in as much detail as possible then it will be easier to understand the other 4 options because where almost all the properties remain the same, only the required property differs in each one.

Grid View Widget

GridView(
scrollDirection: Axis.vertical, //default
reverse: false, //default
controller: ScrollController(),
primary: false,
physics: ,
shrinkWrap: true,
padding: EdgeInsets.all(5.0),
@required
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 5.0,
crossAxisSpacing: 5.0,
), OR
/* gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 125,
mainAxisSpacing: 5.0,
crossAxisSpacing: 5.0),*/
addAutomaticKeepAlives: true, //default
addRepaintBoundaries: true, //default
addSemanticIndexes: true, //default
semanticChildCount: 0,
cacheExtent: 0.0,
dragStartBehavior: DragStartBehavior.start,
clipBehavior: Clip.hardEdge,
keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.manual,
children: [] // List of Widgets
),

The following properties are important to understand while implementing the GridView.

  1. scrollDirection: Axis.Vertical or Axis.Horizontal. Changes the direction of the scroll either up down or left to right.
  2. reverse: false. If it is set to true the whole list will be reversed and scroll position will start the bottom.
  3. primary: false. It determines whether the primary scroll is associated with the parent or not.
  4. physics: It is used to determine the scrolling behaviour when a user is scrolling and has reached the start or the end of the list.
  5. shrinkWrap: false. By default, the value is false. The scrollable list takes as much as space for scrolling in the scroll direction, which may cause a memory leak and reducing the performance of the application. If it is set to true then the scrollable list will be as big as its children widgets allows it to be.
  6. padding(EdgeInsets): It is used to specify space around the whole list of widgets.
  7. crossAxisSpacing: To add space between the children on its crossAxis, mainly meaning the horizontal spacing between the widgets.
  8. mainAxisSpacing: To add space between the children on its mainAxis, mainly meaning the vertical spacing between the widgets.
  9. gridDelegate: This is a required property for GridView widget. I have already mentioned in the above constructor two widgets that are associated with gridDelegate property. The main difference between the two is: SliverGridDelegateWithFixedCrossAxis has a property crossAxisCount, which takes in a number according to which GridView will draw the number of columns. If it is 2 it will show 2 columns, if it is 4 it will show 4 columns. Now SliverGridDelegateWithMaxCrossAxisExtent has a property maxCrossAxisExtent which takes in double pixels. What it really means is that it divides the available space between the widgets and forms the columns accordingly. For example, if the width of the screen is 500 pixels, and maxCrossAxisExtent is set to 150 pixels, each child widget will get a max of 150 pixels or less and so the delegate will draw 4 columns giving each child 125 pixels of space.
Image for post
Image for post
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 5.0,
crossAxisSpacing: 5.0,
),
Image for post
Image for post
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 200,
mainAxisSpacing: 5.0,
crossAxisSpacing: 5.0),

10. keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.Manual. The user will have to manually hide or dismiss the keyboard, and if it is set on onDrag the as soon as the user starts scrolling the keyboard will be dismissed automatically.

GridView.count & GridView.extent

Let me explain…

GridView.count has a required property known as crossAxisCount, sound familiar… in GridView the required property gridDelegate takes in SliverGridDelegateWithFixedCrossAxis that has the same property known as crossAxisCount. So rather implementing that extra bit of complicated code you can directly use GridView.count which apparently is the most frequently used and highly advisable by flutter themselves. Check out the code and image below for reference.

GridView.count(
crossAxisCount: 3, @required
crossAxisSpacing: 5,
mainAxisSpacing: 5,
padding: EdgeInsets.all(10.0),
children: List.generate(
options.length,
(index) => GridOptions(
layout: options[index],
),
),
),
Image for post
Image for post
GridView.count with crossAxisCount set to 3

GridView.extent has a required property known as maxCrossAxisExtent which is similar to SliverGridDelegateWithMaxCrossAxisExtent for which I have already explained in detail how it works, please refer back to gridDelegate. For reference and understanding please look at the code below.

GridView.extent(
crossAxisSpacing: 5,
mainAxisSpacing: 5,
padding: EdgeInsets.all(10.0),
maxCrossAxisExtent: 200, @required
children: List.generate(
options.length,
(index) => GridOptions(
layout: options[index],
),
),
),

The images might look a lot similar in the whole article, I have just randomized colours and used icons and text to create the grid. So it is either 2 column grid or a 3 column grid. Now let’s go to the 3rd Gridview which is …

GridView.builder

The 3 important properties of GridView.builder are…

  1. itemCount: Amount of data or length of data that is going to be displayed
  2. gridDelegate: This one keeps popping up again and again, I really feel I do not have to repeat everything I just wrote earlier in this article about it, please refer back above.
  3. itemBuilder (BuildContext context, int index): If you have created list view in any of your application this is very similar, it is used to create the items in the grid. Let us take a look at an example to understand it.
GridView.builder(
shrinkWrap: true,
itemCount: options.length,
itemBuilder: (BuildContext context, int index) =>
GridOptions(layout: options[index]),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 5.0,
crossAxisSpacing: 5.0,
),
),
Image for post
Image for post
GridView.builder image

GridView.custom

  1. SliverChildListDelegate or SliverChildListDelegate.fixed.
  2. SliverChildBuilderDelegate.

Both are just another way to specify the data or the length of data that is going to be displayed in the GridView. SliverChildListDelegate takes in a List of children or you can specify a fixed number of children. SliverChildBuilderDelegate takes in the itemBuilder and index as we already discussed GridView.builder. Looking at the code for both above will give a better understanding as to how it works.

GridView.custom(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 5.0,
crossAxisSpacing: 5.0,
),
childrenDelegate: SliverChildListDelegate(_buildItems(20)),
),
---------------------------------------
List _buildItems(int count) {
List<Widget> listItems = List();

for (int i = 0; i < count; i++) {
listItems.add(
Card(
color: RandomColor().getColor(),
elevation: 5.0,
child: Center(
child: Text(
'Grid Item ${i.toString()}',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 22.0),
),
),
),
);
}
return listItems;
}
--------------------------------------
class RandomColor {
Random random = Random();
Color getColor() {
return Color.fromARGB(random.nextInt(255), random.nextInt(255),
random.nextInt(255), random.nextInt(255));
}
}

The above will produce the image given below.

Image for post
Image for post
GridView Custom image 1

And now let us look the at the code with SliverChildBuilderDelegate along with its image.

GridView.custom(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 5.0,
crossAxisSpacing: 5.0,
),
childrenDelegate: SliverChildBuilderDelegate(
(BuildContext context, int index) => GridOptions(
layout: options[index],
),),
),
Image for post
Image for post
GridView Custom with Builder

I am posting the rest of the code below which I have written for this article for anyone who wants to experiment and learn from it. If I have missed out anything please do write to and I would be happy to add it to the post.

class GridLayout {
final String title;
final IconData icon;

GridLayout({this.title, this.icon});
}
List<GridLayout> options = [
GridLayout(title: 'Home', icon: Icons.home),
GridLayout(title: 'Email', icon: Icons.email),
GridLayout(title: 'Alarm', icon: Icons.access_alarm),
GridLayout(title: 'Wallet', icon: Icons.account_balance_wallet),
GridLayout(title: 'Backup', icon: Icons.backup),
GridLayout(title: 'Book', icon: Icons.book),
GridLayout(title: 'Camera', icon: Icons.camera_alt_rounded),
GridLayout(title: 'Person', icon: Icons.person),
GridLayout(title: 'Print', icon: Icons.print),
GridLayout(title: 'Phone', icon: Icons.phone),
GridLayout(title: 'Notes', icon: Icons.speaker_notes),
GridLayout(title: 'Music', icon: Icons.music_note_rounded),
GridLayout(title: 'Car', icon: Icons.directions_car),
GridLayout(title: 'Bicycle', icon: Icons.directions_bike),
GridLayout(title: 'Boat', icon: Icons.directions_boat),
GridLayout(title: 'Bus', icon: Icons.directions_bus),
GridLayout(title: 'Train', icon: Icons.directions_railway),
GridLayout(title: 'Walk', icon: Icons.directions_walk),
GridLayout(title: 'Contact', icon: Icons.contact_mail),
GridLayout(title: 'Duo', icon: Icons.duo),
GridLayout(title: 'Hour', icon: Icons.hourglass_bottom),
GridLayout(title: 'Mobile', icon: Icons.mobile_friendly),
GridLayout(title: 'Message', icon: Icons.message),
GridLayout(title: 'Key', icon: Icons.vpn_key),
GridLayout(title: 'Wifi', icon: Icons.wifi),
GridLayout(title: 'Bluetooth', icon: Icons.bluetooth),
GridLayout(title: 'Smile', icon: Icons.sentiment_satisfied),
GridLayout(title: 'QR', icon: Icons.qr_code),
GridLayout(title: 'ADD', icon: Icons.add_box),
GridLayout(title: 'Link', icon: Icons.link),
];
class GridOptions extends StatelessWidget {
final GridLayout layout;
GridOptions({this.layout});
@override
Widget build(BuildContext context) {
return Card(
color: RandomColor().getColor(),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Icon(
layout.icon,
size: 40,
),
Text(
layout.title,
style: TextStyle(
fontSize: 24,
),
),
],
),
),
);
}
}

I have come to the end of my article, hopefully covering it all because as my header says and I have mentioned it in my very first article that I am trying to bring it all together, researching, experimenting and writing in as much as detail as possible so that beginners like me do not have to search the Google for every small piece of information on Flutter widgets. Hope you all readers have learnt something new from it and if you have please clap for me as encouragement and share this article with your friends and family.

leaving links below so that you can connect with me socially and also links to my previous stories that I have posted on Medium.

Flutter Community

Articles and Stories from the Flutter Community

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store