完整报错信息:
RenderFlex children have non-zero flex but incoming height constraints are unbounded.
When a column is in a parent that does not provide a finite height constraint, for example if it is in a vertical scrollable, it will try to shrink-wrap its children along the vertical axis. Setting a flex on a child (e.g. using Expanded) indicates that the child is to expand to fill the remaining space in the vertical direction.
These two directives are mutually exclusive. If a parent is to shrink-wrap its child, the child cannot simultaneously expand to fit its parent.
如图,想要实现的效果是,左侧标题正常居中,但文字居底部显示
那么看到这个布局最容易想到的办法是,因为左侧竖直排列的两个控件,父控件是Column,那么我们可以给标题控件使用Expanded来包装,Expanded的作用是填充剩余空间,和安卓的layout_weight含义差不多。然后时间就可以自然的被挤到底部。
但是实际上按这个思路实现的话,却报出了这个异常。
flutter的文章较少,网上不容易找到答案,在尝试了多遍,使用伪代码复现问题:
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Flexible(
child:ListView(
shrinkWrap: true,
children: <Widget>[
Row(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Expanded(
child: Column(
children: <Widget>[
// Container(color: Colors.blue,child: Text("bbb")),
Expanded(child: Container(color: Colors.blue,child: Text("bbb"))),
Container(color: Colors.green,child: Text("ccc")),
],
)),
Container(color: Colors.red,
child: Text("aaa"),)
],
) ,
],) ,
)
],
)
测试多遍之后,发现了问题原因:
在Flutter的ListView的子View中,你可以在Row中使用Expanded填充水平方向的剩余空间,而无法在Column中使用Expanded填充垂直方向的剩余空间。
原因是ListView垂直方向的计算是包裹子View的,也就是说子View必须有一个明确的高度,或者尽可能小的高度,而不能是无限高。
Row是横向排列,在Row中使用Expanded是填充水平方向的剩余空间,这和ListView的这一特性没有冲突,可以使用。
而Column是竖直排列,在Column中使用Expanded是填充竖直方向的剩余空间,这将和ListView的这一特性发生冲突,因为ListView将无法计算自己的子View的高度。
这么解释看起来似乎也蛮合理,但是我们的子View并不是没有一个明确高度呀,他的右侧图片部分明显比左侧文案部分要高, ListView在绘制这个子View的时候,智能一点,直接使用右侧图片的高度,作为子view的整体高度不就ok了吗?
安卓里面就是系统这样智能处理掉的,而在Flutter中却报错。
好吧,那我们只能使用Flutter的办法去解决这个问题:
IntrinsicHeight可以根据子控件的高度,智能调整自身高度
把这个控件加在itemVIew的最外层,把Row给包括起来。
IntrinsicHeight可以根据子控件(左侧文案和右侧图片),智能选择一个合适的高度调整自身,使得ListView的子View的高度是确切的,这样ListView便不会因为子View想要无限高,而自己又要包括子View而报错了。
最终解决的代码如下:
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Flexible(
child: ListView(
shrinkWrap: true,
children: <Widget>[
IntrinsicHeight(
child: Row(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Expanded(
child: Column(
children: <Widget>[
// Container(color: Colors.blue,child: Text("bbb")),
Expanded(
child: Container(
color: Colors.blue, child: Text("bbb"))),
Container(color: Colors.green, child: Text("ccc")),
],
)),
Container(
color: Colors.red,
child: Text("aaa"),
)
],
),
),
],
),
)
],
))
效果: