天天看點

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,
            //   ),
            // )
          ],
        ),
      ),
    );
  }
           

繼續閱讀