4.1 KiB
4.1 KiB
【Demo】CustomScrollView + Sliver 混排布局
源文件:
lib/pages/demo/sliver_demo.dart| 分类:基础布局 一句话:折叠 AppBar + 网格 + 长列表"整页只滚一次",靠 Sliver 碎片拼装。
一、这个 Demo 解决什么问题
页面要同时包含"可折叠的大图 AppBar + 网格区块 + 长列表区块"时:
- ListView 不能嵌套 ListView/GridView(同向滚动会冲突,控制权打架);
- 正解是
CustomScrollView:把所有区块变成 Sliver"碎片"拼在一起,共用一个滚动控制器,整页只滚一次。
二、怎么运行 / 演示内容
runApp(const MaterialApp(home: SliverDemoPage()));
页面从上到下:折叠大图 AppBar → 网格标题 → 12 格网格 → 列表标题 → 50 条列表, 下滑时 AppBar 收起固定,其余内容连续滚动。
三、核心知识点(新手向)
1. Sliver 是什么
Sliver = "碎片"。CustomScrollView 把多个 sliver 拼成一个统一滚动视图。
2. 常用 sliver 对照表
| Sliver | 作用 | 对应普通组件 |
|---|---|---|
SliverAppBar |
可折叠/固定的 AppBar | AppBar |
SliverToBoxAdapter |
把普通组件(文字/卡片)塞进滚动流 | 任意 Widget |
SliverGrid.builder |
网格区块(懒加载) | GridView |
SliverList.builder |
列表区块(懒加载) | ListView.builder |
SliverPadding |
给某个 sliver 加内边距 | Padding |
3. 核心结构
CustomScrollView(
slivers: [
SliverAppBar( // ① 折叠 AppBar
expandedHeight: 180.h,
pinned: true, // 滚动时固定在顶部
flexibleSpace: FlexibleSpaceBar(
title: Text('Sliver 系列 Demo'),
background: DecoratedBox(...), // 展开时的大图
),
),
SliverToBoxAdapter( // ② 普通文字标题
child: Padding(...Text('网格区块(SliverGrid)')),
),
SliverPadding( // ③ 网格区块(带外边距)
padding: EdgeInsets.all(16.w),
sliver: SliverGrid.builder(...),
),
SliverList.builder( // ④ 列表区块
itemCount: 50,
itemBuilder: ...,
),
],
)
4. 判断口诀(什么时候用 Sliver)
- 页面是"一个网格"或"一个列表" →
GridView/ListView更简单; - 页面是"折叠头 + 网格 + 长列表"混排 →
CustomScrollView + slivers。
四、关键代码剖析
折叠 AppBar(本页的灵魂)
SliverAppBar(
expandedHeight: 180.h, // 展开时高度(大图区域)
pinned: true, // 上滑时缩成一条标题栏并固定在顶部
backgroundColor: Color(0xFF3B82F6),
flexibleSpace: FlexibleSpaceBar(
title: Text('Sliver 系列 Demo'),
centerTitle: true,
background: DecoratedBox( // 展开时显示的大图(这里是渐变)
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Color(0xFF3B82F6), Color(0xFF8E6FE8)],
),
),
),
),
)
五、踩坑记录
- slivers 里的组件必须是 Sliver 家族,普通 Widget(如 Container)直接放会报类型错误——
要用
SliverToBoxAdapter包一层; - 同向嵌套滚动是禁区:CustomScrollView 里不能再放 ListView/GridView;
SliverAppBar不设pinned时,上滑后 AppBar 会完全滚出屏幕(floating 可以浮回)——按产品需求选;- Sliver 的懒加载与 GridView/ListView 相同:builder 系列才懒加载。
六、扩展思考
- Sliver 与 GridView 的本质关系(重点记忆):
GridView = CustomScrollView + 1 个 SliverGrid,两者都是"单个滚动 + 懒加载",区别只在混排能力; - 进阶 Sliver:
SliverPersistentHeader(吸顶 Tab)、SliverAnimatedList(增删动画列表)、SliverAppBar的snap模式; - 电商首页 = Sliver 混排的教科书场景:搜索栏吸顶 + 轮播 + 宫格 + 瀑布流商品;
- 对照 responsive_demo.md:Sliver 解决"滚动结构",响应式解决"不同宽度下的结构",两者可叠加。