单子组件布局控件
1. Container
说明: 最常用的布局 Widget,可以包含一个子Widget,并可以设置 padding、margin、边框、背景等
规则: 如果没有子 Widget,Container 会尽可能大;如果有子 Widget,则根据子 Widget 和自身约束调整大小
注意: 在没有约束的情况下,Container会尽可能大(比如占满整个屏幕);在有约束的情况下(如父Widget是Column),Container如果没有子Widget,则会收缩到没有大小
推荐: 作为其他Widget的容器,用于装饰或设置间距
Container(
padding: const EdgeInsets.all(8.0),
margin: const EdgeInsets.all(16.0),
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(8.0),
),
child: const Text('Hello World'),
)
2. Padding
说明: 给子Widget设置内边距
规则: 只有一个子Widget
注意: 与Container的padding不同,Padding是一个独立的Widget
推荐: 当需要内边距但不需要Container的其他装饰时使用
Container(
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(12),
),
child: const Padding(
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 16),
child: Text(
"Flutter Padding 背景颜色示例",
style: TextStyle(color: Colors.white),
),
),
)
3. Align
说明: 控制子Widget在父Widget中的对齐方式
规则: 通过alignment属性设置对齐方式(如Alignment.center)
注意: 如果父Widget没有约束,Align会尽可能大;如果有约束,则根据约束调整大小,并将子Widget对齐
推荐: 用于精确控制子Widget的位置
Container(
height: 200,
width: 200,
color: Colors.grey,
child: Align(
alignment: Alignment.bottomRight,
child: Container(width: 50, height: 50, color: Colors.red),
),
)
4. Center
说明: 用于将子组件在父组件中水平和垂直居中显示(是Align(alignment: Alignment.center)的简写),Center 组件继承自 Align,因此它本质上是一个简化版的 Align,专门用于居中布局
规则: 如果 Center 没有子组件且父容器提供无界约束(unbounded),则 Center 会尽可能缩小自身尺寸,如果父容器提供有界约束(bounded),则 Center 会扩展到父容器的大小。有子组件时,Center 的尺寸会根据子组件的大小和父容器的约束动态调整。
如果设置了 widthFactor 或 heightFactor,子组件的尺寸会按比例缩放(例如 widthFactor: 2 会使子组件宽度翻倍)
注意: widthFactor 和 heightFactor用于调整子组件的宽度和高度比例,避免嵌套过多层级,如果父容器限制了尺寸(如
SizedBox
),需确保Center
的子组件尺寸在约束范围内推荐: 快速居中单个组件,与复杂布局结合,响应式布局
Center(
child: Container(
width: 200,
height: 100,
color: Colors.blue,
child: const Text(
"居中内容",
style: TextStyle(color: Colors.white),
),
),
)
5. AspectRatio
说明: 强制子Widget保持指定的宽高比
规则: 需要设置aspectRatio属性(宽/高)
注意: 父Widget必须提供约束,否则无法计算
推荐: 用于需要固定宽高比的场景,如播放器
AspectRatio(
aspectRatio: 16 / 9,
child: Container(color: Colors.blue),
)
6. ConstrainedBox
说明: 对子Widget施加额外的约束(BoxConstraints)
规则: 可以设置最小、最大宽高
注意: 如果子Widget本身有约束,可能会冲突,此时以更紧的约束为准
推荐: 用于需要限制子Widget大小的情况
ConstrainedBox(
constraints: const BoxConstraints(
minWidth: 100,
maxWidth: 200,
minHeight: 50,
maxHeight: 100,
),
child: Container(color: Colors.red),
)
7. UnconstrainedBox
说明: 解除父容器的约束,允许子控件按照自身大小绘制,然后根据实际大小再约束
规则: 子组件,其尺寸不会受到UnconstrainedBox的约束,若子组件尺寸超过父容器区域,Debug模式下会显示黄色溢出警告(Release模式会裁剪),若父级有多个约束组件(如嵌套的ConstrainedBox),UnconstrainedBox只能突破直接父级的约束,无法突破更高层约束
注意: constrainedAxis:null(默认):完全解除约束 / Axis.horizontal :仅水平方向解除约束,垂直方向仍受父级限制 / Axis.vertical :仅垂直方向解除约束,水平方向受限制,过度使用可能导致布局计算复杂化,建议仅在必要时使用
推荐: 适用于需要突破父容器约束的场景,例如在ListView或AppBar中保持子组件原始尺寸
ListView(
children: [
// 原始Container被拉伸至屏幕宽度
Container(width: 200, height: 100, color: Colors.red),
// 使用UnconstrainedBox保持原始尺寸
UnconstrainedBox(
child: Container(width: 200, height: 100, color: Colors.blue),
),
],
)
8. SizedBox
说明: 可以指定固定大小的盒子,也可以用于设置间隔
规则: 如果指定了width和height,则强制子Widget使用该大小(如果子Widget有约束,则可能会强制调整)
- SizedBox.shrink() 零尺寸占位符
- SizedBox.expand() 扩展填充占位符
- SizedBox.fromSize() 指定尺寸占位符
注意: 当没有子Widget时,SizedBox会占据指定大小的空间;有子Widget时,则强制子Widget大小为指定大小
推荐: 用于固定尺寸的盒子或间隔(如SizedBox(width: 10))
SizedBox(
width: 100,
height: 100,
child: Container(color: Colors.green),
)
9. FractionallySizedBox
说明: 子Widget的大小相对于父Widget的百分比
规则: 需要设置widthFactor和heightFactor(0.0到1.0)
注意: 父Widget必须提供约束,否则无法计算百分比
推荐: 用于需要相对父容器百分比大小的场景
Container(
width: 200,
height: 200,
color: Colors.blue,
child: FractionallySizedBox(
widthFactor: 0.5,
heightFactor: 0.5,
child: Container(color: Colors.red),
),
)
10. Transform
说明: 对子Widget进行矩阵变换(平移、旋转、缩放等)
规则: 变换不影响布局,变换是在布局之后进行的,所以可能会超出父Widget区域
注意: 变换后可能会超出父Widget范围,导致被裁剪(可以使用Clip.none避免)
推荐: 用于需要变换的场景,如旋转一个图标
Transform.rotate(
angle: 3.14 / 4, // 45度
child: Container(width: 100, height: 100, color: Colors.blue),
)
11. Baseline
- 说明: 根据子Widget的基线对齐(常用于文本), Baseline 的对齐方式有两种类型:
alphabetic: 对齐字母底部基线(适用于英文等拉丁文字)
ideographic: 对齐表意文字基线(适用于中文、日文等)
规则: 需要设置baseline和baselineType(如TextBaseline.alphabetic)
注意: 需要子Widget有基线(如Text),否则无效
推荐: 尤其适用于文字排版场景,处理混合文字(如中英文)时,通过baselineType区分基线类型,避免排版错乱
const Row(
children: [
Baseline(
baseline: 50.0,
baselineType: TextBaseline.alphabetic,
child: Text('Hello', style: TextStyle(fontSize: 20)),
),
Baseline(
baseline: 50.0,
baselineType: TextBaseline.alphabetic,
child: Text('World', style: TextStyle(fontSize: 30)),
),
],
)
12. FittedBox
说明: 对子Widget进行缩放和位置调整,以使其适应可用空间
规则: 通过fit属性设置适应方式(如BoxFit.contain)
注意: 如果子Widget没有约束,可能会出现问题
推荐: 用于需要缩放的场景,如保持图片比例并适应容器
Container(
width: 200,
height: 100,
color: Colors.amber,
child: FittedBox(
fit: BoxFit.contain,
child: Image.network(
'https://upload-images.jianshu.io/upload_images/1976231-cb638ee25dbc7368.png'),
),
)
13. OverflowBox
说明: 允许子Widget超出父Widget的约束,从而在父容器之外显示
规则: 设置自己的约束,子Widget可以突破父Widget的约束
注意: 可能导致布局溢出(无警告),使用时需注意
推荐: 在需要突破约束时使用,但需谨慎
Container(
color: Colors.green,
width: 200.0,
height: 200.0,
padding: const EdgeInsets.all(50.0),
child: OverflowBox(
alignment: Alignment.topLeft,
maxWidth: 400.0,
maxHeight: 400.0,
child: Container(
color: Colors.blueGrey,
width: 300.0,
height: 300.0,
),
),
)
14. LimitedBox
说明: 一个用于限制子组件最大尺寸的布局组件,当父Widget没有约束时,限制子Widget的最大宽高
规则: 在无约束时生效(如在ListView中,ListView沿着主轴方向有约束,但交叉轴方向无约束,此时在交叉轴方向使用LimitedBox可以限制最大宽高)
注意: 在父Widget有约束时无效
推荐: 在ListView中限制交叉轴方向的大小
Row(
children: [
Container(
color: Colors.grey,
width: 100.0,
),
LimitedBox(
maxWidth: 150.0,
maxHeight: 150.0,
child: Container(
color: Colors.lightGreen,
width: 250.0,
height: 250.0,
),
),
],
)
15. IntrinsicWidth/IntrinsicHeight
说明: 调整子Widget到其内部内容的高度或宽度(有性能问题,慎用)
规则: 迫使子Widget计算其内部内容的最大高度或宽度,并调整其他子Widget到相同高度或宽度
注意: 性能差,因为需要遍历子Widget两次(一次测量,一次布局)
推荐: 尽量避免使用,寻找其他布局方式替代。如果必须使用,注意性能影响
Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
IntrinsicWidth(
stepWidth: 100,
child: Container(
color: Colors.blue,
child: Center(
child: Container(
color: Colors.red,
width: 50,
height: 50,
),
),
),
),
],
)
16. CustomSingleChildLayout/CustomMultiChildLayout
说明: 使用自定义的布局代理进行布局,可以实现复杂的布局效果,CustomSingleChildLayout 是一个用于控制单个子组件布局的组件,CustomMultiChildLayout 是一个用于控制多个子组件布局的组件
规则: 需要自定义LayoutDelegate,SingleChildLayoutDelegate 来实现布局逻辑。该组件适用于需要对单个子组件进行复杂或非常规布局的场景,例如需要精确控制子组件的位置或尺寸时,MultiChildLayoutDelegate 来实现布局逻辑,适用于需要对多个子组件进行复杂布局的场景
注意: 相对复杂,需要自己实现布局逻辑
推荐:当其他布局Widget无法满足需求时使用,自定义的网格布局、层叠布局
CustomSingleChildLayout(
delegate: _MyDelegate(),
child: Container(color: Colors.blue),
)
class _MyDelegate extends SingleChildLayoutDelegate {
@override
BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
return constraints.loosen(); // 解除子组件约束
}
@override
Offset getPositionForChild(Size size, Size childSize) {
return Offset(size.width/2, 0); // 顶部居中
}
@override
bool shouldRelayout(covariant SingleChildLayoutDelegate oldDelegate) {
// TODO: implement shouldRelayout
throw UnimplementedError();
}
}
Container(
width: 200.0,
height: 100.0,
color: Colors.yellow,
child: CustomMultiChildLayout(
delegate: TestLayoutDelegate(),
children: <Widget>[
LayoutId(
id: TestLayoutDelegate.title,
child: Container(
color: Colors.red,
child: const Text('Title'),
),
),
LayoutId(
id: TestLayoutDelegate.description,
child: Container(
color: Colors.green,
child: const Text('Description'),
),
),
],
),
)
class TestLayoutDelegate extends MultiChildLayoutDelegate {
static const String title = 'title';
static const String description = 'description';
@override
void performLayout(Size size) {
final BoxConstraints constraints = BoxConstraints(maxWidth: size.width);
final Size titleSize = layoutChild(title, constraints);
positionChild(title, const Offset(0.0, 0.0));
final double descriptionY = titleSize.height;
layoutChild(description, constraints);
positionChild(description, Offset(0.0, descriptionY));
}
@override
bool shouldRelayout(TestLayoutDelegate oldDelegate) => false;
}
17. Placeholder
说明: 主要用于在开发过程中快速构建页面骨架,加速页面流程的运行。它可以在布局中占位,帮助开发者快速预览页面结构。Placeholder 的大小默认适合其容器,若位于无界空间(unbounded space),则根据 fallbackWidth 和 fallbackHeight 调整大小。Placeholder 支持自定义颜色、线条宽度、fallbackHeight 和 fallbackWidth
规则: 可以在 Row 或 Column 中使用 Placeholder,但需要通过 fallbackHeight 和 fallbackWidth 限定大小,在无界空间中,可以使用 fallbackWidth 和 fallbackHeight 来限定占位符的大小
注意: 虽然 Placeholder 是一个简单的占位符,但在复杂的布局中过多使用可能会影响性能,因此应合理使用
推荐: 在页面开发初期,可以使用 Placeholder 来快速构建页面骨架,帮助开发者快速预览页面结构
const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SizedBox(
height: 100,
child: Row(
children: [
Placeholder(
fallbackWidth: 100,
color: Colors.green,
strokeWidth: 10,
),
],
),
),
SizedBox(
width: 100,
child: Column(
children: [
Placeholder(
fallbackHeight: 100,
color: Colors.green,
strokeWidth: 10,
),
],
),
),
],
),
);
因为网站字数限制,只能分系列了,需要一次性看完请去这里
Flutter-详解布局(核心布局控件)
Flutter-详解布局(弹性和层叠布局辅助控件)
Flutter-详解布局(滚动和Sliver系列布局控件)
Flutter-详解布局(响应式和平台适配及特殊布局控件)
需要代码去这里DEMO