# 【Demo】GridView 网格布局(三种构造) > 源文件:`lib/pages/demo/grid_demo.dart` | 分类:基础布局 > 一句话:九宫格/相册/功能宫格都靠它,三种构造方式一次看懂。 --- ## 一、这个 Demo 解决什么问题 "功能宫格(4×2 图标)"、"相册缩略图(3 列)"、"课程卡片墙"这类**多列等宽网格**布局。 GridView 就是 Flutter 的网格容器,支持**懒加载**,大量数据不卡。 --- ## 二、怎么运行 / 演示内容 ```dart runApp(const MaterialApp(home: GridDemoPage())); ``` 一屏并排演示三种构造: 1. `GridView.count`:固定 3 列,写死 children; 2. `GridView.builder`:4 列,`itemCount: 100` 懒加载; 3. `GridView.extent`:每项最多 80 宽,**屏幕越宽列数自动变多**。 --- ## 三、核心知识点(新手向) ### 1. 三个常用构造怎么选 | 构造 | 特点 | 适用 | |---|---|---| | `GridView.count` | 固定列数,children 一次性全创建 | 少量固定网格(< 30) | | `GridView.builder` | 懒加载,`itemCount` + `itemBuilder` | **大量数据首选**(100+ 条) | | `GridView.extent` | 按"每项最大宽度"自适应列数 | 响应式场景(Pad 变列数) | ### 2. 核心参数 ```dart GridView.builder( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 4, // 列数 mainAxisSpacing: 8.w, // 主轴(上下行)间距 crossAxisSpacing: 8.w, // 交叉轴(左右列)间距 childAspectRatio: 1, // 每项 宽:高 比例,默认 1 = 正方形 ), itemCount: 100, itemBuilder: (context, index) => _GridItem(index: index), ) ``` ### 3. 重点记忆:GridView 的本质 **GridView = CustomScrollView + 1 个 SliverGrid**(框架内部自动包的简化套餐)。 - 页面只有网格 → `GridView.builder` 直接用; - 页面要混排(折叠 AppBar + 网格 + 列表)→ 用 `CustomScrollView + slivers`(见 [sliver_demo.md](sliver_demo.md))。 --- ## 四、关键代码剖析 ```dart // Demo3:extent 自适应列数 GridView.extent( maxCrossAxisExtent: 80.w, // 每项最多 80 宽 → 屏幕宽时自动多列 mainAxisSpacing: 8.w, crossAxisSpacing: 8.w, childAspectRatio: 1, children: [for (int i = 0; i < 12; i++) _GridItem(index: i)], ) ``` > 响应式网格更精细的做法见 [responsive_demo.md](responsive_demo.md): > 用 `LayoutBuilder` 拿真实宽度,`(width / 280).floor().clamp(1, 4)` 算列数。 --- ## 五、踩坑记录 1. **GridView 放 Column 里必须 SizedBox 定高或 Expanded**,否则报 `Vertical viewport was given unbounded height`(和 ListView 同一个坑)。 2. **`childAspectRatio` 太小(如 0.5)时,格子内文字会被挤压溢出** —— 调大比例或缩小字号。 3. 本页外层 `SingleChildScrollView` 只是"展示台"(为了并排演示 3 种构造), 真实网格页**别学这个外层** —— 网格自己就能滚。 4. 想"网格 + 下拉刷新",用 `RefreshIndicator` 包 GridView(写法同 [list_demo.md](list_demo.md) 的列表刷新)。 --- ## 六、扩展思考 - **`SliverGridDelegateWithMaxCrossAxisExtent`**:同 extent 效果的另一种 delegate 写法; - 相册九宫格真实案例见 [note_picker_demo.md](note_picker_demo.md): GridView + "加号格" + 右上角删除角标(Stack 组合),多一格用 `itemCount: _images.length + 1`; - 性能提示:builder 系列(builder/extent.builder)是懒加载,`count` 不是 —— 大列表务必 builder。