天天看点

Flutter基础:布局出了问题,为什么我的Column用不好?

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

继续阅读