Files
App.K12.Student.Miniapp_Flu…/docs/demos/sliver_demo.md
T
2026-09-04 15:22:20 +08:00

4.1 KiB
Raw Blame History

【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)],
        ),
      ),
    ),
  ),
)

五、踩坑记录

  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:Sliver 解决"滚动结构",响应式解决"不同宽度下的结构",两者可叠加。