# 【Demo】CustomScrollView + Sliver 混排布局 > 源文件:`lib/pages/demo/sliver_demo.dart` | 分类:基础布局 > 一句话:折叠 AppBar + 网格 + 长列表"整页只滚一次",靠 Sliver 碎片拼装。 --- ## 一、这个 Demo 解决什么问题 页面要同时包含"可折叠的大图 AppBar + 网格区块 + 长列表区块"时: - **ListView 不能嵌套 ListView/GridView**(同向滚动会冲突,控制权打架); - 正解是 `CustomScrollView`:把所有区块变成 Sliver"碎片"拼在一起,**共用一个滚动控制器,整页只滚一次**。 --- ## 二、怎么运行 / 演示内容 ```dart 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. 核心结构 ```dart 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(本页的灵魂) ```dart 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)], ), ), ), ), ) ``` --- ## 五、踩坑记录 1. **slivers 里的组件必须是 Sliver 家族**,普通 Widget(如 Container)直接放会报类型错误—— 要用 `SliverToBoxAdapter` 包一层; 2. **同向嵌套滚动是禁区**:CustomScrollView 里不能再放 ListView/GridView; 3. `SliverAppBar` 不设 `pinned` 时,上滑后 AppBar 会完全滚出屏幕(floating 可以浮回)——按产品需求选; 4. Sliver 的懒加载与 GridView/ListView 相同:builder 系列才懒加载。 --- ## 六、扩展思考 - **Sliver 与 GridView 的本质关系**(重点记忆): `GridView = CustomScrollView + 1 个 SliverGrid`,两者都是"单个滚动 + 懒加载",区别只在混排能力; - 进阶 Sliver:`SliverPersistentHeader`(吸顶 Tab)、`SliverAnimatedList`(增删动画列表)、`SliverAppBar` 的 `snap` 模式; - 电商首页 = Sliver 混排的教科书场景:搜索栏吸顶 + 轮播 + 宫格 + 瀑布流商品; - 对照 [responsive_demo.md](responsive_demo.md):Sliver 解决"滚动结构",响应式解决"不同宽度下的结构",两者可叠加。