flutter 系列之:flutter 中常用的 GridView layout 详解
简介
GridView 是一个网格化的布局,如果在填充的过程中子组件超出了展示的范围的时候,那么 GridView 会自动滚动。
因为这个滚动的特性,所以 GridView 是一个非常好用的 Widget。今天我们一起来探索一下 GridView 这个 layout 组件的秘密。
GridView 详解
GridView 是一个可滚动的 view,也就是 ScrollView,事实上 GridView 继承自 BoxScrollView:
而它的父类 BoxScrollView,则是继承自 ScrollView:
可以看到 BoxScrollView 是一个抽象类,它有两个子类,分别是今天我们要讲的 GridView 和下期要讲的 ListView。
这两个组件的区别是 GridView 是一个 2D 的布局,而 ListView 是一个线性 layout 的布局。
作为 BoxScrollView 的子类,GridView 需要实现 buildChildLayout 方法如下所示:
这里 GridView 返回了一个 SliverGrid,这个 SliverGrid 中有两个属性,分别是 childrenDelegate 和 gridDelegate。
其中 gridDelegate 是一个 SliverGridDelegate 的实例,用来控制子组件在 GridView 中的布局。
childrenDelegate 是一个 SliverChildDelegate 的实例,用来生成 GridView 中的子组件。
这两个属性在 GridView 的构造函数中有使用,我们接下来会详细进行讲解。
GridView 的构造函数
GridView 有很多个构造函数,首先是包含所有参数的全参数构造函数:
在这个构造函数中,需要传入自定义的 gridDelegate,所以在构造函数中 gridDelegate 是 required 状态:
上面提到了 GridView 中的两个自定义属性,还有一个是 childrenDelegate,这个属性是根据传入的其他参数构造而成的,如下所示:
另外一个 GridView 的构造函数叫做 GridView.builder,这个构造函数和默认的构造函数的区别在于 childrenDelegate 的实现不同,我们来看下 GridView.builder 中 childrenDelegate 的实现:
对比发现,GridView.builder 中的 childrenDelegate 多了两个参数,分别是 itemBuilder 和 itemCount。
那么这个两个参数是做什么用的呢?
考虑一下一个有很多 chil 的 GridView,为了提升 GridView 的展示性能,我们不可能一下取出所有的 child 元素进行构建,而是会在滚动中进行动态创建和绘制,而这里的 itemCount 就是 child 的最大容量。
而 itemBuilder 就是一个动态创建 child 的创建器,从而满足了动态创建 child 的需求。
接下来的构造函数叫做 GridView.custom,因为叫做 custom,所以这个构造函数的 SliverGridDelegate 和 SliverChildDelegate 都是可以自定义的,也就是说这两个参数都可以从外部传入,所以这两个参数都是必须的:
GirdView 还有一个构造函数叫做 GridView.count,这里的 count 是指 GridView 可以指定 cross axis 中可以包含的组件个数,所以这里的 gridDelegate 使用的是一个 SliverGridDelegateWithFixedCrossAxisCount:
可以设置 crossAxisCount 的值。
最后一个 GridView 的构造函数叫做 GridView.extent,它和 count 的构造函数很类似,不过 extent 提供的是一个 maximum cross-axis extent,而不是一个固定的 count 值,所以这里的 gridDelegate 是一个 SliverGridDelegateWithMaxCrossAxisExtent 对象:
怎么理解呢?举个例子,如果 GirdView 是竖向滚动的,并且它的 width 是 400 pixels,如果这个时候 maxCrossAxisExtent 被设置为 120,那么一行只能有三列。我们可以通过调整 maxCrossAxisExtent 的值,来调整 view 的展示情况。
我们可以根据需要来选择对应的构造函数,从而满足我们不同的需求。
GridView 的使用
有了 GridView 的构造函数,GridView 使用起来就很简单了。
比如我们动态创建一个包含 image 的 child,组成一个 gridView:
这里的 buildChild 用来生成一个包含 Widget 的 list,如下所示:
最后将构造的 GridViewApp 放到 Scaffold 的 body 中运行:
最后我们可以得到下面的图像:
这里我们使用的是 GridView.extent 构造函数,大家可以自行尝试其他的构造函数。
总结
GridView 是一个我们在日常工作中经常会使用的组件,希望大家能够熟练掌握。
版权声明: 本文为 InfoQ 作者【程序那些事】的原创文章。
原文链接:【http://xie.infoq.cn/article/7043818bf8d159360f867fa21】。文章转载请联系作者。
评论