等间距列表项
如何创建等间距或扩展的列表项
你也许想创建一个列表,让所有列表项均匀分布,从而占满可见空间。例如,下图中的四个列表项均匀分布,「Item 0」在顶部,「Item 3」在底部。
同时,当列表项放不下时(例如设备太小、用户调整了窗口大小,或列表项数量超出屏幕),你可能还希望允许用户滚动浏览列表。
通常你会用 Spacer 调整 widget 之间的间距,或用 Expanded
让 widget 占满可用空间。但在可滚动 widget 内部无法使用这些方案,因为它们需要有限的高度约束。
本食谱演示如何用 LayoutBuilder
和 ConstrainedBox,在空间足够时均匀分布列表项,在空间不足时允许用户滚动,步骤如下:
-
创建带等间距列表项的
Column。
1. 添加带 SingleChildScrollView 的 LayoutBuilder
#
首先创建 LayoutBuilder。你需要提供一个带两个参数的
builder 回调函数:
-
父 widget 的
BoxConstraints。
在本食谱中你不会用到 BuildContext,
但下一步会用到 BoxConstraints。
在 builder 函数中返回 SingleChildScrollView。该 widget 确保子 widget 可滚动,即使父容器太小也是如此。
LayoutBuilder(
builder: (context, constraints) {
return SingleChildScrollView(child: Placeholder());
},
);
2. 在 SingleChildScrollView 内添加 ConstrainedBox
#
在本步中,将 ConstrainedBox
作为 SingleChildScrollView
的子 widget 添加。
ConstrainedBox
widget 会为其子 widget 施加额外约束。
将 minHeight 参数设为 LayoutBuilder
约束的 maxHeight 来配置约束。
这确保子 widget 的最小高度等于 LayoutBuilder
约束提供的可用空间,即 BoxConstraints
的最大高度。
LayoutBuilder(
builder: (context, constraints) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(minHeight: constraints.maxHeight),
child: Placeholder(),
),
);
},
);
但不要设置 maxHeight 参数,因为当列表项放不下屏幕时,你需要允许子 widget 大于 LayoutBuilder
的尺寸。
3. 创建带等间距列表项的 Column
#
最后,将 Column 作为
ConstrainedBox
的子 widget 添加。
要均匀分布列表项,将 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 占用比其他项更多的空间。
为此,你需要用 IntrinsicHeight
widget 包裹 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))),
);
}
}
除非另有说明,本文档之所提及适用于 Flutter 3.44.0 版本。本页面最后更新时间:2026-06-04。查看文档源码 或者 为本页面内容提出建议。