1.2.1 Column
竖列(Column)可将多个子组件沿着垂直的“纵坐标轴”方向排列。由于它需要同时排列多个子组件,所以嵌套子组件的参数不是child,而是复数形式children,代码如下:
图1-13 借助Column组件垂直排列5个组件
这样就可以把5个组件垂直排列在一个“竖列”中,运行效果如图1-13所示。
这里值得一提的是,上例Column的5个子组件中第4个是一个高度为30单位且无填充色的空白Container组件。实战中,页面布局设计可能经常需要在组件之间留白,而插入透明的组件是一种较为常见的思路。有经验的开发者通常会使用SizedBox组件而不是Container组件做到同样的视觉效果,因为前者可使程序运行更高效。SizedBox组件实际上就是一个单纯负责设置尺寸的组件,且可以借助Dart语法中的const关键字进一步提升运行效率,具体用法可参考本章关于SizedBox组件的介绍。
1.子组件的传入
不同于常见的child参数,这里的子组件由children参数接收一个“组件列表”类型,即一系列需要嵌在Column里面的子组件。通常情况下,Column用于程序界面布局,如登录页面等,所以传入的子组件应该都是需要显示到屏幕上的,一般不希望出现“放不下”的情况。如果需要展示的内容不属于程序界面而属于业务逻辑内容的渲染,如产品列表、公司人员列表、财务清单等可能会出现几百甚至几万个元素,应该考虑使用ListView组件,而不是这里的Column组件。ListView组件支持用户滑动翻页,具体用法可以参考第5章“列表和网格”的相关介绍。
2.主轴和交叉轴
因为Column组件会将子组件依次垂直排列,所以垂直方向又称为“主轴”方向,而“交叉轴”方向是指与主轴成90°直角的方向,因此Column组件的交叉轴是水平方向的。简而言之,因为Column组件把子组件“竖着排列”,所以它的主轴就是“竖着的”,而它的交叉轴就是“横着的”。
1)mainAxisSize属性
主轴尺寸是指Column组件在主轴方向(垂直方向)所占的空间。传入类型为MainAxisSize,默认值是MainAxisSize. max(尽量大),例如可通过这个属性将其设置成MainAxisSize. min(尽量小)。默认情况下,Column组件在不打破父级组件尺寸约束的前提下,会在主轴方向尽量多占空间,例如填满全屏幕的高度,如图1-14(左图)所示,但如果传入MainAxisSize. min,则会使Column缩至子组件高度的总和,运行效果如图1-14(右图)所示。图中灰色部分为Column组件的背景色,以方便观察它们所占的空间。
程序运行时,Column组件会根据其父级约束及其children的总尺寸,配合mainAxisSize属性,最终确定自身尺寸。当全部子组件尺寸相加后依然低于父级组件提供的最大可用空间时,该属性就可以决定Column组件是否应该将剩余的空间占满。
这里需要注意的是,Flutter组件在布局的过程中一般不会违背父级约束。例如当Column组件的父级组件是一个尺寸为300×300单位的Container组件时,则该Column组件自身尺寸一定也会是300×300单位,因此这里的mainAxisSize属性就无法生效。换言之,即使将主轴尺寸设置为“尽量小”,Column组件若受到父级约束的最小尺寸限制,则它排列完children后仍可能会有剩余空间。反之,若children参数传入的子组件数量过多,或者高度总和过大,即使将主轴尺寸设置为“尽量大”,Column组件依然会在排列完后没有剩余空间。更进一步,如果Column组件的高度不足以安放所有子组件,就会在运行时渲染“溢出”的黑黄色警戒线效果,如图1-15所示,提醒开发者注意调整布局。
图1-14 Column组件的主轴尺寸属性
图1-15 提示Column组件底部溢出70像素
此类“溢出警戒线”只会在调试模式(Debug Mode)出现。正式发布版(Release)的Flutter程序不应出现溢出提示,而是直接裁剪掉溢出的部分不予显示,并且不报错。
2)mainAxisAlignment属性
主轴对齐方式,需要传入的类型为MainAxisAlignment类,默认为MainAxisAlignment. start,即沿主轴起始位置摆放。在垂直排列的Column组件里,起始位置一般为顶部,如图1-16(左图)所示。若需将子组件沿主轴末尾位置摆放,则可通过传入MainAxisAlignment. end实现,如图1-16(中图)所示。如需居中摆放,则可传入MainAxisAlignment. center,如图1-16(右图)所示。
除了主轴的起始、中间、末尾3个位置外,Column组件还提供了另外3种可自动插入留白的对齐方式,分别是spaceBetween(在相邻的子组件之间插入空白,但不在第一个和最后一个子组件外围插入留白)、spaceEvenly(在子组件周围统一插入留白)、spaceAround(在相邻的子组件之间插入留白,并在第一个和最后一个子组件外围插入一半的留白)。图1-17从左到右依次展示了spaceBetween、spaceEvenly和spaceAround的效果。
图1-16 主轴对齐中3种不留白的效果
图1-17 主轴对齐中3种留白的效果
若主轴排列完所有子组件后并没有出现剩余空间,则这里的对齐就没有效果。如需要在Column组件的任意特定位置设置固定留白,则可以通过在children属性中插入透明的Container组件或SizedBox组件实现。
3)crossAxisAlignment属性
交叉轴对齐方式,默认为居中对齐,即CrossAxisAlignment. center。如果需要向左或者向右对齐,则可以通过传入start和end设置。图1-18从左到右依次展示了CrossAxisAlignment.center(中间)、CrossAxisAlignment. start(起始)和CrossAxisAlignment. end(结束)的效果。
除了以上3种交叉轴对齐方式外,Flutter还提供了stretch和baseline这2种对齐选项。前者要求子组件在宽度上尽量拉伸,以填满整个父级组件的最大约束。例如,实战中可通过它实现“所有按钮宽度一致”的效果。后者则是按照子组件文字的基准线对齐。这是Column组件由父类Flex组件继承而来的属性,一般实战中不会在Column组件中使用。
3.垂直方向
垂直方向(verticalDirection属性)是指子组件的排列顺序,默认为从上到下进行排列,即VerticalDirection. down 方向。如果有必要,则可以通过VerticalDirection. up在运行时反转子组件的顺序。图1-19分别展示了默认的排列方向及反转后的运行效果。
图1-18 交叉轴的3种不同对齐方式
图1-19 左边为默认情况,右边以“从下到上”的顺序排列
这个属性使用率不高,因为Column组件主要用于渲染用户界面元素,而不用于显示诸如货物清单等逻辑业务元素,因此Column内部子组件的顺序通常在设计和开发时就已经确定了,不太需要通过该属性在运行时调整顺序。