文章目录
一、单子 Widget 嵌套布局:
单子 Widget是指只有一个子组件的Widget,这样布局Widget有三个:Container、Padding、Center
1、Container
Container,是一种允许在其内部添加其他控件的控件,也是 UI 框架中的一个常见概念。
在 Flutter 中,Container 本身可以单独作为控件存在(比如单独设置背景色、宽高),也可以作为其他控件的父级存在:Container 可以定义布局过程中子 Widget 如何摆放,以及如何展示。与其他框架不同的是,Flutter 的 Container 仅能包含一个子 Widget。
先简单写一个Container,尺寸200x200;在内部居左上放一个子Container,尺寸80x80
- 代码如下:
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: _container(), // This trailing comma makes auto-formatting nicer for build methods.
);
}
Container _container(){
return Container(
width: 200,
height: 200,
color: Colors.yellow,
alignment: Alignment.topLeft,
child: Container(
color: Colors.red,
width: 80,
height: 80,
),
);
}
- 展示效果:

a、padding
padding可以理解为是Container的"内边框",他会影响内部子控件的位置,示例代码:
Container _container(){
return Container(
width: 200,
height: 200,
padding: EdgeInsets.all(20),
color: Colors.yellow,
child: Container(
color: Colors.red,
),
);
}
上面代码把子Container的宽高限制去掉,这样它就可以尽可能的充满父Container,但是父Container有padding,导致它无法充满,效果如下:

b、margin
margin可以理解为是Container的"外边框",他会影响当前控件的位置,示例代码:
Container _container(){
return Container(
width: 200,
height: 200,
margin: EdgeInsets.all(20),
padding: EdgeInsets.all(20),
color: Colors.yellow,
child: Container(
color: Colors.red,
),
);
}
上面代码给父Container添加了margin,效果如下:

可以看到,父Container已经不再和屏幕左上对齐,而是隔开了一段距离,这个就是margin的效果,使视图具有外边距
2、Padding
Padding 有padding和child两个参数,Padding本身不是视图,是一种布局的描述
- 代码如下:
Padding _padding(){
return Padding(
padding: EdgeInsets.all(20.0),
child: Container(
color: Colors.red,
width: 200,
height: 200,
)
);
}
- 展示效果:

可以看到,由于Padding设置了padding为 EdgeInsets.all(20.0),使子组件视图的布局与它的父视图会产生20像素的间隔
3、Center
Center与Padding一样,本身不是视图,是一种布局的描述,它使子视图的位置在父视图中心
- 代码如下:
Center _center(){
return Center(
child: Container(
color: Colors.red,
width: 200,
height: 200,
)
);
}
- 展示效果:

可以看到子视图的位置在父视图的正中间,这个就是Center的作用!!
二、多子 Widget 布局:
多子 Widget是指有多个子组件的Widget,这样布局Widget大致有三个:Row、Column、Stack,配合的单组件布局Widget有:Expanded、Positioned;Row、Column一般和Expanded配合使用,Stack一般和Positioned配合使用后面会详细介绍。
对于拥有多个子 Widget 的布局类容器而言,其布局行为无非就是两种规则的抽象:水平方向上应该如何布局、垂直方向上应该如何布局。如同 Android 的 LinearLayout、前端的 Flex 布局一样,Flutter 中也有类似的概念,即将子 Widget 按行水平排列的 Row,按列垂直排列的 Column,以及负责分配这些子 Widget 在布局方向(行 / 列)中剩余空间的 Expanded。
1、Row与Column
Row与Column 本身不是视图,是一种布局的描述,它表示将子组件排列在水平一行或者垂直一列,代码及效果如下:
Row _row(){
return Row(
children: [
Container(
color: Colors.red,
width: 40,
height: 40,
),
Container(
color: Colors.yellow,
width: 200,
height: 200,
),
Container(
color: Colors.blue,
width: 80,
height: 80,
)
],
);
}

Column _column(){
return Column(
children: [
Container(
color: Colors.red,
width: 40,
height: 40,
),
Container(
color: Colors.yellow,
width: 200,
height: 200,
),
Container(
color: Colors.blue,
width: 80,
height: 80,
)
],
);
}

2、Row与Column 结合Expanded使用
Expanded表示自动填满,当Container不设置width时,他就会将width自动扩展到最大,示例代码及效果如下:
Row _row(){
return Row(
children: [
Container(
color: Colors.red,
width: 40,
height: 40,
),
Container(
color: Colors.yellow,
width: 200,
height: 200,
),
Expanded(
child:Container(
color: Colors.blue,
height: 80,
)
)
],
);
}

如图所示,最后一个Container的宽度自动填满,这个就是Expanded的布局效果。Column与Expanded结合使用就不多做介绍了。
3、Row与Column 子视图排列方式
a、mainAxisAlignment与crossAxisAlignment
于 Row 与 Column 而言,Flutter 提供了依据坐标轴的布局对齐行为,即根据布局方向划分出主轴和纵轴:主轴,表示容器依次摆放子 Widget 的方向;纵轴,则是与主轴垂直的另一个方向。

我们可以根据主轴与纵轴,设置子 Widget 在这两个方向上的对齐规则 mainAxisAlignment 与 crossAxisAlignment。比如,主轴方向 start 表示靠左对齐、center 表示横向居中对齐、end 表示靠右对齐、spaceEvenly 表示按固定间距对齐;而纵轴方向 start 则表示靠上对齐、center 表示纵向居中对齐、end 表示靠下对齐。
下图展示了在 Row 中mainAxisAlignment设置不同方向的对齐规则后的呈现效果:

下图展示了在 Row 中crossAxisAlignment设置不同方向的对齐规则后的呈现效果:

- 部分代码示例:
Row _row(){
return Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Container(
color: Colors.red,
width: 40,
height: 40,
),
Container(
color: Colors.yellow,
width: 200,
height: 200,
),
Container(
color: Colors.blue,
width: 80,
height: 80,
)
],
);
}
b、mainAxisSize
如果想让容器与子 Widget 在主轴上完全匹配,我们可以通过设置 Row 的 mainAxisSize 参数为 MainAxisSize.min,由所有子 Widget 来决定主轴方向的容器长度,即主轴方向的长度尽可能小,类似 Android 中的 wrap_content,注意,mainAxisSize只有当 mainAxisAlignment为 MainAxisAlignment.spacexxx类型的时候才会生效。
- 当mainAxisSize为MainAxisSize.min时

- 当mainAxisSize为MainAxisSize.max时

4、层叠 Widget 布局:Stack 与 Positioned
有些时候,我们需要让一个控件叠加在另一个控件的上面,比如在一张图片上放置一段文字,又或者是在图片的某个区域放置一个按钮。这时候,我们就需要用到层叠布局容器 Stack 了。Stack 容器与前端中的绝对定位、与iOS 中的 Frame 布局非常类似,子 Widget 之间允许叠加,还可以根据父容器上、下、左、右四个角的位置来确定自己的位置。Stack 提供了层叠布局的容器,而 Positioned 则提供了设置子 Widget 位置的能力,代码如下:
Stack _stack(){
return Stack(
children: [
Container(
color: Colors.yellow,
width: 200,
height: 200,
),
Positioned(
left: 18.0,
top: 18.0,
child: Container(
color: Colors.red,
width: 40,
height: 40,
),
)
],
);
}

可以看到,虽然两个Container是平级,但是他们是叠放在一起的。Stack 控件允许其子 Widget 按照创建的先后顺序进行层叠摆放,类似于iOS addSubview,而 Positioned 控件则用来控制这些子 Widget 的摆放位置。需要注意的是,Positioned 控件只能在 Stack 中使用,在其他容器中使用会报错。
本文详细介绍了Flutter中的常用布局方式,包括单子Widget的Container、Padding、Center布局,以及多子Widget的Row、Column、Stack布局,并结合Expanded和Positioned的使用,展示了各种布局效果和属性的调整,帮助开发者更好地理解和应用Flutter布局。
2002

被折叠的 条评论
为什么被折叠?



