带有间距的列表项
也许您想创建一个列表,其中所有列表项都均匀分布,以便这些项占据可见空间。例如,下图中的四个项目均匀分布,“项目 0”位于顶部,“项目 3”位于底部。
同时,您可能希望允许用户在项目列表无法容纳时滚动浏览列表,这可能是因为设备太小、用户调整了窗口大小或项目数量超过屏幕大小。
通常,您可以使用 Spacer
来调整窗口小部件之间的间距,或使用 Expanded
来扩展窗口小部件以填充可用空间。但是,这些解决方案在可滚动窗口小部件内不可行,因为它们需要有限的高度约束。
此示例演示如何使用 LayoutBuilder
和 ConstrainedBox
在有足够空间时均匀地分隔列表项,并在没有足够空间时允许用户滚动,使用以下步骤:
- 使用
SingleChildScrollView
添加一个LayoutBuilder
。 - 在
SingleChildScrollView
内添加一个ConstrainedBox
。 - 创建一个带有间距项的
Column
。
1. 使用 SingleChildScrollView
添加 LayoutBuilder
#首先创建一个 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'),
),
],
),
),
),
);
});
交互式示例
#此示例显示一个项目列表,这些项目在列中均匀分布。当项目不适合屏幕时,可以上下滚动列表。项目数量由变量 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 的最新稳定版本。页面最后更新于 2025-01-30。 查看源代码 或 报告问题。