Flutter踩坑:ListView布局报错,RenderFlex children have non-zero flex but incoming height constraints are...

完整报错信息:

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"),
                        )
                      ],
                    ),
                  ),
                ],
              ),
            )
          ],
        ))

 

效果:

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值