这是我参与更文挑战的第8天,活动详情查看: 更文挑战
前言
上一篇我们聊了 Flutter 中最常用的列表组件 ListView 的 4 种构建方式,这篇我们聊聊 GridView 的 5 种构建方式
和 2 种布局方式
以及 2 种子项构建方式
, 看下面👇🏻的脑图,我们来一步一步的看实现和效果。
- 统称为
522 方式
,哈哈哈
第一种 - GridView
构造
先看效果
再看源码
Flutter 好处之一就是随时可以查看有很详细注释的源码,看完源码我们就知道里面的实现了,这里先大概看看核心的内容。
这里我们只需要先关注一下 children、gridDelegate、childrenDelegate
这 3 个属性,至于这里的 SliverChildListDelegate
我们之后会聊到,这里先大概了解到我们传递过来的 children
传递到了 SliverChildListDelegate
里,那么肯定是最终通过这里布局子项的,我们继续往下看。
这里的 buildChildLayout
是不是很熟悉,上篇聊 ListView
的时候也看到了这个方法,最终子项的布局是通过这里实现的。GridView
也是同理,区别如下:
名称 | buildChildLayout 区别 |
---|---|
ListView | 1、使用 SliverList 构建 2、只有一个 delegate 参数 |
GridView | 1、使用 SliverGrid 构建 2、有delegate、gridDelegate 两个参数 |
怎么使用?
看了源码我们来看看使用就简单了,只需要构建一个 List<Widget>
传入到 children
和构建一个 gridDelegate
即可。
GridView(
// 次轴固定数量的 GridDelegate
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
// 数量设置3
crossAxisCount: 3,
// 主轴间距
mainAxisSpacing: 6,
// 次轴间距
crossAxisSpacing: 12,
// 子项宽高比率
childAspectRatio: 4 / 3,
),
// 构建子项,可以回看 ListView 篇
children: List.generate(100, (index) {
return getItem(index);
}),
)
竖屏 | 横屏 |
通过上面的对比,我们可以看到无论屏幕宽度如何都有如下特性:
- 都保持次轴上子项
数量是固定
的,最大(宽度)范围不固定 - 间距保持一致
- 子项宽高比一致
getItem 实现
这里很简单就是一个 Image
,如果有不懂的可以翻看 ListView 或其 我的《Flutter Widgets》专栏中对 Image 的介绍
/// 获取子项目
Widget getItem(int index) {
var item = listData[index % 5];
return Image.network(
item.url,
fit: BoxFit.cover,
);
}
第二种 - GridView.builder
构建
这里使用 itemBuilder
来构建子项集合,gridDelegate
我们这里使用的是 最大次轴「范围」的 GridDelegate
,你可以调整最大范围值看看效果即可对比出效果,详细的使用就看代码注释吧
GridView.builder(
// 最大次轴「范围」的 GridDelegate
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
// 最大次轴宽度(或高度)
maxCrossAxisExtent: 140,
// 主轴间距
mainAxisSpacing: 6,
// 次轴间距
crossAxisSpacing: 12,
// 子项宽高比率
childAspectRatio: 16 / 9,
),
itemBuilder: (context, index) {
return getItem(index);
},
// 子项数量
itemCount: 100,
)
对比效果
竖屏 | 横屏 |
通过上面的对比,我们可以看到无论屏幕宽度如何都有如下特性:
- 都保持次轴上子项
最大范围是固定
的,数量不固定 - 间距保持一致
- 子项宽高比一致
到这里我们也就对比出了 SliverGridDelegateWithFixedCrossAxisCount
和 SliverGridDelegateWithMaxCrossAxisExtent
这两个 GridDelegate 的区别,前者范围数量固定,后者范围固定。
第三种 - GridView.count
构建
GridView.count(
crossAxisCount: 6,
mainAxisSpacing: 6,
crossAxisSpacing: 12,
childAspectRatio: 4 / 3,
children: List.generate(100, (index) {
return getItem(index);
}),
)
看到这里就不用继续多说了吧,其实就是 SliverGridDelegateWithFixedCrossAxisCount
的封装呗,走我们看看源码是不是
果然和我们预想的一样,就是为了方便我们使用而封装了一下。
第四种 - GridView.extent
构建
GridView.extent(
// 最大次轴范围
maxCrossAxisExtent: 140,
mainAxisSpacing: 6,
crossAxisSpacing: 12,
childAspectRatio: 16 / 9,
children: List.generate(100, (index) {
return getItem(index);
}),
)
通过上面就可以推断出这里就是对 SliverGridDelegateWithMaxCrossAxisExtent
的封装,走看看源码验证一下
果然也是与我们预想的一样,看看效果吧
第五种 - GridView.custom
构建
最后这种看名字就是让我们自定义,其实最主要的就是自定义 gridDelegate
和 childrenDelegate
GridView.custom(
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 140,
mainAxisSpacing: 6,
crossAxisSpacing: 12,
childAspectRatio: 16 / 9,
),
childrenDelegate: SliverChildListDelegate(
List.generate(100, (index) {
return getItem(index);
}),
),
)
这里我们回顾之前总结一下这两个参数的常用构造类
参数名称 | 常用构建类与说明 |
---|---|
gridDelegate | SliverGridDelegateWithMaxCrossAxisExtent(次轴子项范围固定) SliverGridDelegateWithFixedCrossAxisCount(次轴子项数量固定) |
childrenDelegate | SliverChildListDelegate(列表构建) SliverChildBuilderDelegate(Builder方式构建) |
深夜更文不易,如有帮助请点赞👍🏻 给予最大的支持
源码仓库
基于 Flutter 🔥 最新版本
参考链接
关注专栏
- 此文章已收录到下面👇 的专栏,可以直接关注
- 更多文章继续阅读|系列文章持续更新
👏 欢迎点赞➕收藏➕关注,有任何问题随时在下面👇评论,我会第一时间回复哦