GridView 是 ScrollView 的子类,ScrollView 组合了 Scrollable 与 Viewport。 很多参数在 Fluter 滚动的基石 Scrollable 中已经讲过了。并且还有一些与 ListView 重合,可以先看下 Flutter ListView 详解,这里只讲下 GridView 独有的参数。

GridView 独有的参数其实只有一个 gridDelegate,gridDelegate 的作用是为 GridView 布局,制定每行几个 child,空白多少等。

SliverGridDelegate 是一个抽象类,它有两个子类,来完成布局。

SliverGridDelegateWithFixedCrossAxisCount

SliverGridDelegateWithFixedCrossAxisCount 会生成固定的列数。

看下它的参数。按默认 scrollDirection = Axis.vertical 的方式来解释。

  1. childAspectRatio 控制 child 的高宽比。
  2. crossAxisCount 是每行的列数。这个参数是这个子类的核心参数。
  3. crossAxisSpacing 是每列之间的空白
  4. mainAxisExtent 每个 child 的高度。
  5. mainAxisSpacing 每行之间的空白。

SliverGridDelegateWithMaxCrossAxisExtent

SliverGridDelegateWithMaxCrossAxisExtent 每个 child 的有最大宽度的限制。在限制范围内,会尽量宽。

  1. childAspectRatio 控制 child 的高宽比。
  2. maxCrossAxisExtent 每个 child 最大的宽度,只要不超过这个最大宽度,尽量宽。这个参数是这个子类的核心参数。
  3. crossAxisSpacing 是每列之间的空白
  4. mainAxisExtent 每个 child 的高度。
  5. mainAxisSpacing 每行之间的空白。

mainAxisExtent 的优先级高于 childAspectRatio,两个参数同时指定的时候,以 mainAxisExtent 为准。

列表数据很少

如果你的列表数据不是很多,可以一次给 GridView

GridView(
      gridDelegate:const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 5),
      children: List<Widget>.generate(50, (index) => ListTile(title: Text('$index'),)),
  );

列表数据很多

如果数据很多,不方便一次都给,可以用 itemBuilder,和 ListView 的 itemBuilder 一模一样,不再多说了。

GridView.builder(
      gridDelegate:const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 5),
      itemBuilder: (context, index) {
         return ListTile(title: Text('$index');
      },
    );

列数固定

数据可以一次性给出,并列表固定,内部用 SliverGridDelegateWithFixedCrossAxisCount 实现

GridView.count(
        crossAxisCount: 5,
        children: List<Widget>.generate(
            100, (index) => ListTile(title: Text('$index'))));

限定最大宽度

数据可以一次性给出,有宽度最大限制,内部用 ## SliverGridDelegateWithMaxCrossAxisExtent 实现。

GridView.extent(
        maxCrossAxisExtent: 100,
        children: List<Widget>.generate(
            100, (index) => ListTile(title: Text('$index'))));

自定义

这是灵活度最大的一种。

GridView.custom(
      gridDelegate:
          const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 5),
      childrenDelegate: SliverChildBuilderDelegate(
          (context, index) => ListTile(title: Text('$index'))),
    );

以上就是所有的 GridView的 构造方式,可以根据情况选用合适的构造函数。

去除空白。

因为 GridView 也是从 BoxScrollView 继承的,所以也会有和 ListView 同样的问题,可能会自动加上空白。去除也很简,指定 padding 为 0 即可。

GridView.count(
      padding: EdgeInsets.zero,
      crossAxisCount: 5,
);