在清單頂部放置一個浮動的 app bar
為了方便使用者檢視清單,你可能希望在使用者向下捲動清單時隱藏 app bar,尤其在你的 app bar 特別高,導致它佔據了很多豎向空間的時候。
一般情況下,你可以透過給 Scaffold
元件設定一個 appBar
屬性來建立一個 app bar。這個 app bar 會始終固定在 Scaffold
元件的 body
上方。
把 app bar 從 Scaffold
元件挪到一個 CustomScrollView
裡,可以讓你建立一個隨著你滑動 CustomScrollView
裡清單的同時在螢幕外自動隨之捲動的 app bar。
下面這篇教程將介紹如何透過 CustomScrollView
來生成一個帶有隨著使用者滑動清單同時會在螢幕外隨之捲動的 app bar 的清單。
-
建立一個
CustomScrollView
-
透過
SliverAppBar
來新增一個浮動的 app bar -
透過
SliverList
來新增清單
CustomScrollView
1. 建立一個 要建立一個浮動的 app bar,你需要將 app bar
放在一個包含清單的 CustomScrollView
裡,這會同步 app bar 和清單的捲動位置。你可以把 CustomScrollView
元件當成一個可以讓你把不同型別的可捲動清單和元件混合對應在一起的 ListView
。
可以放在 CustomScrollView
裡的可捲動清單和元件我們稱之為 slivers。有幾種型別的 slivers,比如 SliverList
、SliverGrid
和 SliverAppBar
。實際上,ListView
和 GridView
元件底層使用的就是 SliverList
和 SliverGrid
。
以下例子示範了建立一個包含 SliverAppBar
和 SliverList
的 CustomScrollView
。另外你需要刪除你之前可能設定在 Scaffold
元件上的 app bar!
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>[]),
);
SliverAppBar
來新增一個浮動的 app bar
2. 使用 接下來為 CustomScrollView
新增一個 app bar。
Flutter 提供開箱即用的 SliverAppBar
元件,與普通的 AppBar
元件非常相似,你可以使用 SliverAppBar
來顯示標題、標籤、影象等內容。
同時,SliverAppBar
元件也提供一種建立『浮動』 app bar 的能力,當用戶向下捲動清單時,app bar 會隨之在螢幕外捲動。此外,你可以設定 SliverAppBar
在使用者捲動時縮小或展開。
要達到這個效果:
-
先建立一個只顯示標題的 app bar
-
將
floating
屬性設為true
,這使用戶在向上捲動清單時能快速顯示 app bar。 -
新增一個
flexibleSpace
元件,這個元件將填充可用的expandedHeight
。
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,
),
],
)
SliverList
來新增一個清單
3. 使用 現在你已經建立好一個 app bar,接下來應該給 CustomScrollView
新增一個清單。你有兩種選擇:選擇 SliverList
或者 SliverGrid
。如果你需要一個一個往下排地顯示清單中的內容,應該用 SliverList
元件。如果需要網格狀地顯示清單中的內容,應該用 SliverGrid
元件。
SliverList
和 SliverGrid
元件都需要一個必要引數:SliverChildDelegate
。雖然聽起來很花稍,但它只是用來給清單元件
SliverList
或 SliverGrid
提供一個代理。例如,SliverChildBuilderDelegate
允許你建立一組可以在捲動時延遲載入的清單項,就和 ListView.builder
元件差不多。
// 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,
),
),
],
),
),
);
}
}