滿懷信心使用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,
// ),
// )
],
),
),
);
}