具有間隔項目的清單
您可能想要建立一個清單,其中所有清單項目都間隔均勻,以便項目佔據可見空間。例如,下圖中的四個項目間隔均勻,「項目 0」位於頂部,「項目 3」位於底部。
同時,您可能希望允許使用者在項目清單不適合時捲動清單,可能是因為裝置太小、使用者調整了視窗大小,或項目數量超過螢幕大小。
通常,您會使用 Spacer
來調整 Widget 之間的間距,或使用 Expanded
來展開 Widget 以填滿可用空間。然而,這些解決方案在可捲動的 Widget 內部是不可行的,因為它們需要有限的高度約束。
本食譜示範如何使用 LayoutBuilder
和 ConstrainedBox
,在空間足夠時均勻間隔清單項目,並允許使用者在空間不足時捲動,使用以下步驟
- 加入具有
SingleChildScrollView
的LayoutBuilder
。 - 在
SingleChildScrollView
內部加入ConstrainedBox
。 - 建立具有間隔項目的
Column
。
1. 加入具有 SingleChildScrollView
的 LayoutBuilder
#首先,建立一個 LayoutBuilder
。您需要提供一個具有兩個參數的 builder
回呼函式
LayoutBuilder
提供的BuildContext
。- 父 Widget 的
BoxConstraints
。
在本食譜中,您不會使用 BuildContext
,但在下一步中您會需要 BoxConstraints
。
在 builder
函式內部,傳回一個 SingleChildScrollView
。此 Widget 可確保子 Widget 可以捲動,即使父容器太小。
LayoutBuilder(builder: (context, constraints) {
return SingleChildScrollView(
child: Placeholder(),
);
});
2. 在 SingleChildScrollView
內部加入 ConstrainedBox
#在此步驟中,將 ConstrainedBox
加入為 SingleChildScrollView
的子項。
ConstrainedBox
Widget 會對其子項施加額外的約束。
將 minHeight
參數設定為 LayoutBuilder
約束的 maxHeight
,來設定約束。
這可確保子 Widget 的最小高度被約束為等於 LayoutBuilder
約束提供的可用空間,也就是 BoxConstraints
的最大高度。
LayoutBuilder(builder: (context, constraints) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(minHeight: constraints.maxHeight),
child: Placeholder(),
),
);
});
然而,您不設定 maxHeight
參數,因為您需要允許子項大於 LayoutBuilder
的大小,以防項目不適合螢幕。
3. 建立具有間隔項目的 Column
#最後,將 Column
加入為 ConstrainedBox
的子項。
為了均勻間隔項目,請將 mainAxisAlignment
設定為 MainAxisAlignment.spaceBetween
。
LayoutBuilder(builder: (context, constraints) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(minHeight: constraints.maxHeight),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ItemWidget(text: 'Item 1'),
ItemWidget(text: 'Item 2'),
ItemWidget(text: 'Item 3'),
],
),
),
);
});
或者,您可以使用 Spacer
Widget 來調整項目之間的間距,或使用 Expanded
Widget,如果您希望一個 Widget 比其他 Widget 佔用更多空間。
為此,您必須使用 IntrinsicHeight
Widget 包裹 Column
,這會強制 Column
Widget 將自身調整為最小高度,而不是無限展開。
LayoutBuilder(builder: (context, constraints) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(minHeight: constraints.maxHeight),
child: IntrinsicHeight(
child: Column(
children: [
ItemWidget(text: 'Item 1'),
Spacer(),
ItemWidget(text: 'Item 2'),
Expanded(
child: ItemWidget(text: 'Item 3'),
),
],
),
),
),
);
});
互動式範例
#此範例顯示一個清單,其中的項目在一個 Column 內均勻間隔。當項目不適合螢幕時,可以上下捲動清單。項目數量由變數 items
定義,變更此值以查看當項目不適合螢幕時會發生什麼。
import 'package:flutter/material.dart';
void main() => runApp(const SpacedItemsList());
class SpacedItemsList extends StatelessWidget {
const SpacedItemsList({super.key});
@override
Widget build(BuildContext context) {
const items = 4;
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
cardTheme: CardTheme(color: Colors.blue.shade50),
useMaterial3: true,
),
home: Scaffold(
body: LayoutBuilder(builder: (context, constraints) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(minHeight: constraints.maxHeight),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: List.generate(
items, (index) => ItemWidget(text: 'Item $index')),
),
),
);
}),
),
);
}
}
class ItemWidget extends StatelessWidget {
const ItemWidget({
super.key,
required this.text,
});
final String text;
@override
Widget build(BuildContext context) {
return Card(
child: SizedBox(
height: 100,
child: Center(child: Text(text)),
),
);
}
}
除非另有說明,否則本網站上的文件反映了 Flutter 的最新穩定版本。頁面上次更新時間為 2024-06-26。 檢視原始碼 或 回報問題。