Flutter.源码剖析 GridView flutter/packages/flutter/lib/src/widgets/scroll_view.dart/GridView


李俊才 的个人博客blog.csdn.net/qq_28550263

本文地址blog.csdn.net/qq_28550263…

本文供给 Flutter 框架中 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://www.6hu.cc/files/2023/11/220210-Om31Dr.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

SliverChildListDelegateSliverChildDelegate的一个完成,它运用一个固定的子部件列表来生成网格的子部件。这儿,children参数便是这个列表。另外,addAutomaticKeepAlivesaddRepaintBoundariesaddSemanticIndexes参数用于操控子部件的生命周期、是否添加重绘鸿沟和语义索引。

另外一方面,该结构函数种调用了其父类(BoxScrollView)的结构函数。semanticChildCount参数用于语义剖析,它表示GridView中的子部件数量。假如semanticChildCountnull,则运用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,
       );

从代码能够看到,这个结构函数接纳多个参数,其间最重要的两个参数是gridDelegateitemBuilder

  • gridDelegate是一个SliverGridDelegate目标,它决议了网格的布局。这是一个必需的参数。
  • itemBuilder是一个函数,它接纳一个 BuildContext 和一个索引,然后回来一个 Widget。这个函数只会被调用大于等于零且小于itemCount的索引。这是一个必需的参数。

GridView.builder结构函数的作业原理是,当需求烘托一个子部件时,它会调用itemBuilder函数,传入当前的BuildContext和子部件的索引,然后将回来的 组件 添加到网格中。这样,只有当子部件实际需求显现时,才会调用itemBuilder函数创立子部件。

此外,GridView.builder还接纳一些其他参数,如itemCountaddAutomaticKeepAlivesaddRepaintBoundariesaddSemanticIndexes,这些参数用于操控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完成网格的布局作业:gridDelegateSliverGridDelegate类型的目标,它是一个托付,担任界说网格的布局。具体来说,它决议了网格中每行的列数,以及每个格子的巨细。当GridView需求布局其子部件时,它会调用gridDelegate的办法来获取布局信息。所以,你能够说 gridDelegate 托付了网格的布局作业。
  • childrenDelegate完成子部件的创立作业:childrenDelegateSliverChildDelegate类型的目标,它是一个托付,担任创立网格的子部件。具体来说,当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结构函数会依据crossAxisCountmainAxisSpacingcrossAxisSpacingchildAspectRatio的值来布局网格,然后依据children列表来创立子部件。这使得你能够轻松地创立一个具有固定列数的网格视图。

GridView.count结构函数中,gridDelegate被设置为SliverGridDelegateWithFixedCrossAxisCount目标。这个目标会依据crossAxisCountmainAxisSpacingcrossAxisSpacingchildAspectRatio的值来布局网格。

childrenDelegate被设置为SliverChildListDelegate目标,它会依据传入的children列表来创立子部件。addAutomaticKeepAlivesaddRepaintBoundariesaddSemanticIndexes参数会传递给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结构函数会依据maxCrossAxisExtentmainAxisSpacingcrossAxisSpacingchildAspectRatio的值来布局网格,然后依据children列表来创立子部件。这使得你能够轻松地创立一个具有固定最大宽度的网格视图。

GridView.extent结构函数中,gridDelegate被设置为SliverGridDelegateWithMaxCrossAxisExtent目标。这个目标会依据maxCrossAxisExtentmainAxisSpacingcrossAxisSpacingchildAspectRatio的值来布局网格。

childrenDelegate被设置为SliverChildListDelegate目标,它会依据传入的children列表来创立子部件。addAutomaticKeepAlivesaddRepaintBoundariesaddSemanticIndexes参数会传递给SliverChildListDelegate,用于操控子部件的生命周期、是否添加重绘鸿沟和语义索引。

7. gridDelegate特点

gridDelegate 是 GridView 类中的一个特点,它的类型是 SliverGridDelegate。这个特点是一个托付(delegate),它决议了 GridView 中子部件的布局。

其源代码为:

  /// 一个托付,操控 [GridView] 中子部件的布局。
  ///
  /// [GridView],[GridView.builder] 和 [GridView.custom] 结构函数答应你清晰指定这个托付。其他结构函数隐式创立一个 [gridDelegate]。
  final SliverGridDelegate gridDelegate;

gridDelegate特点的效果便是界说GridView中子部件的布局。这使得GridView能够灵敏地习惯各种需求,例如创立固定列数的网格,或许创立具有固定最大宽度的网格。

SliverGridDelegate是一个抽象类,它有两个常用的子类:SliverGridDelegateWithFixedCrossAxisCountSliverGridDelegateWithMaxCrossAxisExtent

  • SliverGridDelegateWithFixedCrossAxisCount创立一个网格,其间穿插轴上有固定数量的格子。你能够指定穿插轴上的格子数量,以及格子之间的距离和宽高比。
  • SliverGridDelegateWithMaxCrossAxisExtent创立一个网格,其间穿插轴上的每个格子都有最大的宽度。你能够指定每个格子的最大宽度,以及格子之间的距离和宽高比。

GridViewGridView.builderGridView.custom结构函数中,你能够清晰指定gridDelegate。在其他结构函数中,gridDelegate会主动创立。

8. childrenDelegate特点

  /// 一个托付,为 [GridView] 供给子部件。
  ///
  /// [GridView.custom] 结构函数答应你清晰指定这个托付。其他结构函数创立一个包装给定子部件列表的 [childrenDelegate]。
  final SliverChildDelegate childrenDelegate;

能够看到,childrenDelegate特点类型为SliverChildDelegate。这个特点是一个托付(delegate) ,它决议了怎么为GridView创立子部件。

SliverChildDelegate是一个抽象类,它有两个常用的子类:SliverChildListDelegateSliverChildBuilderDelegate。其间:

  • 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是一个能够在网格中显现其子项的滑动列表。它需求两个参数:delegategridDelegate

  1. delegate参数是一个SliverChildDelegate目标,它决议了怎么创立和布局子项。在GridView中,这个参数的值是childrenDelegate特点。
  2. gridDelegate参数是一个SliverGridDelegate目标,它决议了网格的布局。在GridView中,这个参数的值是gridDelegate特点。