本指南描述瞭如何在 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 來顯示標題、標籤、影像等等。

但是,SliverAppBar 還允許你建立“浮動”應用欄,當不在頁面頂部時,它會縮小並浮動。

要建立此效果

  1. 從一個只顯示標題的應用欄開始。
  2. pinned 屬性設定為 true
  3. 新增一個 flexibleSpace 小部件,它填充可用的 expandedHeight
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,
            ),
          ],
        ),
      ),
    );
  }
}