flutter架 构项目基础
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
# 【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。
|
||||
Reference in New Issue
Block a user