Introduction
GridView is a grid layout. If the sub-components exceed the display range during the filling process, the GridView will automatically scroll.
Because of this scrolling feature, GridView is a very useful Widget. Today, let's explore the secrets of the GridView layout component.
GridView details
GridView is a scrollable view, that is, ScrollView, in fact GridView inherits from BoxScrollView:
class GridView extends BoxScrollView
And its parent class BoxScrollView inherits from ScrollView:
abstract class BoxScrollView extends ScrollView
You can see that BoxScrollView is an abstract class that has two subclasses, namely GridView we will talk about today and ListView we will talk about in the next issue.
The difference between these two components is that GridView is a 2D layout, while ListView is a linear layout.
As a subclass of BoxScrollView, GridView needs to implement the buildChildLayout method as follows:
@override
Widget buildChildLayout(BuildContext context) {
return SliverGrid(
delegate: childrenDelegate,
gridDelegate: gridDelegate,
);
}
Here GridView returns a SliverGrid, which has two properties, childrenDelegate and gridDelegate.
The gridDelegate is an instance of SliverGridDelegate, which is used to control the layout of child components in the GridView.
childrenDelegate is an instance of SliverChildDelegate used to generate child components in GridView.
These two properties are used in the constructor of GridView, which we will explain in detail next.
GridView constructor
GridView has many constructors, the first is a full-parameter constructor with all parameters:
GridView({
Key? key,
Axis scrollDirection = Axis.vertical,
bool reverse = false,
ScrollController? controller,
bool? primary,
ScrollPhysics? physics,
bool shrinkWrap = false,
EdgeInsetsGeometry? padding,
required this.gridDelegate,
bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
bool addSemanticIndexes = true,
double? cacheExtent,
List<Widget> children = const <Widget>[],
int? semanticChildCount,
DragStartBehavior dragStartBehavior = DragStartBehavior.start,
Clip clipBehavior = Clip.hardEdge,
ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual,
String? restorationId,
})
In this constructor, you need to pass in a custom gridDelegate, so gridDelegate is required in the constructor:
required this.gridDelegate
Two custom properties in GridView are mentioned above, and one is childrenDelegate, which is constructed based on other parameters passed in, as shown below:
childrenDelegate = SliverChildListDelegate(
children,
addAutomaticKeepAlives: addAutomaticKeepAlives,
addRepaintBoundaries: addRepaintBoundaries,
addSemanticIndexes: addSemanticIndexes,
),
Another GridView constructor is called GridView.builder. The difference between this constructor and the default constructor is that the implementation of childrenDelegate is different. Let's take a look at the implementation of childrenDelegate in GridView.builder:
childrenDelegate = SliverChildBuilderDelegate(
itemBuilder,
childCount: itemCount,
addAutomaticKeepAlives: addAutomaticKeepAlives,
addRepaintBoundaries: addRepaintBoundaries,
addSemanticIndexes: addSemanticIndexes,
),
By comparison, it is found that the childrenDelegate in GridView.builder has two more parameters, itemBuilder and itemCount.
So what are these two parameters used for?
Consider a GridView with a lot of chicks. In order to improve the display performance of the GridView, we can't take out all the child elements for construction, but will dynamically create and draw during scrolling, and the itemCount here is the maximum capacity of the child.
The itemBuilder is a creator that dynamically creates children, thus meeting the needs of dynamically creating children.
The next constructor is called GridView.custom, because it is called custom, so both SliverGridDelegate and SliverChildDelegate of this constructor can be customized, which means that both parameters can be passed in from outside, so these two parameters are necessary:
required this.gridDelegate,
required this.childrenDelegate
GirdView also has a constructor called GridView.count, where count refers to the number of components that GridView can specify in the cross axis, so the gridDelegate here uses a SliverGridDelegateWithFixedCrossAxisCount:
gridDelegate = SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: crossAxisCount,
mainAxisSpacing: mainAxisSpacing,
crossAxisSpacing: crossAxisSpacing,
childAspectRatio: childAspectRatio,
),
The value of crossAxisCount can be set.
The last GridView constructor is called GridView.extent, which is similar to the count constructor, but the extent provides a maximum cross-axis extent instead of a fixed count value, so the gridDelegate here is a SliverGridDelegateWithMaxCrossAxisExtent object:
gridDelegate = SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: maxCrossAxisExtent,
mainAxisSpacing: mainAxisSpacing,
crossAxisSpacing: crossAxisSpacing,
childAspectRatio: childAspectRatio,
),
How to understand it? For example, if the GirdView is scrolled vertically and its width is 400 pixels, and if maxCrossAxisExtent is set to 120 at this time, then a row can only have three columns. We can adjust the display of the view by adjusting the value of maxCrossAxisExtent.
We can choose the corresponding constructor according to our needs to meet our different needs.
Use of GridView
With GridView's constructor, GridView is very simple to use.
For example, we dynamically create a child containing an image to form a gridView:
class GridViewApp extends StatelessWidget{
@override
Widget build(BuildContext context) {
return GridView.extent(
maxCrossAxisExtent: 100,
padding: const EdgeInsets.all(4),
mainAxisSpacing: 4,
crossAxisSpacing: 4,
children: buildChild(10));
}
The buildChild here is used to generate a list containing Widgets, as follows:
List<Widget> buildChild(int number) {
return List.generate(
number, (i) => Container(
child: Image.asset('images/head.jpg')));
}
Finally, put the constructed GridViewApp into the Scaffold's body to run:
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: GridViewApp(),
),
);
}
Finally we can get the following image:
Here we use the GridView.extent constructor, you can try other constructors by yourself.
Summarize
GridView is a component that we often use in our daily work, and I hope everyone can master it proficiently.
Example from this article: https://github.com/ddean2009/learn-flutter.git
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。