概述
GridView是Flutter中用于展示网格布局的组件,适合商品列表、图片画廊等场景。GridView提供了多种构造方式,可以灵活地控制网格的列数、宽高比等属性。
GridView构造函数
GridView.count
通过指定列数创建网格:
GridView.count({Key?key,AxisscrollDirection=Axis.vertical,bool reverse=false,ScrollController?controller,bool?primary,ScrollPhysics?physics,EdgeInsetsGeometry?padding,bool shrinkWrap=false,required int crossAxisCount,// 列数double mainAxisSpacing=0,// 主轴间距double crossAxisSpacing=0,// 交叉轴间距double childAspectRatio=1,// 宽高比bool addAutomaticKeepAlives=true,bool addRepaintBoundaries=true,bool addSemanticIndexes=true,int?semanticChildCount,requiredList<Widget>children,// 子组件列表})GridView.extent
通过指定最大宽度创建网格:
GridView.extent({Key?key,AxisscrollDirection=Axis.vertical,bool reverse=false,ScrollController?controller,bool?primary,ScrollPhysics?physics,EdgeInsetsGeometry?padding,bool shrinkWrap=false,required double maxCrossAxisExtent,// 最大宽度double mainAxisSpacing=0,double crossAxisSpacing=0,double childAspectRatio=1,bool addAutomaticKeepAlives=true,bool addRepaintBoundaries=true,bool addSemanticIndexes=true,int?semanticChildCount,requiredList<Widget>children,})GridView.builder
懒加载模式,适合大数据网格:
GridView.builder({Key?key,AxisscrollDirection=Axis.vertical,bool reverse=false,ScrollController?controller,bool?primary,ScrollPhysics?physics,EdgeInsetsGeometry?padding,bool shrinkWrap=false,requiredSliverGridDelegategridDelegate,// 网格代理requiredIndexedWidgetBuilderitemBuilder,// 项构建器int?itemCount,bool addAutomaticKeepAlives=true,bool addRepaintBoundaries=true,bool addSemanticIndexes=true,int?semanticChildCount,})核心属性详解
crossAxisCount
指定列数,只在GridView.count中使用:
crossAxisCount:2,// 2列maxCrossAxisExtent
指定子组件的最大宽度,只在GridView.extent中使用:
maxCrossAxisExtent:200,// 每个子组件最大宽度200mainAxisSpacing
主轴方向的间距:
mainAxisSpacing:10,// 垂直方向间距10像素crossAxisSpacing
交叉轴方向的间距:
crossAxisSpacing:10,// 水平方向间距10像素childAspectRatio
子组件的宽高比:
childAspectRatio:1,// 正方形childAspectRatio:1.5,// 宽大于高childAspectRatio:0.66,// 高大于宽gridDelegate
网格代理,用于自定义网格布局,常用SliverGridDelegateWithFixedCrossAxisCount和SliverGridDelegateWithMaxCrossAxisExtent:
// 固定列数gridDelegate:constSliverGridDelegateWithFixedCrossAxisCount(crossAxisCount:2,mainAxisSpacing:10,crossAxisSpacing:10,childAspectRatio:1,),// 固定最大宽度gridDelegate:constSliverGridDelegateWithMaxCrossAxisExtent(maxCrossAxisExtent:200,mainAxisSpacing:10,crossAxisSpacing:10,childAspectRatio:1,),基本用法示例
GridView.count
GridView.count(crossAxisCount:2,padding:EdgeInsets.all(16),mainAxisSpacing:10,crossAxisSpacing:10,children:[Container(color:Colors.blue[100],child:constCenter(child:Text('Item 1'))),Container(color:Colors.green[100],child:constCenter(child:Text('Item 2'))),Container(color:Colors.orange[100],child:constCenter(child:Text('Item 3'))),Container(color:Colors.purple[100],child:constCenter(child:Text('Item 4'))),],)GridView.extent
GridView.extent(maxCrossAxisExtent:150,padding:EdgeInsets.all(16),mainAxisSpacing:10,crossAxisSpacing:10,children:[Container(color:Colors.blue[100],child:constCenter(child:Text('Item 1'))),Container(color:Colors.green[100],child:constCenter(child:Text('Item 2'))),Container(color:Colors.orange[100],child:constCenter(child:Text('Item 3'))),Container(color:Colors.purple[100],child:constCenter(child:Text('Item 4'))),],)GridView.builder
GridView.builder(gridDelegate:constSliverGridDelegateWithFixedCrossAxisCount(crossAxisCount:2,mainAxisSpacing:10,crossAxisSpacing:10,),itemCount:100,itemBuilder:(context,index){returnContainer(color:Colors.grey[200],child:Center(child:Text('Item$index')),);},)商品列表实战
基础商品网格
GridView.count(crossAxisCount:2,padding:EdgeInsets.all(16),mainAxisSpacing:12,crossAxisSpacing:12,childAspectRatio:0.7,children:[_buildProductCard('商品1','¥99'),_buildProductCard('商品2','¥199'),_buildProductCard('商品3','¥299'),_buildProductCard('商品4','¥399'),],)Widget_buildProductCard(Stringname,Stringprice){returnCard(elevation:2,child:Padding(padding:EdgeInsets.all(8),child:Column(children:[Expanded(child:Container(color:Colors.grey[200],child:constIcon(Icons.shopping_bag,size:48),),),SizedBox(height:8),Text(name,style:TextStyle(fontWeight:FontWeight.bold)),SizedBox(height:4),Text(price,style:TextStyle(color:Colors.red)),],),),);}商品列表全屏布局
GridView.builder(gridDelegate:constSliverGridDelegateWithFixedCrossAxisCount(crossAxisCount:2,mainAxisSpacing:8,crossAxisSpacing:8,childAspectRatio:0.8,),padding:EdgeInsets.all(8),itemCount:50,itemBuilder:(context,index){returnCard(child:Column(children:[Expanded(child:Container(color:Colors.blue[100],child:Center(child:Text('商品$index')),),),Padding(padding:EdgeInsets.all(8),child:Column(children:[Text('商品名称$index',style:TextStyle(fontWeight:FontWeight.bold)),SizedBox(height:4),Text('¥${(index+1)*10}',style:TextStyle(color:Colors.red)),],),),],),);},)图片画廊实战
图片网格布局
GridView.extent(maxCrossAxisExtent:150,padding:EdgeInsets.all(8),mainAxisSpacing:8,crossAxisSpacing:8,children:List.generate(20,(index){returnContainer(decoration:BoxDecoration(color:Colors.grey[200],borderRadius:BorderRadius.circular(8),),child:Center(child:Icon(Icons.image,size:48)),);}),)三种构造方式对比
| 特性 | GridView.count | GridView.extent | GridView.builder |
|---|---|---|---|
| 创建方式 | 固定列数 | 固定最大宽度 | 懒加载 |
| 适合场景 | 固定列数布局 | 响应式布局 | 大量数据 |
| 内存占用 | 较高 | 较高 | 较低 |
| 性能 | 一般 | 一般 | 优异 |
性能优化策略
使用GridView.builder
对于大量数据,使用GridView.builder进行懒加载:
GridView.builder(gridDelegate:constSliverGridDelegateWithFixedCrossAxisCount(crossAxisCount:3),itemCount:1000,itemBuilder:(context,index){returnText('Item$index');},)设置childAspectRatio
设置合适的宽高比,避免不必要的测量:
childAspectRatio:0.7,// 商品卡片常用比例优化子组件
确保子组件是轻量级的:
GridView.builder(gridDelegate:constSliverGridDelegateWithFixedCrossAxisCount(crossAxisCount:2),itemCount:1000,itemBuilder:(context,index){returnContainer(child:constIcon(Icons.image),);},)关键要点总结
- crossAxisCount指定列数(GridView.count)
- maxCrossAxisExtent指定最大宽度(GridView.extent)
- mainAxisSpacing和crossAxisSpacing控制间距
- childAspectRatio控制宽高比
- GridView.builder适合大数据网格
- gridDelegate用于自定义网格布局
常见问题
Q1: 如何实现响应式网格?
A: 使用GridView.extent,根据屏幕宽度自动调整列数。
Q2: 如何设置不同的列数?
A: 使用SliverGridDelegateWithFixedCrossAxisCount并动态设置crossAxisCount。
Q3: 大数据网格卡顿怎么办?
A: 使用GridView.builder进行懒加载。
Q4: 如何控制子组件大小?
A: 通过childAspectRatio和容器尺寸控制。
实践建议
- 固定列数:使用GridView.count
- 响应式布局:使用GridView.extent
- 大量数据:使用GridView.builder
- 商品列表:设置childAspectRatio为0.7~0.8
- 图片画廊:设置childAspectRatio为1(正方形)
通过合理使用GridView的各种构造方式和属性,可以创建出高效、美观的网格布局,满足商品展示、图片画廊等多种应用场景的需求。