1.Column 和Row 是横向关系的对比而已。
同样的,column 中的子widget 不能超过屏幕的剩余空间,不支持上下滚动。如果需要支持滚动则要使用ListView
。
如果只有一个child,可以考虑用Center
或者Align
来定位child。
demo
body: new Column(
children: <Widget>[
new Text('eliver features faster'),
new Text('Craft beautiful UIs'),
new Expanded(
child: new FittedBox(
child: const FlutterLogo(),
))
],
),
效果如下: text,和 图片都是居中显示。
可以通过设置
crossAxisAlignment
属性改变对其方式,例如设置 crossAxisAlignment
为rossAxisAlignment.start
可以让child从左对齐,设置mainAxisSize
为MainAxisSize.min
可以是column最小化适应子控件。
demo如下
body: new Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
new Text('We move under cover and we move as one'),
new Text('Through the night, we have ondd ddddddddddd ddddddd ddddddd ddddddddde shot to live another day'),
new Text('We cannot let a stray gunshot give us away'),
new Text('We will fight up close, seize the moment and stay in it'),
new Text('It’s either that or meet the business end of a bayonet'),
new Text('The code word is ‘Rochambeau,’ dig me?'),
new Text('Rochambeau!',
style: DefaultTextStyle
.of(context)
.style
.apply(fontSizeFactor: 0.5)),
],
),
2.棘手的问题
-
2.1当输入的垂直约束是无界限的怎么办?
当一个column嵌套在另一个column或者ListView中,并且这个column有一个或多个Expanded 或Flexible 的子控件时,会出现运行时异常,错误大概是:包含非零的flex 子控件,但是垂直约束是无界限。
刚才上面的异常主要是因为使用Flexible或Expanded意味这对于剩余空间是平均分配的,但是输入的垂直约束是无界限的,这样就意味有无限的剩余空间,显然无法平均分配。
解决这个问题的核心需要确认为什么,Column
需要接受无界限的垂直约束。
- 一个常见的原因是:
column
被嵌套在另一个column
(内嵌的Column
并没有使用Expanded
或者Flexible
)中。当column
包裹他的非弹性子孩子(指的非Expanded
或Flexible
的子控件),column会传递子控件无界限约束因此子控件可以根据控制自己的大小(传递无限制约束通常意味着子控件需要自适应自己的内容)。在这种情况下,
解决方案通常是用Expanded来包裹里面的Column,并且指定它需要占外部的剩余空间,而不是让他占据所需要的任意空间。
- 另一个原因是 在ListView或其他垂直带可滑动的控件中内嵌Column。这种场景下,确实存在无线的垂直空间(关键是整个垂直列表允许无限空间)。这时通常值得检查下内部的Colunm需要Expanded或者Flexible 子控件的原因:子类所需要实际的大小是多少?
典型的解决方案是移除内部的Expanded或者Flexible控件。
2.2.黄黑条纹警告线
当Column里面的内容超出了剩余空间,Column溢出了,并且里面的内容被裁剪了。在debug模式下,在溢出边沿出现黄黑条纹警告线意味这出了异常,并且会打印检测出现溢出的多少信息。
解决的方案通常是采用ListView代替Column,以便于在受限的垂直方向上面可以滚动。
3. Layout布局算法
这一部分主要描述Column在framework中的具体是如何渲染的。可以通过查看BoxConstraints
了解具体的装载layout的数据模型。
Column进行布局主要包括6步:
step1>
为每个子节点设置一个空或零Flex因子(例如,那些没有展开的),其中包含无限制的垂直约束和输入的水平约束。如果crossAxisAlignment
设置为CrossAxisAlignment.stretch
而不是采用紧缩水平约束来匹配输入的最大宽度。
step2>
通过设置的flex因子,将剩余垂直空间分配给具有非零flex因子的孩子(例如 Expanded)例如,某个孩子拥有flex 因子2.0的将会是另一个flex因子为1.0的2倍垂直空间。
step3>
使用与步骤1相同的水平约束来布局每个剩余的子节点,但是使用基于步骤2中分配的空间量的垂直约束来代替无限制的垂直约束。具有Flexible.fit属性为FlexFit.tight的子节点被给予严格的约束(即,强制填充分配的空间),具有Flexible.fit属性为FlexFit.look的子节点被给予松散约束(即,不强制填充分配的空间)。
step4>
Column的宽度通常是子节点(通常满足输入的子节点的约束)的最大宽度。
step5>
Column的高度取决于mainAxisSize
属性。如果mainAxisSize
设置为MainAxisSize.max,那么column的高度则是输入约束的最大高度。如果MainAxisSize
设置为MainAxisSize.min
,那么column的高度则是子节点(所输入的约束的目标结点)的高度之和。
step6>
通过mainAxisAlignment
和crossAxisAlignment
确定子节点的位置。例如,如果mainAxisAlignment
是MainAxisAlignment.spaceBetween
,则未分配给子节点的任何垂直空间被均匀地分割并放置在子节点之间。