前言:
通过本讲学习,你可以基于 Sliver 体系构建高性能、高交互性的滚动界面,替代传统的 ListView/GridView 嵌套方案,是 Flutter 中高级滚动布局的核心技术。然并卵,能够开发界面就行了!哪来那么多精细事!vibecoding时代,快速产出迭代大量自己喜欢的项目,才是生存之道。
一、总览
本章聚焦 Flutter 中基于 Sliver(切片) 的高性能滚动布局体系,核心解决传统 ListView/GridView 混合滚动时的性能问题、滚动联动问题,以及实现复杂的折叠/吸顶/悬浮等滚动交互效果。
-
核心目标:掌握 Sliver 架构的设计思想,使用
CustomScrollView统一管理各类 Sliver 组件,实现高性能、高定制化的滚动界面(如电商首页、社交APP个人主页、资讯流等复杂滚动场景)。 -
解决的痛点:
- 传统
ListView嵌套滚动不连贯、性能损耗大 - 难以实现 AppBar 折叠、吸顶、悬浮等高级滚动交互
- 多类型滚动组件(列表/网格/固定区域)的统一滚动控制
- 传统
Sliver 核心价值:将滚动内容切片化,按需加载,解决传统滚动组件的性能和联动问题。
核心组件关系:CustomScrollView 是容器,内部可放 SliverAppBar/SliverList/SliverGrid 等组件,共享滚动上下文。
高级交互关键:SliverAppBar 的 pinned(吸顶)、floating(悬浮)、snap(吸附)三属性组合实现折叠效果。
- Sliver 本质:将滚动内容拆分为「可按需加载的切片」,只有进入视口的切片才会被构建/渲染,大幅降低内存占用。
- 统一驱动:
CustomScrollView封装了Scrollable+Viewport,所有子 Sliver 共享同一个滚动控制器和视口,实现滚动联动。 - 约束-几何反馈:每个 Sliver 接收
SliverConstraints(滚动偏移、视口尺寸等),返回SliverGeometry(自身尺寸、滚动范围等),Viewport 根据这些信息布局所有 Sliver。
二、核心组件详解
2.1 基础容器:CustomScrollView
核心作用
作为所有 Sliver 组件的统一容器,提供共享的滚动上下文,是实现多 Sliver 联动滚动的核心。
核心属性
| 属性 | 作用 | 常用值 |
|---|---|---|
slivers | 存放所有 Sliver 组件的数组 | [SliverAppBar(), SliverList()] |
scrollDirection | 滚动方向 | Axis.vertical/Axis.horizontal |
physics | 滚动物理效果 | BouncingScrollPhysics()/ClampingScrollPhysics() |
controller | 滚动控制器 | ScrollController() |
基础案例
CustomScrollView(
// 所有Sliver组件都放在slivers数组中
slivers: [
// 后续添加各类Sliver组件
SliverToBoxAdapter(child: Text("基础Sliver容器")),
],
)
注意事项
slivers数组中只能放 Sliver 类型组件,普通组件需用SliverToBoxAdapter包裹- 所有子 Sliver 共享同一个滚动偏移,实现天然的滚动联动
2.2 列表组件:SliverList
核心作用
高性能列表组件,替代传统 ListView,专为 CustomScrollView 设计,按需加载列表项。
核心属性
| 属性 | 作用 |
|---|---|
delegate | 列表项代理,常用 SliverChildBuilderDelegate |
itemExtent | 固定列表项高度(可选,设置后提升性能) |
实战案例
CustomScrollView(
// 所有Sliver组件都放在slivers数组中
slivers: [
// 后续添加各类Sliver组件
SliverToBoxAdapter(child: Text("基础Sliver容器")),
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
// 按需构建列表项
return ListTile(
title: Text("Sliver列表项 $index"),
leading: const Icon(Icons.list),
);
},
childCount: 50, // 列表项总数
),
),
],
),
注意事项
SliverChildBuilderDelegate是懒加载,仅构建可视区域内的项- 相比
ListView,SliverList 无嵌套滚动问题,可与其他 Sliver 无缝联动
2.3 网格组件:SliverGrid
核心作用
高性能网格组件,替代传统 GridView,适配 CustomScrollView 滚动体系。
核心属性
| 属性 | 作用 |
|---|---|
delegate | 网格项代理(同 SliverList) |
gridDelegate | 网格布局规则,常用 SliverGridDelegateWithFixedCrossAxisCount |
实战案例
SliverGrid(
// 网格布局规则:固定列数
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2, // 列数
mainAxisSpacing: 10, // 纵向间距
crossAxisSpacing: 10, // 横向间距
childAspectRatio: 1.0, // 宽高比
),
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
color: Colors.blue[100 * (index % 9)],
alignment: Alignment.center,
child: Text("网格项 $index"),
);
},
childCount: 20,
),
)
注意事项
-
网格布局规则有两种:
SliverGridDelegateWithFixedCrossAxisCount:固定列数(常用)SliverGridDelegateWithMaxCrossAxisExtent:固定子项最大宽度
2.4 折叠导航栏:SliverAppBar
核心作用
支持折叠/吸顶/悬浮的高级 AppBar,是 Sliver 体系中最具特色的组件。
核心属性(折叠效果三剑客)
| 属性 | 作用 | 效果说明 |
|---|---|---|
pinned | 是否吸顶 | true:AppBar 始终固定在顶部(折叠后保留导航栏) false:滚动时AppBar完全滑出视口 |
floating | 是否悬浮 | true:手指轻扫即可召回AppBar(无需滚动到顶部) false:需滚动到顶部才能显示AppBar |
snap | 是否快速吸附 | 需配合 floating=true 使用 true:AppBar 要么完全显示,要么完全隐藏 false:AppBar 可停留在中间状态 |
expandedHeight | 展开高度 | 设置AppBar展开时的总高度 |
flexibleSpace | 可折叠区域 | 放置折叠的背景/图片等内容 |
实战案例(折叠效果)
SliverAppBar(
title: const Text("折叠导航栏"),
backgroundColor: Colors.blue,
expandedHeight: 200, // 展开高度
pinned: true, // 吸顶(折叠后保留标题栏)
floating: true, // 悬浮(轻扫召回)
snap: true, // 快速吸附
// 可折叠区域
flexibleSpace: FlexibleSpaceBar(
background: Image.network(
"https://flutter.dev/images/flutter-logo-sharing.png",
fit: BoxFit.cover,
),
),
)
注意事项
snap必须配合floating=true才生效expandedHeight需大于 AppBar 折叠后的高度(默认56)- 背景图片建议用
FlexibleSpaceBar包裹,保证折叠时的过渡效果
4. 综合实战案例:电商首页
需求说明
实现一个电商首页,包含:
- 折叠吸顶的 AppBar(带背景图)
- 分类网格区(SliverGrid)
- 推荐商品列表(SliverList)
- 所有区域统一滚动,联动效果
完整代码
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Sliver实战',
theme: ThemeData(primarySwatch: Colors.blue),
home: const SliverHomePage(),
);
}
}
class SliverHomePage extends StatelessWidget {
const SliverHomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
// 核心:CustomScrollView统一管理所有Sliver
body: CustomScrollView(
physics: const BouncingScrollPhysics(), // 回弹效果(iOS风格)
slivers: [
// 1. 折叠吸顶AppBar
SliverAppBar(
title: const Text("电商首页"),
expandedHeight: 200,
pinned: true, // 吸顶
floating: true, // 悬浮
snap: true, // 快速吸附
flexibleSpace: FlexibleSpaceBar(
background: Image.network(
"https://cdn.deepseek.com/logo.png?x-image-process=image%2Fresize%2Cw_828",
fit: BoxFit.cover,
),
),
),
// 2. 分类网格区(SliverGrid)
SliverPadding(
padding: EdgeInsets.all(10),
sliver: SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4, // 4列
mainAxisSpacing: 10,
crossAxisSpacing: 10,
childAspectRatio: 1.0,
),
delegate: SliverChildBuilderDelegate(
(context, index) {
// 分类图标+文字
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.category, color: Colors.blue[600]),
const SizedBox(height: 5),
Text("分类${index+1}"),
],
);
},
childCount: 8, // 8个分类
),
),
),
// 3. 推荐商品标题(普通组件需用SliverToBoxAdapter包裹)
SliverToBoxAdapter(
child: Container(
padding: const EdgeInsets.all(10),
child: const Text(
"推荐商品",
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
),
),
// 4. 推荐商品列表(SliverList)
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
// 商品项
return ListTile(
leading: Container(
width: 60,
height: 60,
color: Colors.grey[200],
child: const Icon(Icons.shopping_bag),
),
title: Text("商品名称 ${index+1}"),
subtitle: const Text("¥99.00 好评率99%"),
trailing: const Icon(Icons.arrow_forward_ios),
);
},
childCount: 20, // 20个商品
),
),
],
),
);
}
}
效果说明
- 滚动时 AppBar 从 200 高度折叠到 56 高度,标题始终吸顶
- 轻扫屏幕即可快速召回完整 AppBar(floating + snap 效果)
- 分类网格和商品列表共享同一个滚动上下文,滚动连贯无卡顿
- 所有列表项均为懒加载,仅渲染可视区域内容,性能最优
应用场景
- 电商/资讯类APP首页(折叠导航+多类型列表)
- 社交APP个人主页(头像折叠+动态列表)
- 长列表+网格混合的复杂滚动界面