1. GridView
1.1. SliverGridDelegate
SliverGridDelegate是一个抽象类,定义了GridView Layout相关接口,子类需要通过实现它们来实现具体的布局算法。Flutter中提供了两个SliverGridDelegate的子类SliverGridDelegateWithFixedCrossAxisCount和SliverGridDelegateWithMaxCrossAxisExtent。
1.1.1. 1. SliverGridDelegateWithFixedCrossAxisCount
通过设置横轴子元素的数量和比例的layout算法。
SliverGridDelegateWithFixedCrossAxisCount({
@required double crossAxisCount,
double mainAxisSpacing = 0.0,
double crossAxisSpacing = 0.0,
double childAspectRatio = 1.0,
})
1.1.2. 2. SliverGridDelegateWithMaxCrossAxisExtent
设置子元素最大长度的layout算法。
SliverGridDelegateWithMaxCrossAxisExtent({
double maxCrossAxisExtent,
double mainAxisSpacing = 0.0,
double crossAxisSpacing = 0.0,
double childAspectRatio = 1.0,
})
1.2. GridView.count
GridView.count构造函数内部使用了SliverGridDelegateWithFixedCrossAxisCount。
GridView.count(
crossAxisCount: 3,
childAspectRatio: 1.0,
children: <Widget>[
Icon(Icons.ac_unit),
Icon(Icons.airport_shuttle),
Icon(Icons.all_inclusive),
Icon(Icons.beach_access),
Icon(Icons.cake),
Icon(Icons.free_breakfast),
],
);
1.3. GridView.extent
GridView.extent构造函数内部使用了SliverGridDelegateWithMaxCrossAxisExtent。
GridView.extent(
maxCrossAxisExtent: 120.0,
childAspectRatio: 2.0,
children: <Widget>[
Icon(Icons.ac_unit),
Icon(Icons.airport_shuttle),
Icon(Icons.all_inclusive),
Icon(Icons.beach_access),
Icon(Icons.cake),
Icon(Icons.free_breakfast),
],
);
1.4. GridView.builder
当子widget比较多时,我们可以通过GridView.builder来动态创建子widget。GridView.builder 必须指定的参数有两个:
GridView.builder(
...
required SliverGridDelegate gridDelegate,
required IndexedWidgetBuilder itemBuilder,
)
1.5. 示例
假设我们需要从一个异步数据源(如网络)分批获取一些Icon,然后用GridView来展示:
class InfiniteGridView extends StatefulWidget {
@override
_InfiniteGridViewState createState() => _InfiniteGridViewState();
}
class _InfiniteGridViewState extends State<InfiniteGridView> {
List<IconData> _icons = []; //保存Icon数据
@override
void initState() {
super.initState();
// 初始化数据
_retrieveIcons();
}
@override
Widget build(BuildContext context) {
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3, //每行三列
childAspectRatio: 1.0, //显示区域宽高相等
),
itemCount: _icons.length,
itemBuilder: (context, index) {
//如果显示到最后一个并且Icon总数小于200时继续获取数据
if (index == _icons.length - 1 && _icons.length < 200) {
_retrieveIcons();
}
return Icon(_icons[index]);
},
);
}
//模拟异步获取数据
void _retrieveIcons() {
Future.delayed(Duration(milliseconds: 200)).then((e) {
setState(() {
_icons.addAll([
Icons.ac_unit,
Icons.airport_shuttle,
Icons.all_inclusive,
Icons.beach_access,
Icons.cake,
Icons.free_breakfast,
]);
});
});
}
}