Skip to main content

将浮动应用栏放置在列表上方

为了方便用户查看项目列表,您可能希望在用户向下滚动列表时隐藏应用栏。如果您的应用显示一个占用大量垂直空间的“高”应用栏,这一点尤其重要。

通常,您可以通过向 Scaffold 小部件提供 appBar 属性来创建应用栏。这将创建一个始终位于 Scaffoldbody 上方的固定应用栏。

将应用栏从 Scaffold 小部件移动到 CustomScrollView 中,允许您创建一个应用栏,当您滚动浏览 CustomScrollView 内包含的项目列表时,该应用栏会滚动到屏幕外。

此示例演示如何使用 CustomScrollView 来显示项目列表,顶部带有应用栏,该应用栏在用户向下滚动列表时会滚动到屏幕外,步骤如下:

  1. 创建一个 CustomScrollView
  2. 使用 SliverAppBar 添加浮动应用栏。
  3. 使用 SliverList 添加项目列表。

1. 创建 CustomScrollView

#

要创建一个浮动应用栏,请将应用栏放置在一个也包含项目列表的 CustomScrollView 中。这会同步应用栏和项目列表的滚动位置。您可以将 CustomScrollView 小部件视为一个 ListView,它允许您混合和匹配不同类型的可滚动列表和小部件。

提供给 CustomScrollView 的可滚动列表和小部件称为 slivers。有几种类型的 slivers,例如 SliverListSliverGridSliverAppBar。事实上,ListViewGridView 小部件使用 SliverListSliverGrid 小部件来实现滚动。

在此示例中,创建一个包含 SliverAppBarSliverListCustomScrollView。此外,请移除您提供给 Scaffold 小部件的任何应用栏。

dart
Scaffold(
  // 没有提供 appBar 属性,只有 body。
  body: CustomScrollView(
      // 在接下来的步骤中,将应用栏和项目列表作为 slivers 添加。
      slivers: <Widget>[]),
);

2. 使用 SliverAppBar 添加浮动应用栏

#

接下来,将应用栏添加到 CustomScrollView。Flutter 提供了 SliverAppBar 小部件,它与普通的 AppBar 小部件非常相似,使用 SliverAppBar 显示标题、标签、图像等等。

但是,SliverAppBar 还使您可以创建一个“浮动”应用栏,当用户向下滚动列表时,该应用栏会滚动到屏幕外。此外,您可以配置 SliverAppBar 以在用户滚动时收缩和展开。

要创建此效果:

  1. 从只显示标题的应用栏开始。
  2. floating 属性设置为 true。这允许用户在向上滚动列表时快速显示应用栏。
  3. 添加一个填充可用 expandedHeightflexibleSpace 小部件。
dart
CustomScrollView(
  slivers: [
    // 将应用栏添加到 CustomScrollView。
    SliverAppBar(
      // 提供标准标题。
      title: Text(title),
      // 允许用户在开始向上滚动项目列表时显示应用栏。
      floating: true,
      // 显示占位符小部件以可视化收缩大小。
      flexibleSpace: Placeholder(),
      // 使 SliverAppBar 的初始高度大于正常高度。
      expandedHeight: 200,
    ),
  ],
)

3. 使用 SliverList 添加项目列表

#

现在您已将应用栏就位,请将项目列表添加到 CustomScrollView。您有两个选择:SliverListSliverGrid。如果您需要按顺序显示项目列表,请使用 SliverList 小部件。如果您需要显示网格列表,请使用 SliverGrid 小部件。

SliverListSliverGrid 小部件采用一个必需参数:SliverChildDelegate,它向 SliverListSliverGrid 提供小部件列表。例如,SliverChildBuilderDelegate 允许您创建项目列表,这些项目会在您滚动时延迟构建,就像 ListView.builder 小部件一样。

dart
// 接下来,创建一个 SliverList
SliverList(
  // 使用委托在项目滚动到屏幕上时构建它们。
  delegate: SliverChildBuilderDelegate(
    // builder 函数返回一个 ListTile,其标题显示当前项目的索引。
    (context, index) => ListTile(title: Text('Item #$index')),
    // 构建 1000 个 ListTile
    childCount: 1000,
  ),
)

交互式示例

#
import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

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

  @override
  Widget build(BuildContext context) {
    const title = 'Floating App Bar';

    return MaterialApp(
      title: title,
      home: Scaffold(
        // 没有向 Scaffold 提供 appbar,只有一个带有 CustomScrollView 的 body。
        body: CustomScrollView(
          slivers: [
            // 将应用栏添加到 CustomScrollView。
            const SliverAppBar(
              // 提供标准标题。
              title: Text(title),
              // 允许用户在开始向上滚动项目列表时显示应用栏。
              floating: true,
              // 显示占位符小部件以可视化收缩大小。
              flexibleSpace: Placeholder(),
              // 使 SliverAppBar 的初始高度大于正常高度。
              expandedHeight: 200,
            ),
            // 接下来,创建一个 SliverList
            SliverList(
              // 使用委托在项目滚动到屏幕上时构建它们。
              delegate: SliverChildBuilderDelegate(
                // builder 函数返回一个 ListTile,其标题显示当前项目的索引。
                (context, index) => ListTile(title: Text('Item #$index')),
                // 构建 1000 个 ListTile
                childCount: 1000,
              ),
            ),
          ],
        ),
      ),
    );
  }
}