网格布局是一种常见的布局类型,GridView
组件正是实现了网格布局的组件。
主要通过Count、extent、custom、builder
构造列表。有内边距、是否反向、滑动控制器等属性。
四个属性使用场景,Count、extent、custom
适用于子布局较少时使用。可能会用到上拉刷新,数据较多时,则使用builder
属性。其构造:
GridView({
super.key,
super.scrollDirection,//滚动方向
super.reverse,
super.controller,
super.primary,
super.physics,
super.shrinkWrap,
super.padding,
required this.gridDelegate,//控制GridView子组件如何排列(layout)
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,
})
SliverGridDelegate
是一个抽象类,定义了GridView Layout
相关接口,子类需要通过实现它们来实现具体的布局算法。Flutter中提供了两个SliverGridDelegate
的子类SliverGridDelegateWithFixedCrossAxisCount
和SliverGridDelegateWithMaxCrossAxisExtent
。
SliverGridDelegateWithFixedCrossAxisCount
该子类实现了一个横轴为固定数量子元素的layout算法,其构造函数为:
const SliverGridDelegateWithFixedCrossAxisCount({
required this.crossAxisCount,//横轴子元素的数量
this.mainAxisSpacing = 0.0,//主轴方向的间距
this.crossAxisSpacing = 0.0,//横轴方向子元素的间距
this.childAspectRatio = 1.0,//子元素在横轴长度和主轴长度的比例
this.mainAxisExtent,
})
例子:
import 'package:flutter/material.dart';
class GridViewPage extends StatefulWidget {
const GridViewPage({Key? key}) : super(key: key);
@override
State<GridViewPage> createState() => _GridViewPageState();
}
class _GridViewPageState extends State<GridViewPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('GridView网格组件'),),
body: GridView(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,//横轴3个
childAspectRatio: 1.0,//宽高比1
),
children: const [
Icon(Icons.ac_unit),
Icon(Icons.apple),
Icon(Icons.android),
Icon(Icons.access_time_filled),
Icon(Icons.share_location),
Icon(Icons.star_half),
],
),
);
}
}
SliverGridDelegateWithMaxCrossAxisExtent
该子类实现了一个横轴子元素为固定最大长度的layout算法,其构造:
const SliverGridDelegateWithMaxCrossAxisExtent({
required this.maxCrossAxisExtent,//子元素在横轴上的最大长度,横轴方向每个子元素的长度仍然是等分的
this.mainAxisSpacing = 0.0,
this.crossAxisSpacing = 0.0,
this.childAspectRatio = 1.0,
this.mainAxisExtent,
})
例子:
import 'package:flutter/material.dart';
class GridViewPage extends StatefulWidget {
const GridViewPage({Key? key}) : super(key: key);
@override
State<GridViewPage> createState() => _GridViewPageState();
}
class _GridViewPageState extends State<GridViewPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('GridView网格组件'),),
body: GridView(
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 120,
childAspectRatio: 2,//宽高比2
),
children: const [
Icon(Icons.ac_unit),
Icon(Icons.apple),
Icon(Icons.android),
Icon(Icons.access_time_filled),
Icon(Icons.share_location),
Icon(Icons.star_half),
],
),
);
}
}
GridView.count
GridView.count
构造函数内部使用了SliverGridDelegateWithFixedCrossAxisCount
,我们通过它可以快速的创建横轴固定数量子元素的GridView
,例子:
GridView.count(
crossAxisCount: 3,
childAspectRatio: 1,
children: const [
Icon(Icons.ac_unit),
Icon(Icons.apple),
Icon(Icons.android),
Icon(Icons.access_time_filled),
Icon(Icons.share_location),
Icon(Icons.star_half),
],
),
GridView.extent
GridView.extent
构造函数内部使用了SliverGridDelegateWithMaxCrossAxisExtent
,我们通过它可以快速的创建横轴子元素为固定最大长度的的GridView
,例子:
GridView.extent(
maxCrossAxisExtent: 120,
childAspectRatio: 2,
children: const [
Icon(Icons.ac_unit),
Icon(Icons.apple),
Icon(Icons.android),
Icon(Icons.access_time_filled),
Icon(Icons.share_location),
Icon(Icons.star_half),
],
),
GridView.builder
当子widget
比较多时,我们可以通过GridView.builder
来动态创建子widget
。GridView.builder
必须指定的参数有两个:
GridView.builder(
gridDelegate: gridDelegate,
itemBuilder: itemBuilder
),
例子:
import 'package:flutter/material.dart';
class GridViewPage extends StatefulWidget {
const GridViewPage({Key? key}) : super(key: key);
@override
State<GridViewPage> createState() => _GridViewPageState();
}
class _GridViewPageState extends State<GridViewPage> {
final myProducts = List<Map>.generate(1000, (index) => {"id":index,"name":"P $index"}).toList();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('GridView网格组件'),),
body: GridView.builder(
padding: const EdgeInsets.all(10),
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 200,
childAspectRatio: 3/2,
crossAxisSpacing: 20,
mainAxisSpacing: 20
),
itemCount: myProducts.length,
itemBuilder: (BuildContext context,index){
return Container(
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.amber,
borderRadius: BorderRadius.circular(15),
),
child: Text(myProducts[index]["name"]),
);
}
),
);
}
}