帶間隔項的列表
如何建立帶有間隔或擴充套件項的列表
也許你想建立一個所有列表項均勻分佈的列表,使這些項能夠佔用可見空間。例如,下圖中四個專案均勻分佈,“項 0”在頂部,“項 3”在底部。
同時,你可能還希望在列表項無法完全顯示時(例如裝置太小、使用者調整了視窗大小或專案數量超過了螢幕尺寸)允許使用者滾動列表。
通常,你會使用 Spacer 來調整元件之間的間距,或者使用 Expanded 來拉伸元件以填充可用空間。然而,這些解決方案在可滾動元件內部是無法使用的,因為它們需要一個有限的高度約束。
本方案演示瞭如何使用 LayoutBuilder 和 ConstrainedBox 在有足夠空間時均勻分佈列表項,並在空間不足時允許使用者滾動,具體步驟如下:
- 新增一個帶有
SingleChildScrollView的LayoutBuilder。 - 在
SingleChildScrollView中新增一個ConstrainedBox。 - 建立一個帶有間隔項的
Column。
1. 新增一個 LayoutBuilder 和 SingleChildScrollView
#
首先建立一個 LayoutBuilder。你需要提供一個包含兩個引數的 builder 回撥函式:
LayoutBuilder提供的BuildContext。- 父元件的
BoxConstraints。
在本方案中,你不需要使用 BuildContext,但在下一步中需要用到 BoxConstraints。
在 builder 函式內部,返回一個 SingleChildScrollView。該元件確保即使父容器太小時,子元件也可以滾動。
LayoutBuilder(
builder: (context, constraints) {
return SingleChildScrollView(child: Placeholder());
},
);
2. 在 SingleChildScrollView 中新增 ConstrainedBox
#
在這一步中,新增一個 ConstrainedBox 作為 SingleChildScrollView 的子元件。
ConstrainedBox 元件會對其子元件施加額外的約束。
透過將 minHeight 引數設定為 LayoutBuilder 約束的 maxHeight 來配置約束。
這確保了子元件的最小高度被限制為 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 元件來調整專案間的間距,或者如果你希望某個元件佔據比其他元件更多的空間,則可以使用 Expanded 元件。
為此,你必須使用 IntrinsicHeight 元件包裹 Column,這會強制 Column 元件將其自身尺寸設定為最小高度,而不是無限擴充套件。
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: CardThemeData(color: Colors.blue.shade50),
),
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))),
);
}
}