云计算百科
云计算领域专业知识百科平台

Flutter 滚动体系完全指南|SingleChildScrollView / ListView / CustomScrollView / Sliver 全套详解

Flutter 滚动体系完全指南|SingleChildScrollView / ListView / CustomScrollView / Sliver 全套详解

在这里插入图片描述

在这里插入图片描述

在 Flutter 开发中,滚动组件是页面搭建的核心基石。几乎所有 App 都离不开列表、滚动页面、复杂视差折叠、吸顶布局。

很多开发者只会简单使用ListView,但不知道:

  • 什么时候用 SingleChildScrollView

  • ListView 四种构造的性能差异

  • 为什么 Column 嵌套 ListView 会报错

  • 复杂折叠、吸顶、混合布局必须用 CustomScrollView + Sliver


一、Flutter 滚动体系整体架构

Flutter 滚动组件分为三大层级:

1. 基础滚动

SingleChildScrollView:一次性渲染全部子组件,适合少量静态页面

2. 常规列表滚动

ListView / GridView:自带懒加载,适合单一列表、网格业务

3. 高级复杂滚动(Sliver 体系)

CustomScrollView + Sliver 系列:支持折叠头部、吸顶、混合布局、视差效果,适合首页、详情页、复杂页面


二、SingleChildScrollView 基础滚动

核心特点

  • 只能包含一个子组件(通常嵌套 Column)

  • 无懒加载机制,一次性渲染所有 Widget

  • 适合:表单页、个人中心、静态长页面

  • 禁止:大数据列表、长列表

基础示例

SingleChildScrollView(
padding: EdgeInsets.all(16),
child: Column(
children: [
Text("内容1"),
Text("内容2"),
// 大量静态组件
],
),
)

常见问题

  • 内部嵌套超大数量组件会卡顿、内存溢出

  • 不支持 item 回收,性能不如 ListView


三、ListView 深度详解

ListView 是 Flutter 标准线性滚动列表,自带懒加载、组件回收,是长列表首选。

3.1 ListView 四种构造方式

1)ListView() 默认构造

一次性渲染所有 children,无懒加载,仅适合少量数据。

ListView(
children: [
ListTile(title: Text("条目1")),
ListTile(title: Text("条目2")),
],
)

2)ListView.builder

按需构建可视区域 Item,滑出屏幕立即销毁,带有懒加载,大数据首选。

ListView.builder(
itemCount: 1000,
itemBuilder: (context, index) {
return ListTile(title: Text("数据 $index"));
},
)

3)ListView.separated 带分割线懒加载

在 builder 基础上支持自定义分割线,项目最常用。

ListView.separated(
itemCount: 20,
itemBuilder: (ctx, idx) => ListTile(title: Text("数据 $idx")),
separatorBuilder: (ctx, idx) => Divider(height: 1),
)

4)ListView.custom 自定义

基于SliverChildDelegate,可自定义缓存、回收策略,底层所有 ListView 都基于它封装。

3.2 ListView 核心属性详解

scrollDirection 滚动方向
  • Axis.vertical:默认垂直

  • Axis.horizontal:水平列表

shrinkWrap
  • false(默认):占满父容器,拥有完整懒加载

  • true:自适应内容高度,失去懒加载能力

场景:ListView 嵌套 ListView 必须开启,但大数据慎用。

itemExtent 固定条目尺寸

提前指定 item 高度/宽度,Flutter 无需实时计算尺寸,大幅提升长列表性能。

physics 滚动物理效果
  • BouncingScrollPhysics:iOS 回弹

  • ClampingScrollPhysics:Android 边界停止

  • NeverScrollableScrollPhysics:禁止滚动

  • AlwaysScrollableScrollPhysics:内容不足也可拉动

3.3 ScrollController 滚动监听与控制

用于监听滚动偏移、代码滚动、触底加载、回到顶部。

核心能力
  • offset:当前滚动距离

  • maxScrollExtent:最大滚动区域

  • animateTo:平滑滚动

  • jumpTo:无动画跳转

完整示例

class ListDemo extends StatefulWidget {

State<ListDemo> createState() => _ListDemoState();
}

class _ListDemoState extends State<ListDemo> {
late ScrollController _controller;


void initState() {
super.initState();
_controller = ScrollController();
_controller.addListener(() {
// 触底判断
if (_controller.offset >= _controller.position.maxScrollExtent 20) {
print("触发上拉加载");
}
});
}

//销毁防泄漏

void dispose() {
_controller.dispose();
super.dispose();
}


Widget build(BuildContext context) {
return Column(
children: [
ElevatedButton(
onPressed: () {
_controller.animateTo(0, duration: Duration(milliseconds: 200), curve: Curves.ease);
},
child: Text("回到顶部"),
),
Expanded(
child: ListView.builder(
controller: _controller,
itemCount: 50,
itemBuilder: (_, idx) => ListTile(title: Text("item $idx")),
),
)
],
);
}
}

3.4 ListView 常见报错与解决方案

Q1:Vertical viewport was given unbounded height

原因:Column / Row 嵌套 ListView,滚动组件无边界约束

解决:ListView 外层包裹 Expanded

Q2:列表溢出、卡顿

解决:禁用 shrinkWrap、使用 builder、设置 itemExtent


四、Flutter 高级滚动:CustomScrollView + Sliver

4.1 为什么需要 Sliver?

普通 ListView / GridView 只能单一滚动布局。

业务中常见的:折叠头部 + 吸顶导航 + 轮播 + 列表 + 网格混合页面,普通组件完全无法实现。

于是 Flutter 提供 Sliver 碎片滚动体系:

  • 所有组件共享同一个滚动视口

  • 支持折叠、拉伸、粘性吸顶

  • 支持混合多种布局联动滚动

4.2 Box 组件 vs Sliver 组件

体系代表组件适用场景
Box 常规组件 ListView、Column、Container 简单单一布局
Sliver 滚动碎片 SliverList、SliverAppBar、SliverPersistentHeader 复杂滚动、折叠、吸顶、混合布局

4.3 常用 Sliver 组件对照表

Sliver 组件功能说明对应 Box 组件
SliverAppBar 折叠、拉伸、悬浮导航栏 AppBar
SliverList 懒加载列表 ListView.builder
SliverGrid 网格布局 GridView.builder
SliverToBoxAdapter 适配普通 Widget 占位容器
SliverPersistentHeader 粘性吸顶头部
SliverPadding Sliver 内边距 Padding

核心禁忌:CustomScrollView 中不能直接放 Container/Text,普通组件必须包裹 SliverToBoxAdapter

4.4 SliverAppBar 折叠导航核心参数

SliverAppBar(
expandedHeight: 200, // 展开最大高度
pinned: true, // 收缩后固定在顶部(最常用)
floating: false,
stretch: true, // 下拉拉伸效果
flexibleSpace: FlexibleSpaceBar(
title: Text("折叠标题"),
background: Container(color: Colors.blue),
),
)

4.5 SliverPersistentHeader 粘性吸顶

实现滚动标题常驻顶部效果,必须自定义 Delegate

4.6 完整高级混合滚动 Demo

功能:折叠头部 + 吸顶标题 + 普通区域 + 网格 + 列表

import 'package:flutter/material.dart';

void main() {
runApp(const MyApp());
}

class MyApp extends StatelessWidget {
const MyApp({super.key});


Widget build(BuildContext context) {
return MaterialApp(home: SliverPage(), debugShowCheckedModeBanner: false);
}
}

class SliverPage extends StatelessWidget {

Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: [
// 1. 折叠头部
SliverAppBar(
expandedHeight: 200,
pinned: true,
stretch: true,
flexibleSpace: FlexibleSpaceBar(
title: Text("Sliver 高级滚动页面"),
background: Container(color: Colors.teal),
),
),

// 2. 吸顶标题
SliverPersistentHeader(
pinned: true,
delegate: MyHeaderDelegate(
height: 48,
child: Container(
color: Colors.white,
padding: EdgeInsets.symmetric(horizontal: 16),
alignment: Alignment.centerLeft,
child: Text("🔥 网格专区", style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
),
),
),

// 3. 普通组件区域
SliverToBoxAdapter(
child: Padding(
padding: EdgeInsets.all(16),
child: Text("下面是网格布局演示"),
),
),

// 4. 网格布局
SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 10,
mainAxisSpacing: 10,
),
delegate: SliverChildBuilderDelegate(
(_, idx) => Container(
color: Colors.primaries[idx % Colors.primaries.length],
child: Center(child: Text("网格 $idx")),
),
childCount: 6,
),
),

// 第二个吸顶标题
SliverPersistentHeader(
pinned: true,
delegate: MyHeaderDelegate(
height: 48,
child: Container(
color: Colors.white,
padding: EdgeInsets.symmetric(horizontal: 16),
alignment: Alignment.centerLeft,
child: Text("📃 列表数据", style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
),
),
),

// 5. 列表布局
SliverList(
delegate: SliverChildBuilderDelegate(
(_, idx) => ListTile(title: Text("列表条目 $idx")),
childCount: 30,
),
)
],
),
);
}
}

// 吸顶 Header 委托
class MyHeaderDelegate extends SliverPersistentHeaderDelegate {
final Widget child;
final double height;

MyHeaderDelegate({required this.child, required this.height});


Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) => child;


double get maxExtent => height;


double get minExtent => height;


bool shouldRebuild(covariant MyHeaderDelegate oldDelegate) {
return oldDelegate.child != child || oldDelegate.height != height;
}
}


五、Flutter 滚动组件选型终极标准

1. 少量静态页面

✅ SingleChildScrollView

2. 简单列表、大数据列表、瀑布流

✅ ListView / GridView(builder 模式)

3. 需要折叠头部、吸顶、混合布局、视差效果

✅ CustomScrollView + Sliver 全套体系


六、滚动组件性能优化总结

  • 长列表必须使用 builder 懒加载

  • 固定 item 高度优先设置 itemExtent

  • 尽量避免shrinkWrap: true

  • ScrollController 页面销毁必须 dispose

  • 复杂页面优先 Sliver 体系,减少多层嵌套滚动

  • itemBuilder 内不创建新对象、不做耗时操作


  • 七、总结

    Flutter 滚动三件套:

    • 基础滚动:SingleChildScrollView

    • 常规列表滚动:ListView 四种构造、滚动监听、性能优化

    • 高级复杂滚动:CustomScrollView + 全套 Sliver 组件、折叠、吸顶、混合布局

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » Flutter 滚动体系完全指南|SingleChildScrollView / ListView / CustomScrollView / Sliver 全套详解
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!