满怀信心使用Column进行布局,总会遇到各种各样异常,有的直接报错,有的表现形式和预想的不同。下面直接分场景归纳并解决Column中的问题(大多数布局问题都有Column这货参与):
1.Column中嵌套Column,外层Column直接撑满屏幕,而内层Column只是刚好为子元素高度(子元素没有Flexible类型组件)
2.Column中嵌套Column,内层Column有Expanded,直接抛出异常
3.Scroll类型组件中嵌套Column,Column只是刚好为子元素高度(子元素没有Flexible类型组件),和场景一表现一致
4.Scroll类型组件中嵌套Column,内层Column有Expanded,直接抛出异常,报错和场景二一致
1、3,2、4场景极为相似,阅读源码后发现原因都是
场景2,4报错信息总结为一句话:
RenderFlex children have non-zero flex but incoming height constraints are unbounded.
什么时unbounded的constraints?,源码告诉我们:“An axis whose maximum constraint is infinite is _unbounded_.”,也就是maxHight为无限大,这会引发什么现象?源码中又有透露:
“it gives them unbounded constraints so that they can determine their own dimensions (passing unbounded constraints usually signals to the child that it should shrink-wrap its contents)”
就是让接收到unbounded constraints的元素收缩到刚好包裹子元素(其实就是尽可能小),这就是场景1,3出现的原因。在此基础上,如果你一意孤行,在内层的Column内部使用Expanded或者Flexible这些flex值为1的组件,它们在分配空间时按照flex比例划分剩下的可用空间,而可用空间是无限的(因为unbounded constraints意味着maxHeight为无限,就是说有无限的可用空间),这是渲染无法做到的,于是报错,出现场景2,4。解决的最好实践如下:
场景1:其实并没有什么问题,如果想要让内层Column也撑满高度,可以把它包裹在外层Expanded中
场景2、4:可以按照1中来,知道了问题所在自由发挥都行,既然是可用空间无限导致问题,给定一个有限的maxHight值就ok了,甚至可以在内层Column中使用mainAxisSize: MainAxisSize.min配合Flexible(这样虽然可以但是多此一举,没必要,但有助于理解),详细解决见这里
场景3:其实并没有什么问题,拿出来说只是为了解释Column的特性
附上一段可以自由把玩,理解原理的代码,里面的注释可以随意取消掉看看效果,报错了也可以看看控制台提示:
Widget build(BuildContext context) {
return ConstrainedBox(
constraints: BoxConstraints(
maxWidth: 200.0,
maxHeight: 200.0,
),
child: Container(
color: Colors.purple,
child: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
// mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Container(
color: Colors.green,
// constraints: BoxConstraints(
// maxHeight: 200.0,
// ),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisSize: MainAxisSize.min, //有效,外层Colum高度为整个屏幕
children: <Widget>[
Container(
color: Colors.blue,
// constraints: BoxConstraints(maxHeight: 1300.0),
height: 500,
child: Column(
mainAxisSize: MainAxisSize.min,//无效,内层Colum高度为实际高度
children: <Widget>[
Text("hello world "),
Text("I am Jack "),
// Expanded(
// child: Container(
// color: const Color(0xff800000), // Red
// height: 120.0,
// ),
// ),
Flexible(
child: Container(
color: const Color(0xff8eeeee), // Red
height: 220.0,
),
),
],
),
),
// Flexible(
// child: Container(
// color: const Color(0xff00e0e0),
// width: 80.0,
// height: 60.0,
// ),
// ),
// Flexible(
// child: Container(
// color: Colors.red,
// child: Column(
// mainAxisSize: MainAxisSize.min,//无效,内层Colum高度为实际高度
// mainAxisAlignment: MainAxisAlignment.center,
// children: <Widget>[
// Text("hello world "),
// Text("I am Jack "),
// Expanded(
// // A flexible child that will grow to fit the viewport but
// // still be at least as big as necessary to fit its contents.
// child: Container(
// color: const Color(0xff000000),
// height: 120.0,
// ),
// ),
// ],
// ),
// ),
// )
],
),
),
),
// Flexible(
// child: Container(
// color: const Color(0xff008000),
// width: 60.0,
// ),
// ),
// Expanded(
// child: Container(
// color: Colors.black,
// ),
// )
],
),
),
);
}