Flutter.源码分析GridViewflutter/packages/flutter/lib/src/widgets/scroll_view.dart/GridView
1. 类注释部分
/// 一个可滚动的二维组件数组。 /// /// {@youtube 560 315 https://www.youtube.com/watch?v=bLOtZDTm4H8} /// /// 网格的主轴方向是其滚动的方向([scrollDirection])。 /// /// 最常用的网格布局是 [GridView.count],它创建一个在交叉轴上有固定数量的瓷砖的布局,和 /// [GridView.extent],它创建一个瓷砖具有最大交叉轴范围的布局。自定义的 [SliverGridDelegate] 可以产生任意的2D /// 子组件布局,包括不对齐或重叠的布局。 /// /// 要创建一个具有大量(或无限)子组件的网格,使用 [GridView.builder] 构造函数,配合 /// [SliverGridDelegateWithFixedCrossAxisCount] 或 [SliverGridDelegateWithMaxCrossAxisExtent] /// 作为 [gridDelegate]。 /// /// 要使用自定义的 [SliverChildDelegate],使用 [GridView.custom]。 /// /// 要创建一个线性的子组件数组,使用 [ListView]。 /// /// 要控制滚动视图的初始滚动偏移,提供一个设置了 [ScrollController.initialScrollOffset] 属性的 [controller]。 /// /// ## 转换到 [CustomScrollView] /// /// [GridView] 基本上是一个在其 [CustomScrollView.slivers] 属性中有一个 [SliverGrid] 的 [CustomScrollView]。 /// /// 如果 [GridView] 不再足够,例如因为滚动视图要同时有一个网格和一个列表,或者因为网格要与 [SliverAppBar] 结合等, /// 那么从使用 [GridView] 到直接使用 [CustomScrollView] 的代码移植是直接的。 /// /// [GridView] 上的 [key],[scrollDirection],[reverse],[controller],[primary],[physics], /// 和 [shrinkWrap] 属性直接映射到 [CustomScrollView] 上同名的属性。 /// /// [CustomScrollView.slivers] 属性应该是一个只包含 [SliverGrid] 的列表。 /// /// [GridView] 上的 [childrenDelegate] 属性对应于 [SliverGrid.delegate] 属性, /// 而 [GridView] 上的 [gridDelegate] 属性对应于 [SliverGrid.gridDelegate] 属性。 /// /// [GridView],[GridView.count] 和 [GridView.extent] /// 构造函数的 `children` 参数对应于 [childrenDelegate] 是一个具有相同参数的 [SliverChildListDelegate]。 /// [GridView.builder] 构造函数的 `itemBuilder` 和 `childCount` 参数对应于 [childrenDelegate] 是一个具有匹配参数的 [SliverChildBuilderDelegate]。 /// /// [GridView.count] 和 [GridView.extent] 构造函数创建 /// 自定义网格委托,并在 [SliverGrid] 上有同名的构造函数以便于转换:分别是 [SliverGrid.count] 和 /// [SliverGrid.extent]。 /// /// [padding] 属性对应于在 [CustomScrollView.slivers] 属性中有一个 [SliverPadding] 而不是网格本身, /// 并且 [SliverGrid] 是 [SliverPadding] 的子组件。 /// /// 一旦代码被移植为使用 [CustomScrollView],其他的 slivers,如 [SliverList] 或 [SliverAppBar], /// 可以放在 [CustomScrollView.slivers] 列表中。 /// /// {@tool snippet} /// 这个示例演示了如何创建一个有两列的 [GridView]。子组件之间的间距使用 `crossAxisSpacing` 和 `mainAxisSpacing` 属性设置。 /// /// ![GridView 显示了两列的六个具有不同背景颜色的子组件](https://flutter.github.io/assets-for-api-docs/assets/widgets/grid_view.png) /// /// ```dart /// GridView.count( /// primary: false, /// padding: const EdgeInsets.all(20), /// crossAxisSpacing: 10, /// mainAxisSpacing: 10, /// crossAxisCount: 2, /// children: <Widget>[ /// Container( /// padding: const EdgeInsets.all(8), /// color: Colors.teal[100], /// child: const Text("He'd have you all unravel at the"), /// ), /// Container( /// padding: const EdgeInsets.all(8), /// color: Colors.teal[200], /// child: const Text('Heed not the rabble'), /// ), /// Container( /// padding: const EdgeInsets.all(8), /// color: Colors.teal[300], /// child: const Text('Sound of screams but the'), /// ), /// Container( /// padding: const EdgeInsets.all(8), /// color: Colors.teal[400], /// child: const Text('Who scream'), /// ), /// Container( /// padding: const EdgeInsets.all(8), /// color: Colors.teal[500], /// child: const Text('Revolution is coming...'), /// ), /// Container( /// padding: const EdgeInsets.all(8), /// color: Colors.teal[600], /// child: const Text('Revolution, they...'), /// ), /// ], /// ) /// ``` /// {@end-tool} /// /// {@tool snippet} /// 这个示例展示了如何使用 [CustomScrollView] 和 [SliverGrid] 创建与上一个示例相同的网格。 /// /// ![CustomScrollView 包含一个 SliverGrid,它显示了两列的六个具有不同背景颜色的子组件](https://flutter.github.io/assets-for-api-docs/assets/widgets/grid_view_custom_scroll.png) /// /// ```dart /// CustomScrollView( /// primary: false, /// slivers: <Widget>[ /// SliverPadding( /// padding: const EdgeInsets.all(20), /// sliver: SliverGrid.count( /// crossAxisSpacing: 10, /// mainAxisSpacing: 10, /// crossAxisCount: 2, /// children: <Widget>[ /// Container( /// padding: const EdgeInsets.all(8), /// color: Colors.green[100], /// child: const Text("He'd have you all unravel at the"), /// ), /// Container( /// padding: const EdgeInsets.all(8), /// color: Colors.green[200], /// child: const Text('Heed not the rabble'), /// ), /// Container( /// padding: const EdgeInsets.all(8), /// color: Colors.green[300], /// child: const Text('Sound of screams but the'), /// ), /// Container( /// padding: const EdgeInsets.all(8), /// color: Colors.green[400], /// child: const Text('Who scream'), /// ), /// Container( /// padding: const EdgeInsets.all(8), /// color: Colors.green[500], /// child: const Text('Revolution is coming...'), /// ), /// Container( /// padding: const EdgeInsets.all(8), /// color: Colors.green[600], /// child: const Text('Revolution, they...'), /// ), /// ], /// ), /// ), /// ], /// ) /// ``` /// {@end-tool} /// /// 默认情况下,[GridView] 会自动填充网格的滚动边界的限制,以避免 [MediaQuery] 的填充指示的部分遮挡。 /// 要避免这种行为,用零 [padding] 属性覆盖。 /// /// {@tool snippet} /// 下面的示例演示了如何使用 [MediaQuery.removePadding] 覆盖默认的顶部填充。 /// /// ```dart /// Widget myWidget(BuildContext context) { /// return MediaQuery.removePadding( /// context: context, /// removeTop: true, /// child: GridView.builder( /// gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( /// crossAxisCount: 3, /// ), /// itemCount: 300, /// itemBuilder: (BuildContext context, int index) { /// return Card( /// color: Colors.amber, /// child: Center(child: Text('$index')), /// ); /// } /// ), /// ); /// } /// ``` /// {@end-tool} /// /// {@tool dartpad} /// 这个示例展示了在 [GridView] 或 [ListView] 中 [ListTile] 选择的自定义实现。 /// 长按任何 ListTile 以启用选择模式。 /// /// ** 查看 examples/api/lib/widgets/scroll_view/list_view.0.dart 中的代码 ** /// {@end-tool} /// /// 另请参阅: /// /// * [SingleChildScrollView],这是一个有一个单一子组件的可滚动组件。 /// * [ListView],这是一个可滚动的,线性的组件列表。 /// * [PageView],这是一个滚动的子组件列表,每个子组件都是视口的大小。 /// * [CustomScrollView],这是一个创建自定义滚动效果的可滚动组件。 /// * [SliverGridDelegateWithFixedCrossAxisCount],它创建一个在交叉轴上有固定数量的瓷砖的布局。 /// * [SliverGridDelegateWithMaxCrossAxisExtent],它创建一个瓷砖具有最大交叉轴范围的布局。 /// * [ScrollNotification] 和 [NotificationListener],它们可以用来观察滚动位置,而无需使用 [ScrollController]。 /// * [布局组件目录](https://flutter.dev/widgets/layout/)。 class GridView extends BoxScrollView { // ... }
2. 默认构造函数部分
/// 使用自定义 [SliverGridDelegate] 创建一个可滚动的二维组件数组。 /// /// [gridDelegate] 参数不能为空。 /// /// `addAutomaticKeepAlives` 参数对应于 [SliverChildListDelegate.addAutomaticKeepAlives] 属性。 /// `addRepaintBoundaries` 参数对应于 [SliverChildListDelegate.addRepaintBoundaries] 属性。两者都不能为 null。 GridView({ super.key, super.scrollDirection, super.reverse, super.controller, super.primary, super.physics, super.shrinkWrap, super.padding, required this.gridDelegate, bool addAutomaticKeepAlives = true, bool addRepaintBoundaries = true, bool addSemanticIndexes = true, super.cacheExtent, List<Widget> children = const <Widget>[], int? semanticChildCount, super.dragStartBehavior, super.clipBehavior, super.keyboardDismissBehavior, super.restorationId, }) : childrenDelegate = SliverChildListDelegate( children, addAutomaticKeepAlives: addAutomaticKeepAlives, addRepaintBoundaries: addRepaintBoundaries, addSemanticIndexes: addSemanticIndexes, ), super( semanticChildCount: semanticChildCount ?? children.length, );
从 GridView 默认构造函数的结构可以看出,它本质上不过是创建了一个 SliverChildListDelegate 对象并赋值给 childrenDelegate
。
而 SliverChildListDelegate 是 SliverChildDelegate 的一个实现,它使用一个固定的子部件列表来生成网格的子部件。这里,children
参数就是这个列表。另外,addAutomaticKeepAlives
、addRepaintBoundaries
和 addSemanticIndexes
参数用于控制子部件的生命周期、是否添加重绘边界和语义索引。
另外一方面,该构造函数种调用了其父类(BoxScrollView)的构造函数。semanticChildCount
参数用于语义分析,它表示 GridView 中的子部件数量。如果 semanticChildCount
为 null
,则使用 children.length
作为默认值。
3. GridView.builder构造函数部分
GridView.builder 构造函数用于创建一个可以滚动的,按需创建的二维部件数组。这对于具有大量(或无限)子部件的网格视图非常合适,因为构建器只会为实际可见的子部件调用。
/// 创建一个可滚动的,按需创建的二维部件数组。 /// /// 对于具有大量(或无限)子部件的网格视图,此构造函数是合适的,因为构建器只会为实际可见的子部件调用。 /// /// 提供非空的 `itemCount` 可以提高 [GridView] 估计最大滚动范围的能力。 /// /// `itemBuilder` 只会被调用大于等于零且小于 `itemCount` 的索引。 /// /// {@macro flutter.widgets.ListView.builder.itemBuilder} /// /// {@macro flutter.widgets.PageView.findChildIndexCallback} /// /// [gridDelegate] 参数是必需的。 /// /// `addAutomaticKeepAlives` 参数对应于 [SliverChildBuilderDelegate.addAutomaticKeepAlives] 属性。 /// `addRepaintBoundaries` 参数对应于 [SliverChildBuilderDelegate.addRepaintBoundaries] 属性。 /// `addSemanticIndexes` 参数对应于 [SliverChildBuilderDelegate.addSemanticIndexes] 属性。 GridView.builder({ super.key, super.scrollDirection, super.reverse, super.controller, super.primary, super.physics, super.shrinkWrap, super.padding, required this.gridDelegate, required NullableIndexedWidgetBuilder itemBuilder, ChildIndexGetter? findChildIndexCallback, int? itemCount, bool addAutomaticKeepAlives = true, bool addRepaintBoundaries = true, bool addSemanticIndexes = true, super.cacheExtent, int? semanticChildCount, super.dragStartBehavior, super.keyboardDismissBehavior, super.restorationId, super.clipBehavior, }) : childrenDelegate = SliverChildBuilderDelegate( itemBuilder, findChildIndexCallback: findChildIndexCallback, childCount: itemCount, addAutomaticKeepAlives: addAutomaticKeepAlives, addRepaintBoundaries: addRepaintBoundaries, addSemanticIndexes: addSemanticIndexes, ), super( semanticChildCount: semanticChildCount ?? itemCount, );
从代码可以看到,这个构造函数接收多个参数,其中最重要的两个参数是 gridDelegate
和 itemBuilder
。
gridDelegate
是一个 SliverGridDelegate 对象,它决定了网格的布局。这是一个必需的参数。itemBuilder
是一个函数,它接收一个 BuildContext 和一个索引,然后返回一个 Widget。这个函数只会被调用大于等于零且小于itemCount
的索引。这是一个必需的参数。
GridView.builder 构造函数的工作原理是,当需要渲染一个子部件时,它会调用 itemBuilder
函数,传入当前的 BuildContext 和子部件的索引,然后将返回的 组件 添加到网格中。这样,只有当子部件实际需要显示时,才会调用 itemBuilder
函数创建子部件。
此外,GridView.builder 还接收一些其他参数,如 itemCount
、addAutomaticKeepAlives
、addRepaintBoundaries
和 addSemanticIndexes
,这些参数用于控制 GridView 的行为。
最后,GridView.builder 通过 SliverChildBuilderDelegate 创建了一个 childrenDelegate
,然后传递给 GridView 的父类构造函数。这个 childrenDelegate
决定了如何为 GridView 创建子部件。
4. GridView.custom 构造函数部分
/// 使用自定义 [SliverGridDelegate] 和自定义 [SliverChildDelegate] 创建一个可滚动的二维部件数组。 /// /// 要使用 [IndexedWidgetBuilder] 回调来构建子部件,可以使用 [SliverChildBuilderDelegate] 或使用 [GridView.builder] 构造函数。 /// /// [gridDelegate] 和 [childrenDelegate] 参数不能为空。 const GridView.custom({ super.key, super.scrollDirection, super.reverse, super.controller, super.primary, super.physics, super.shrinkWrap, super.padding, required this.gridDelegate, required this.childrenDelegate, super.cacheExtent, super.semanticChildCount, super.dragStartBehavior, super.keyboardDismissBehavior, super.restorationId, super.clipBehavior, });
GridView.custom 构造函数用于创建一个可滚动的二维部件数组,它允许你完全自定义 **SliverGridDelegate **和 SliverChildDelegate。
- SliverGridDelegate 决定了网格的布局,例如每行的列数、每个子部件的尺寸等。
- SliverChildDelegate 决定了如何生成网格的子部件。你可以使用 SliverChildBuilderDelegate 来按需生成子部件,或者使用 SliverChildListDelegate 来生成一个固定列表的子部件。
GridView.custom 构造函数接收多个参数,其中最重要的两个参数是 gridDelegate 和 childrenDelegate,这两个参数都是必需的。
gridDelegate
是一个 SliverGridDelegate 对象,它决定了网格的布局。childrenDelegate
是一个 SliverChildDelegate 对象,它决定了如何为 GridView 创建子部件。
GridView.custom 会根据
gridDelegate
的设置来布局网格,然后调用childrenDelegate
来生成子部件。这样,你可以完全自定义 GridView 的布局和子部件的生成方式。
在这个构造函数的实现种:
gridDelegate
实现网格的布局工作:gridDelegate
是 SliverGridDelegate 类型的对象,它是一个委托,负责定义网格的布局。具体来说,它决定了网格中每行的列数,以及每个格子的大小。当 GridView 需要布局其子部件时,它会调用gridDelegate
的方法来获取布局信息。所以,你可以说 gridDelegate 委托了网格的布局工作。childrenDelegate
实现子部件的创建工作:childrenDelegate
是 SliverChildDelegate 类型的对象,它是一个委托,负责创建网格的子部件。具体来说,当 GridView 需要渲染一个新的子部件时,它会调用childrenDelegate
的方法来创建这个子部件。
5. GridView.count 构造函数部分
GridView.count 构造函数用于创建一个可滚动的二维部件数组,其中交叉轴上有固定数量的格子。这个构造函数接收多个参数,其中最重要的是
crossAxisCount
,它决定了交叉轴上的格子数量。此外,还可以设置 mainAxisSpacing 和 crossAxisSpacing 来控制格子之间的间距,以及 childAspectRatio 来控制每个格子的宽高比。
该构造函数的代码为:
/// 创建一个可滚动的,二维部件数组,交叉轴上有固定数量的格子。 /// /// 使用 [SliverGridDelegateWithFixedCrossAxisCount] 作为 [gridDelegate]。 /// /// `addAutomaticKeepAlives` 参数对应于 [SliverChildListDelegate.addAutomaticKeepAlives] 属性。 /// `addRepaintBoundaries` 参数对应于 [SliverChildListDelegate.addRepaintBoundaries] 属性。两者都不能为空。 /// /// 另请参阅: /// /// * [SliverGrid.count],[SliverGrid] 的等效构造函数。 GridView.count({ super.key, super.scrollDirection, super.reverse, super.controller, super.primary, super.physics, super.shrinkWrap, super.padding, required int crossAxisCount, double mainAxisSpacing = 0.0, double crossAxisSpacing = 0.0, double childAspectRatio = 1.0, bool addAutomaticKeepAlives = true, bool addRepaintBoundaries = true, bool addSemanticIndexes = true, super.cacheExtent, List<Widget> children = const <Widget>[], int? semanticChildCount, super.dragStartBehavior, super.keyboardDismissBehavior, super.restorationId, super.clipBehavior, }) : gridDelegate = SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: crossAxisCount, mainAxisSpacing: mainAxisSpacing, crossAxisSpacing: crossAxisSpacing, childAspectRatio: childAspectRatio, ), childrenDelegate = SliverChildListDelegate( children, addAutomaticKeepAlives: addAutomaticKeepAlives, addRepaintBoundaries: addRepaintBoundaries, addSemanticIndexes: addSemanticIndexes, ), super( semanticChildCount: semanticChildCount ?? children.length, );
从代码可以看出,GridView.count 构造函数会根据 crossAxisCount
、mainAxisSpacing
、crossAxisSpacing
和 childAspectRatio
的值来布局网格,然后根据 children
列表来创建子部件。这使得你可以轻松地创建一个具有固定列数的网格视图。
在 GridView.count 构造函数中,gridDelegate
被设置为 SliverGridDelegateWithFixedCrossAxisCount 对象。这个对象会根据 crossAxisCount
、mainAxisSpacing
、crossAxisSpacing
和 childAspectRatio
的值来布局网格。
childrenDelegate
被设置为 SliverChildListDelegate 对象,它会根据传入的 children
列表来创建子部件。addAutomaticKeepAlives
、addRepaintBoundaries
和 addSemanticIndexes
参数会传递给 SliverChildListDelegate,用于控制子部件的生命周期、是否添加重绘边界和语义索引。
6. GridView.extent构造函数部分
GridView.extent 构造函数用于创建一个可滚动的二维部件数组,其中交叉轴上的每个格子都有最大的宽度。
这个构造函数接收多个参数,其中最重要的是 maxCrossAxisExtent,它决定了交叉轴上每个格子的最大宽度。此外,还可以设置 mainAxisSpacing 和 crossAxisSpacing 来控制格子之间的间距,以及 childAspectRatio 来控制每个格子的宽高比。
该构造函数源码为:
/// 创建一个可滚动的,二维部件数组,每个格子在交叉轴上都有最大的范围。 /// /// 使用 [SliverGridDelegateWithMaxCrossAxisExtent] 作为 [gridDelegate]。 /// /// `addAutomaticKeepAlives` 参数对应于 [SliverChildListDelegate.addAutomaticKeepAlives] 属性。 /// `addRepaintBoundaries` 参数对应于 [SliverChildListDelegate.addRepaintBoundaries] 属性。两者都不能为空。 /// /// 另请参阅: /// /// * [SliverGrid.extent],[SliverGrid] 的等效构造函数。 GridView.extent({ super.key, super.scrollDirection, super.reverse, super.controller, super.primary, super.physics, super.shrinkWrap, super.padding, required double maxCrossAxisExtent, double mainAxisSpacing = 0.0, double crossAxisSpacing = 0.0, double childAspectRatio = 1.0, bool addAutomaticKeepAlives = true, bool addRepaintBoundaries = true, bool addSemanticIndexes = true, super.cacheExtent, List<Widget> children = const <Widget>[], int? semanticChildCount, super.dragStartBehavior, super.keyboardDismissBehavior, super.restorationId, super.clipBehavior, }) : gridDelegate = SliverGridDelegateWithMaxCrossAxisExtent( maxCrossAxisExtent: maxCrossAxisExtent, mainAxisSpacing: mainAxisSpacing, crossAxisSpacing: crossAxisSpacing, childAspectRatio: childAspectRatio, ), childrenDelegate = SliverChildListDelegate( children, addAutomaticKeepAlives: addAutomaticKeepAlives, addRepaintBoundaries: addRepaintBoundaries, addSemanticIndexes: addSemanticIndexes, ), super( semanticChildCount: semanticChildCount ?? children.length, );
GridView.extent 构造函数会根据 maxCrossAxisExtent
、mainAxisSpacing
、crossAxisSpacing
和 childAspectRatio
的值来布局网格,然后根据 children
列表来创建子部件。这使得你可以轻松地创建一个具有固定最大宽度的网格视图。
在 GridView.extent 构造函数中,gridDelegate
被设置为 SliverGridDelegateWithMaxCrossAxisExtent 对象。这个对象会根据 maxCrossAxisExtent
、mainAxisSpacing
、crossAxisSpacing
和 childAspectRatio
的值来布局网格。
childrenDelegate
被设置为 SliverChildListDelegate 对象,它会根据传入的 children
列表来创建子部件。addAutomaticKeepAlives
、addRepaintBoundaries
和 addSemanticIndexes
参数会传递给 SliverChildListDelegate,用于控制子部件的生命周期、是否添加重绘边界和语义索引。
7. gridDelegate属性
gridDelegate 是 GridView 类中的一个属性,它的类型是 SliverGridDelegate。这个属性是一个委托(delegate),它决定了 GridView 中子部件的布局。
其源代码为:
/// 一个委托,控制 [GridView] 中子部件的布局。 /// /// [GridView],[GridView.builder] 和 [GridView.custom] 构造函数允许你明确指定这个委托。其他构造函数隐式创建一个 [gridDelegate]。 final SliverGridDelegate gridDelegate;
gridDelegate
属性的作用就是定义 GridView 中子部件的布局。这使得 GridView 可以灵活地适应各种需求,例如创建固定列数的网格,或者创建具有固定最大宽度的网格。
SliverGridDelegate 是一个抽象类,它有两个常用的子类:SliverGridDelegateWithFixedCrossAxisCount 和 SliverGridDelegateWithMaxCrossAxisExtent。
- SliverGridDelegateWithFixedCrossAxisCount 创建一个网格,其中交叉轴上有固定数量的格子。你可以指定交叉轴上的格子数量,以及格子之间的间距和宽高比。
- SliverGridDelegateWithMaxCrossAxisExtent 创建一个网格,其中交叉轴上的每个格子都有最大的宽度。你可以指定每个格子的最大宽度,以及格子之间的间距和宽高比。
在 GridView、GridView.builder 和 GridView.custom 构造函数中,你可以明确指定 gridDelegate
。在其他构造函数中,gridDelegate
会自动创建。
8. childrenDelegate属性
/// 一个委托,为 [GridView] 提供子部件。 /// /// [GridView.custom] 构造函数允许你明确指定这个委托。其他构造函数创建一个包装给定子部件列表的 [childrenDelegate]。 final SliverChildDelegate childrenDelegate;
可以看到,childrenDelegate
属性类型为 SliverChildDelegate。这个属性是一个 委托(delegate),它决定了如何为 GridView 创建子部件。
SliverChildDelegate 是一个抽象类,它有两个常用的子类:SliverChildListDelegate 和 SliverChildBuilderDelegate。其中:
- SliverChildListDelegate 接收一个固定长度的子部件列表,然后按照列表顺序创建子部件。
- SliverChildBuilderDelegate 接收一个构建函数,然后按需创建子部件。这对于具有大量子部件的 GridView 非常有用,因为只有当子部件实际需要显示时,才会调用构建函数创建子部件。
在 GridView.custom 构造函数中,你可以明确指定 childrenDelegate
。在其他构造函数中,childrenDelegate
会自动创建,通常是包装给定的子部件列表。
因此,childrenDelegate 属性的作用就是定义如何为 GridView 创建子部件。这使得 GridView 可以灵活地适应各种需求,例如创建固定数量的子部件,或者按需创建子部件。
9. buildChildLayout方法
buildChildLayout 负责构建 GridView 的子布局。
@override Widget buildChildLayout(BuildContext context) { return SliverGrid( delegate: childrenDelegate, gridDelegate: gridDelegate, ); }
buildChildLayout
方法的作用就是根据 GridView 的属性来创建一个 SliverGrid 对象,这个 SliverGrid 对象定义了 GridView 的子布局。
这个方法接收一个 BuildContext 对象作为参数,然后返回一个 SliverGrid 对象。
SliverGrid 是一个可以在网格中显示其子项的滑动列表。它需要两个参数:delegate
和 gridDelegate
:
delegate
参数是一个 SliverChildDelegate 对象,它决定了如何创建和布局子项。在 GridView 中,这个参数的值是childrenDelegate
属性。gridDelegate
参数是一个 SliverGridDelegate 对象,它决定了网格的布局。在 GridView 中,这个参数的值是gridDelegate
属性。