前言
开发移动端难免会碰到各种表格视图,flutter
当然也不例外,例如: ios 的 CollectionView
,android的GridView
等,flutter
就有一个Gridview
,flutter
中就有Gridview
,可展开可复用,使用极其方便,下面我们来接触一下吧
话不多说,先看一下是什么类型的是网格视图吧,至少萌新能够明白,如下图,多个表情包像网格一样排列
GridView基本属性
其基本属性和上一篇 ListView
一样,这里就直接 copy 过来了,此外还新增了一个必填的新属性gridDelegate
,其很关键
scrollDirection
: 列表的滚动方向,可选值有Axis
的horizontal
和vertical
,可以看到默认是垂直方向上滚动;shrinkWrap
:列表都存在该属性
,该属性默认为false
,表示内部滚动方向无穷长,不会完全计算全部内容长度;如果该属性设置为true
,会尽可能缩放滚动视图,一次性计算出所有内容,然后布局;一般嵌套滚动视图时内部设置为true,避免内部计算有问题,根据实际情况使用,一般不推荐,长列表过多计算可能会造成卡顿padding
: 列表内边距;controller
: 控制器,与列表滚动相关,比如监听列表的滚动事件(一般很少用);physics
: 列表滚动至边缘后继续拖动的物理效果
Android
与iOS
效果不同。默认Android
会呈现出一个波纹状(对应ClampingScrollPhysics
),而iOS
上有一个回弹的弹性效果(对应BouncingScrollPhysics
),需要设置成一样的,可以设置,注意BouncingScrollPhysics
不满屏不支持滚动。- 如果想不同的平台上呈现各自的效果,且无论内容是否占满,都支持滚动的话,可以使用
AlwaysScrollableScrollPhysics
(默认也是这个,如果两端都像ios一样滚动,参数parent: BouncingScrollPhysics
即可),它会根据不同平台自动选用各自的物理效果。 - 如果想禁用在边缘的拖动效果,那可以使用
NeverScrollableScrollPhysics
;
shrinkWrap
: 该属性将决定列表的长度是否仅包裹其内容的长度。当ListView
嵌在一个无限长的容器组件中时,shrinkWrap
必须为true,否则Flutter
会给出警告;itemExtent
: 子元素长度。当列表中的每一项长度是固定的情况下可以指定该值,有助于提高列表的性能(因为它可以帮助ListView
在未实际渲染子元素之前就计算出每一项元素的位置);cacheExtent
: 预渲染区域长度,ListView
会在其可视区域的两边留一个cacheExtent
长度的区域作为预渲染区域(对于ListView.build
或ListView.separated
构造函数创建的列表,不在可视区域和预渲染区域内的子元素不会被创建或会被销毁);children
: 容纳子元素的组件数组gridDelegate
: 其类型为一个接口,可以穿入两个实现了该接口的类SliverGridDelegateWithFixedCrossAxisCount
、SliverGridDelegateWithMaxCrossAxisExtent
SliverGridDelegateWithFixedCrossAxisCount
固定列数,取决于crossAxisCount,用的比较多,就像 UICollectionView 一样SliverGridDelegateWithMaxCrossAxisExtent
:最大列宽,根据间距和最大列宽是否填充满当前行而分成多列,以最少列满足占满横轴为依据;使用最大列宽计算,略大于当前屏幕,会缩小列宽为正好满足合适宽度;如果等于就使用当前列宽;如果刚好小于最大列宽,则会再新增一列,缩小列宽占满横屏;以上逻辑不会出现单个列宽小于等于最大列宽,以牺牲部分列宽来满足填充全屏
GridView基本使用
基础GridView
基础 GridView
使用,就像 ListView
一样
GridView(
//默认是垂直方向滑动,也可以竖直方向滑动,可以详细查看其它属性
scrollDirection: Axis.vertical,
//设置padding
padding: const EdgeInsets.all(10),
//设置滚动效果,这是比较常用的几个参数了
//都和ios一样支持回弹,不填默认ios回弹,android水波纹
physics: const AlwaysScrollableScrollPhysics(
//两端都拥有弹性效果,不填这里和默认physics不写一样
parent: BouncingScrollPhysics(),
),
//固定列数,取决于crossAxisCount
//用的比较多,就像UICollectionView一样,就以它为例
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2, //横轴有几个
mainAxisSpacing: 10, //主轴方向间距
crossAxisSpacing: 10, //次轴方向间距
childAspectRatio: 1, //单个网格宽长比,默认为1,如果是长方形必填
),
//最大列宽,根据间距和最大列宽是否填充满当前行而分成多列,以最少列满足占满横轴为依据
//使用最大列宽计算,略大于当前屏幕,会缩小列宽为正好满足合适宽度
//如果等于就使用当前列宽
//如果刚好小于最大列宽,则会再新增一列,缩小列宽占满横屏
//以上逻辑不会出现单个列宽小于等于最大列宽,以牺牲部分列宽来满足填充全屏
//用的比较少
// gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
// maxCrossAxisExtent: 120,
// mainAxisSpacing: 10, //主轴方向间距
// crossAxisSpacing: 10, //次轴方向间距
// ),
//用到这种情况是,内部不会复用,会以上面的形式来一行一行铺上
children: [0, 1, 3, 4, 5, 6, 7, 8, 9, 10].map((e) {
return Container(
color: Colors.green,
);
}).toList(),
);
SliverGridDelegateWithFixedCrossAxisCount
与 SliverGridDelegateWithMaxCrossAxisExtent
规则不太一样,下面简单以案例介绍一下
SliverGridDelegateWithFixedCrossAxisCount
设置 crossAxisCount
即一行固定有多少列,常见为2列,就这样较为规则的平铺下去,例如:10 张图片,每行放两个,除去间距,剩下空间平分给两个单元格视图,多出来的换行,然后继续平分,以此往复平铺
SliverGridDelegateWithMaxCrossAxisExtent
设置 maxCrossAxisExtent
最大列宽,即每个单元格视图最大这么宽,去除间距等因素,以最大列宽平分剩余空间,那么每列多少个怎么计算的呢,其以最大列宽为根据,对比当前屏幕尺寸,进行计算,如下所示
屏幕 375,边间距和网格间距都为10,那么一个单元格就占用 120,以最大列宽为基数,增加网格数量直到内容大于或者等于屏幕宽
这里以最大列宽增加到 3 倍发现达到条件,间距 40 + 120 * 3 = 400 > 375
,即列宽为3
此时列宽需要缩小以避免内容出屏,列宽为减去边距除以数量: (375 - 40) / 3 ≈ 111.67
,就得出的最适合的间距
注意
:顶部是为了方便查看不同效果用的 tabbar
GridView.count
SliverGridDelegateWithFixedCrossAxisCount
的语法糖
GridView.count(
//默认是垂直方向滑动,也可以竖直方向滑动,可以详细查看其它属性
scrollDirection: Axis.vertical,
//设置padding
padding: const EdgeInsets.all(10),
//设置滚动效果,这是比较常用的几个参数了
//都和ios一样支持回弹,不填默认ios回弹,android水波纹
physics: const AlwaysScrollableScrollPhysics(
//两端都拥有弹性效果,不填这里和默认physics不写一样
parent: BouncingScrollPhysics(),
),
crossAxisCount: 2,//设置列数,相当于将
crossAxisSpacing: 10,
mainAxisSpacing: 10,
//用到这种情况是,内部不会复用,会以上面的形式来一行一行铺上
children: [0, 1, 3, 4, 5, 6, 7, 8, 9, 10].map((e) {
return Container(
color: Colors.cyanAccent,
);
}).toList(),
);
GridView.extent
SliverGridDelegateWithMaxCrossAxisExtent
的语法糖
GridView.extent(
//默认是垂直方向滑动,也可以竖直方向滑动,可以详细查看其它属性
scrollDirection: Axis.vertical,
//设置padding
padding: const EdgeInsets.all(10),
//设置滚动效果,这是比较常用的几个参数了
//都和ios一样支持回弹,不填默认ios回弹,android水波纹
physics: const AlwaysScrollableScrollPhysics(
//两端都拥有弹性效果,不填这里和默认physics不写一样
parent: BouncingScrollPhysics(),
),
maxCrossAxisExtent: 120,//设置最大列宽
crossAxisSpacing: 10,
mainAxisSpacing: 10,
//用到这种情况是,内部不会复用,会以上面的形式来一行一行铺上
children: [0, 1, 3, 4, 5, 6, 7, 8, 9, 10].map((e) {
return Container(
color: Colors.blueAccent,
);
}).toList(),
);
GridView.builder
GridView.builder
复用语法糖,相当于 ios 的 UICollectionView
,适用于长列表
GridView.builder(
//默认是垂直方向滑动,也可以竖直方向滑动,可以详细查看其它属性
scrollDirection: Axis.vertical,
//设置padding
padding: const EdgeInsets.all(10),
//设置滚动效果,这是比较常用的几个参数了
//都和ios一样支持回弹,不填默认ios回弹,android水波纹
physics: const AlwaysScrollableScrollPhysics(
//两端都拥有弹性效果,不填这里和默认physics不写一样
parent: BouncingScrollPhysics(),
),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 10,
crossAxisSpacing: 10,
childAspectRatio: 0.75, //单个网格宽长比,默认为1,如果这里是垂直方向比较高
),
itemBuilder: (context, index) {
return Container(
color: Colors.red,
);
},
);