封面图

第139期:Flutter的flex布局组件(row 和 column)_前端

Row 组件

这两个组件可以用来进行做flex布局,row可以用来做水平方向的布局,column可以用来进行垂直方向上的布局,这两个类都是基于web的flex布局模式实现的。

​Row​​​组件通常不会考虑到内部元素的滚动问题,如果Row中的子组件超过可用空间的大小,则会被视为一种错误。如果我们有几个组件,并且希望在空间不足的时候有个滚动效果,那么我们就可以考虑使用​​ListView​​组件。

​Row​​组件类有这么几个属性:

  • ​children​​:要进行布局的子组件。
  • ​crossAxisAlignment​​: 交叉轴对齐方式。
  • ​mainAxisAlignment​​: 主轴对齐方式。
  • ​mainAxisSize​​: 主轴上占用的空间。
  • ​textDirection​​: 控制子元素的排列方向。

如果我们只有一个组件,在用​​Row​​组件进行布局的时候,我们通常可以让它居中:

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('出发~'),
]
),
);
}

当我们​​Row​​组件中的内容超出它的空间时,屏幕上就会出现黄黑相间的条纹警示信息。

第139期:Flutter的flex布局组件(row 和 column)_ide_02

这时候我们可以把文本包裹在​​Expanded​​组件中来解决这个问题:

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Expanded(
child: Text(
'Flutters hot reload helps you quickly and easily experiment, build UIs, add features, and fix bug faster. Experience sub-second reload times, without losing state, on emulators, simulators, and hardware for iOS and Android.'),
)
]
),
);
}

​crossAxisAlignment​​​,​​mainAxisAlignment​​​,​​mainAxisSize​​​,​​textDirection​​这几个属性我们稍微用小拇指琢磨一下,其实他们都是枚举类型:

  • start
  • end
  • center
  • spaceAround
  • spaceBetween
  • stretch ...

具体的值和css中的flex布局属性保持了一致。

Row 组件布局算法流程

​Row​​组件的布局分为六个步骤:

  1. 使用无边界的水平约束和传入的垂直约束,为每个子对象布置一个空或零的弹性因子。如果设置的交叉轴属性为stretch,则改用与传入最大高度匹配的紧密垂直约束。
  2. 根据弹性系数在具有非零弹性系数(例如,展开的弹性系数)的子级之间划分剩余的水平空间。例如,弹性系数为2.0的子级将获得的水平空间量是弹性系数为1.0的子级的两倍。
  3. 使用与步骤1中相同的垂直约束来布局剩余的每个子对象,但并不使用无边界的水平约束,而是使用基于步骤2中分配的空间量的水平约束。子元素中带有​​Flexible.fit​​​属性值为​​tight​​​的则强制填充分配的空间,​​Flexible.fit​​​属性值为​​loose​​的,则不再强制填充分配的空间。
  4. 设置Row的高度为子对象的最大高度(始终满足传入的垂直约束)。
  5. 设置Row的宽度。Row的宽度由mainAxisSize属性决定。如果​​mainAxisSize​​​属性为​​mainAxisSize.max​​​,则Row的宽度是传入约束的最大宽度。如果​​mainAxisSize​​​属性为​​mainAxisSize.min​​,则Row的宽度是子对象的宽度之和。
  6. 根据​​mainAxisAlignment​​​和​​crossAxisAlignation​​​确定每个子对象的位置。例如,如果​​mainAxisAlignment​​​是​​mainAxisAlignment.spaceBetween​​,任何未分配给子对象的水平空间都将被平均分配并放置在子对象之间。

Cloumn组件

Cloumn组件主要用来将子组件进行垂直方向上的布局。想要要使子组件展开以填充可用的垂直空间,我们可以将子组件包裹在​​Expanded​​件中。

同样,Cloumn组件默认也不支持滚动,如果我们想要滚动的功能,那么我们还得考虑使用​​ListView​​组件。

Cloumn组件上的属性和Row 组件上的属性基本一致,这里就不再多说了。

当传入的组件没有具体的垂直约束边界(高度)时,我们可能会遇到各种问题,比如:

我们不用​​Expanded​​组件对Cloumn组件进行包裹,而Cloumn组件中的内容超出了容器本身的限制。

或者我们把Cloumn组件嵌入到了​​ListView​​组件中。

第139期:Flutter的flex布局组件(row 和 column)_属性值_03

这时候我们需要考虑组件内部的结构到底应该怎么布局,子组件的大小具体应该设置成什么?是否应该移除一些多余的内容等等。

Cloumn 组件布局算法流程

​Cloumn​​组件的布局也分为六个步骤:

  1. 使用无边界的垂直约束和传入的水平约束,为每个子对象布置一个空或零的弹性因子。如果​​crossAxisAlignment​​​为​​crossAxisAlignment.stretch​​,则使用与传入的最大宽度匹配的紧密水平约束。
  2. 根据弹性系数在具有非零弹性系数(的子级之间划分剩余的垂直空间。例如,弹性系数为2.0的子级将获得两倍于弹性系数为1.0的子级的垂直空间量。
  3. 使用与步骤1中相同的水平约束来布局剩余的每个子对象,但不要使用无边界的垂直约束,而是使用基于步骤2中分配的空间量的垂直约束。子元素中带有​​Flexible.fit​​​属性值为​​tight​​​则强制填充分配的空间),​​Flexible.fit​​​属性值为​​loose​​的,则不再强制填充分配的空间。
  4. 设置Cloumn的宽度为子项的最大宽度。
  5. 设置Cloumn的高度。Cloumn的高度由​​mainAxisSize​​​属性确定。如果​​mainAxisSize​​​属性为​​mainAxisSize.max​​​,则Column的高度为传入约束的最大高度。如果​​mainAxisSize​​​属性为​​mainAxisSize.min​​,则Column的高度为子对象的高度之。
  6. 根据​​mainAxisAlignment​​​和​​crossAxisAlignation​​​确定每个子对象的位置。例如,如果​​mainAxisAlignmen​​​t是​​mainAxisAlignment.spaceBetween​​,任何未分配给子对象的垂直空间都将被均匀划分并放置在子对象之间。

最后

掌握了这些内容,就算是掌握了flutter的Cloumn组件 和 Row 组件。