本指南介绍了如何在 Flutter 应用中将浮动应用栏或导航栏置于列表上方。

概述

#

为了方便用户查看项目列表,您可能希望在用户向下滚动列表时,将应用栏(导航栏)最小化。

将应用栏移入 CustomScrollView,您就可以创建一个应用栏,该应用栏可以在您滚动 CustomScrollView 中包含的项目列表时最小化或滚动到屏幕外。

本示例介绍了如何使用 CustomScrollView 来显示带有应用栏的项目列表,该应用栏在用户向下滚动列表时会最小化,具体步骤如下:

  1. 创建 CustomScrollView
  2. CustomScrollView 添加浮动应用栏。
  3. CustomScrollView 添加项目列表。

1. 创建 CustomScrollView

#

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

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

对于此示例,请创建一个包含 SliverListCustomScrollView。此外,如果您的代码中存在应用栏属性,请将其移除。

dart
MaterialApp(
  title: 'Floating App Bar',
  home: Scaffold(
    // No app bar property provided yet.
    body: CustomScrollView(
      // Add the app bar and list of items as slivers in the next steps.
      slivers: <widget>[],
    ),
  ),
);

dart
CupertinoApp(
  title: 'Floating Navigation Bar',
  home: CupertinoPageScaffold(
    // No navigation bar property provided yet.
    child: CustomScrollView(
      // Add the navigation bar and list of items as slivers in the next steps.
      slivers: <widget>[],
    ),
  ),
);

2. 添加浮动应用栏

#

接下来,将应用栏添加到 CustomScrollView

Flutter 提供了 SliverAppBar 小部件,它与普通的 AppBar 小部件非常相似,用于显示标题、选项卡、图像等。

然而,SliverAppBar 还允许您创建一个“浮动”应用栏,当您不在页面顶部时,它会收缩并浮动。

要创建此效果

  1. 从仅显示标题的应用栏开始。
  2. pinned 属性设置为 true
  3. 添加一个填充可用 expandedHeightflexibleSpace 小部件。
dart
slivers: [
  // Add the app bar to the CustomScrollView.
  SliverAppBar(
    // Provide a standard title.
    title: Text('Floating App Bar'),
    // Pin the app bar when scrolling.
    pinned: true,
    // Display a placeholder widget to visualize the shrinking size.
    flexibleSpace: Placeholder(),
    // Make the initial height of the SliverAppBar larger than normal.
    expandedHeight: 200,
  ),
],

Flutter 提供了 CupertinoSliverNavigationBar 小部件,它允许您拥有一个“浮动”导航栏,当您向下滚动时它会收缩,当您不在页面顶部时它会浮动。

要创建此效果

  1. CupertinoSliverNavigationBar 添加到 CustomScrollView
  2. 从仅显示标题的应用栏开始。
dart
slivers: [
  // Add the navigation bar to the CustomScrollView.
  CupertinoSliverNavigationBar(
    // Provide a standard title.
    largeTitle: Text('Floating App Bar'),
  ),
],

3. 添加项目列表

#

现在您已经放置了应用栏,请将项目列表添加到 CustomScrollView 中。您有两个选项:SliverListSliverGrid。如果您需要一个接一个地显示项目列表,请使用 SliverList 小部件。如果您需要显示网格列表,请使用 SliverGrid 小部件。

dart
// Next, create a SliverList
SliverList.builder(
  // The builder function returns a ListTile with a title that
  // displays the index of the current item.
  itemBuilder: (context, index) =>
      ListTile(title: Text('Item #$index')),
  // Builds 50 ListTiles
  itemCount: 50,
)
dart
// Next, create a SliverList
SliverList.builder(
  // The builder function returns a CupertinoListTile with a title
  // that displays the index of the current item.
  itemBuilder: (context, index) =>
      CupertinoListTile(title: Text('Item #$index')),
  // Builds 50 CupertinoListTile
  itemCount: 50,
)

互动示例

#
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 app bar provided to 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),
              // Pin the app bar when scrolling
              pinned: 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.builder(
              // The builder function returns a ListTile with a title that
              // displays the index of the current item.
              itemBuilder: (context, index) =>
                  ListTile(title: Text('Item #$index')),
              // Builds 50 ListTiles
              itemCount: 50,
            ),
          ],
        ),
      ),
    );
  }
}
import 'package:flutter/cupertino.dart';

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

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

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

    return CupertinoApp(
      title: title,
      home: CupertinoPageScaffold(
        // No navigation bar provided to CupertinoPageScaffold,
        // only a body with a CustomScrollView.
        child: CustomScrollView(
          slivers: [
            // Add the navigation bar to the CustomScrollView.
            const CupertinoSliverNavigationBar(
              // Provide a standard title.
              largeTitle: Text(title),
            ),
            // Next, create a SliverList
            SliverList.builder(
              // The builder function returns a CupertinoListTile with a title
              // that displays the index of the current item.
              itemBuilder: (context, index) =>
                  CupertinoListTile(title: Text('Item #$index')),
              // Builds 50 CupertinoListTile
              itemCount: 50,
            ),
          ],
        ),
      ),
    );
  }
}