第十讲 Sliver高性能滚动布局

0 阅读5分钟

前言:

通过本讲学习,你可以基于 Sliver 体系构建高性能、高交互性的滚动界面,替代传统的 ListView/GridView 嵌套方案,是 Flutter 中高级滚动布局的核心技术。然并卵,能够开发界面就行了!哪来那么多精细事!vibecoding时代,快速产出迭代大量自己喜欢的项目,才是生存之道。

一、总览

本章聚焦 Flutter 中基于 Sliver(切片) 的高性能滚动布局体系,核心解决传统 ListView/GridView 混合滚动时的性能问题、滚动联动问题,以及实现复杂的折叠/吸顶/悬浮等滚动交互效果。

  • 核心目标:掌握 Sliver 架构的设计思想,使用 CustomScrollView 统一管理各类 Sliver 组件,实现高性能、高定制化的滚动界面(如电商首页、社交APP个人主页、资讯流等复杂滚动场景)。

  • 解决的痛点

    • 传统 ListView 嵌套滚动不连贯、性能损耗大
    • 难以实现 AppBar 折叠、吸顶、悬浮等高级滚动交互
    • 多类型滚动组件(列表/网格/固定区域)的统一滚动控制

Sliver 核心价值:将滚动内容切片化,按需加载,解决传统滚动组件的性能和联动问题。

核心组件关系CustomScrollView 是容器,内部可放 SliverAppBar/SliverList/SliverGrid 等组件,共享滚动上下文。

高级交互关键SliverAppBarpinned(吸顶)、floating(悬浮)、snap(吸附)三属性组合实现折叠效果。

image.png

  1. Sliver 本质:将滚动内容拆分为「可按需加载的切片」,只有进入视口的切片才会被构建/渲染,大幅降低内存占用。
  2. 统一驱动CustomScrollView 封装了 Scrollable + Viewport,所有子 Sliver 共享同一个滚动控制器和视口,实现滚动联动。
  3. 约束-几何反馈:每个 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. 综合实战案例:电商首页

需求说明

实现一个电商首页,包含:

  1. 折叠吸顶的 AppBar(带背景图)
  2. 分类网格区(SliverGrid)
  3. 推荐商品列表(SliverList)
  4. 所有区域统一滚动,联动效果

完整代码

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个商品
            ),
          ),
        ],
      ),
    );
  }
}

效果说明

  1. 滚动时 AppBar 从 200 高度折叠到 56 高度,标题始终吸顶
  2. 轻扫屏幕即可快速召回完整 AppBar(floating + snap 效果)
  3. 分类网格和商品列表共享同一个滚动上下文,滚动连贯无卡顿
  4. 所有列表项均为懒加载,仅渲染可视区域内容,性能最优

应用场景

  • 电商/资讯类APP首页(折叠导航+多类型列表)
  • 社交APP个人主页(头像折叠+动态列表)
  • 长列表+网格混合的复杂滚动界面