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

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

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

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

此食谱演示了如何使用 CustomScrollView 来显示项目列表,并在顶部显示一个应用栏,该应用栏在用户使用以下步骤向下滚动列表时会滚动到屏幕外

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

1. 创建一个 CustomScrollView

#

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

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

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

dart
Scaffold(
  // No appBar property provided, only the body.
  body: CustomScrollView(
      // Add the app bar and list of items as slivers in the next steps.
      slivers: <Widget>[]),
);

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

#

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

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

要创建此效果

  1. 从一个只显示标题的应用栏开始。
  2. floating 属性设置为 true。这允许用户在向上滚动列表时快速显示应用栏。
  3. 添加一个填充可用 expandedHeightflexibleSpace 小部件。
dart
CustomScrollView(
  slivers: [
    // Add the app bar to the CustomScrollView.
    const SliverAppBar(
      // Provide a standard title.
      title: Text(title),
      // Allows the user to reveal the app bar if they begin scrolling
      // back up the list of items.
      floating: true,
      // Display a placeholder widget to visualize the shrinking size.
      flexibleSpace: Placeholder(),
      // Make the initial height of the SliverAppBar larger than normal.
      expandedHeight: 200,
    ),
  ],
)

3. 使用 SliverList 添加项目列表

#

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

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

dart
// Next, create a SliverList
SliverList(
  // Use a delegate to build items as they're scrolled on screen.
  delegate: SliverChildBuilderDelegate(
    // The builder function returns a ListTile with a title that
    // displays the index of the current item.
    (context, index) => ListTile(title: Text('Item #$index')),
    // Builds 1000 ListTiles
    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(
        // No appbar provided to the Scaffold, only a body with a
        // CustomScrollView.
        body: CustomScrollView(
          slivers: [
            // Add the app bar to the CustomScrollView.
            const SliverAppBar(
              // Provide a standard title.
              title: Text(title),
              // Allows the user to reveal the app bar if they begin scrolling
              // back up the list of items.
              floating: true,
              // Display a placeholder widget to visualize the shrinking size.
              flexibleSpace: Placeholder(),
              // Make the initial height of the SliverAppBar larger than normal.
              expandedHeight: 200,
            ),
            // Next, create a SliverList
            SliverList(
              // Use a delegate to build items as they're scrolled on screen.
              delegate: SliverChildBuilderDelegate(
                // The builder function returns a ListTile with a title that
                // displays the index of the current item.
                (context, index) => ListTile(title: Text('Item #$index')),
                // Builds 1000 ListTiles
                childCount: 1000,
              ),
            ),
          ],
        ),
      ),
    );
  }
}