[Flutter必備]-Flex布局完全解讀

0.前言

Flex布局是Flutter的五虎上將之一,虎父無犬子穆壕,其子Row和Column也能力非凡
你有沒有被mainAxisAlignment,crossAxisAlignment弄得暈頭轉(zhuǎn)向,本文將助你將他們納入麾下署照。
先看一下父子三人在Flutter布局體系中的位置:多子組件布局

image

1.Flex的屬性一覽
屬性名 類型 默認(rèn)值 簡介
direction Axis @required 軸向
mainAxisAlignment MainAxisAlignment start 主軸方向?qū)R方式
crossAxisAlignment CrossAxisAlignment center 交叉軸方向?qū)R方式
mainAxisSize MainAxisSize max 主軸尺寸
textDirection TextDirection null 文本方向
verticalDirection VerticalDirection down 豎直方向
textBaseline TextBaseline null 基線類型
children List<Widget> <Widget>[] 內(nèi)部孩子

2.軸向:direction:Axis
enum Axis {
  horizontal,//水平
  vertical,//豎直
}

也就是水平排放還是豎直排放臭脓,可以看出默認(rèn)情況下都是主軸頂頭,交叉軸居中
比如horizontal下主軸為水平軸酗钞,交叉軸則為豎直。也就是水平頂頭来累,豎直居中
這里使用MultiShower快速展示,更好的對比出不同之處砚作,MultiShower詳見

image
var direction =[Axis.horizontal,Axis.vertical];
var show = MultiShower(direction,(e){
  return Flex(
    direction: e,
    children: <Widget>[redBox,blueBox,yellowBox,greenBox],

  );
},color: Colors.black12,width: 300,height: 200);

var redBox= Container(
  color: Colors.red,
  height: 50,
  width: 50,
);

var blueBox= Container(
  color: Colors.blue,
  height: 30,
  width: 60,
);

var yellowBox= Container(
  color: Colors.yellow,
  height: 50,
  width: 100,
);

var greenBox= Container(
  color: Colors.green,
  height: 60,
  width: 60,
);

3.主軸方向:mainAxisAlignment:MainAxisAlignment

主軸方向的排布規(guī)則,這里以水平為例,主軸為水平方向嘹锁。豎直類比即可

enum MainAxisAlignment {
  start,//頂頭
  end,//接尾
  center,//居中
  spaceBetween,//頂頭接尾葫录,其他均分
  spaceAround,//中間的孩子均分,兩頭的孩子空一半
  spaceEvenly,//均勻平分
image
testMainAxisAlignment(){
  var redBox= Container(
    color: Colors.red,
    height: 50,
    width: 50,
  );

  var blueBox= Container(
    color: Colors.blue,
    height: 30,
    width: 60,
  );

  var yellowBox= Container(
    color: Colors.yellow,
    height: 10,
    width: 10,
  );

  var greenBox= Container(
    color: Colors.green,
    height: 50,
    width: 10,
  );

  var mainAxisAlignment =[
  MainAxisAlignment.start,MainAxisAlignment.center,
  MainAxisAlignment.end,MainAxisAlignment.spaceAround,
  MainAxisAlignment.spaceBetween,MainAxisAlignment.spaceEvenly];

  var show = MultiShower(mainAxisAlignment,(e){
    return Flex(
      direction: Axis.horizontal,
      mainAxisAlignment: e,
      children: <Widget>[redBox,blueBox,yellowBox,greenBox],

    );
  },color: Colors.black12,width: 200,height: 150);
  return show;
}

4.交叉軸方向:crossAxisAlignment:CrossAxisAlignment
enum CrossAxisAlignment {
  start,//頂頭
  end,//接尾
  center,//居中
  stretch,//伸展
  baseline,//基線
}

還是水平為例,交叉軸便是豎軸领猾,這里可以看出他們的布局行為
其中需要注意的是CrossAxisAlignment.baseline使用時(shí)必須有textBaseline
其中textBaseline確定對齊的是那種基線,分為alphabeticideographic

image
testCrossAxisAlignment(){
  var redBox= Container(
    color: Colors.red,
    height: 50,
    width: 50,
  );

  var blueBox= Container(
    color: Colors.blue,
    height: 30,
    width: 60,
  );

  var yellowBox= Container(
    color: Colors.yellow,
    height: 10,
    width: 10,
  );

  var greenBox= Container(
    color: Colors.green,
    height: 50,
    width: 10,
  );
  
  var crossAxisAlignment =[CrossAxisAlignment.start,CrossAxisAlignment.center,
    CrossAxisAlignment.end,CrossAxisAlignment.stretch,CrossAxisAlignment.baseline];

  var show = MultiShower(crossAxisAlignment,(e){
    return Flex(
      direction: Axis.horizontal,
      crossAxisAlignment: e,
      textBaseline: TextBaseline.alphabetic,//基線類型
      children: <Widget>[redBox,blueBox,yellowBox,greenBox],

    );
  },color: Colors.black12,width: 200,height: 140);

  return show;
}

5.主軸尺寸:mainAxisSize
enum MainAxisSize {
  min,
  max,
}

當(dāng)父容器的寬未約束,Flex默認(rèn)會(huì)將自身盡可能延伸米同,這便是MainAxisSize.max

image

此時(shí)改為MainAxisSize.min時(shí),它不會(huì)延伸自己的區(qū)域骇扇,自會(huì)包裹內(nèi)容

image
testMainAxisSize(){
  var redBox= Container(
    color: Colors.red,
    height: 50,
    width: 50,
  );

  var blueBox= Container(
    color: Colors.blue,
    height: 30,
    width: 60,
  );

  var yellowBox= Container(
    color: Colors.yellow,
    height: 10,
    width: 10,
  );

  var greenBox= Container(
    color: Colors.green,
    height: 50,
    width: 10,
  );

  return Center(child: Flex(
    direction: Axis.horizontal,
    mainAxisSize: MainAxisSize.max,
    children: <Widget>[redBox,blueBox,yellowBox,greenBox],

  ),);
}

6.文字方向:textDirection:TextDirection
enum TextDirection {
  ltr,//從左到右
  rtl,//從右到左
}

這個(gè)非常好理解,不多言了

image
testTextDirection(){
  var redBox= Container(
    color: Colors.red,
    height: 50,
    width: 50,
  );

  var blueBox= Container(
    color: Colors.blue,
    height: 30,
    width: 60,
  );

  var yellowBox= Container(
    color: Colors.yellow,
    height: 10,
    width: 10,
  );

  var greenBox= Container(
    color: Colors.green,
    height: 50,
    width: 10,
  );

  var textDirection =[TextDirection.ltr,TextDirection.rtl];
  var show = MultiShower(textDirection,(e){
    return Flex(
      direction: Axis.horizontal,
      textDirection: e,
      children: <Widget>[redBox,blueBox,yellowBox,greenBox],

    );
  },color: Colors.black12,width: 200,height: 140);
  return show;
}

7.豎直方向排序:verticalDirection:VerticalDirection
enum VerticalDirection{
    up,
    down,
}
image
testVerticalDirection(){
  var redBox= Container(
    color: Colors.red,
    height: 50,
    width: 50,
  );

  var blueBox= Container(
    color: Colors.blue,
    height: 30,
    width: 60,
  );

  var yellowBox= Container(
    color: Colors.yellow,
    height: 10,
    width: 10,
  );

  var greenBox= Container(
    color: Colors.green,
    height: 50,
    width: 10,
  );

  var verticalDirection =[VerticalDirection.up,VerticalDirection.down];

  var show = MultiShower(verticalDirection,(e){
    return Flex(
      direction: Axis.vertical,
      verticalDirection: e
      children: <Widget>[redBox,blueBox,yellowBox,greenBox],

    );
  },color: Colors.black12,width: 200,height: 140);

  return show;
}

8.基線對齊方式:textBaseline:TextBaseline
enum TextBaseline {
  alphabetic,
  ideographic,
}
image
testTextBaseline(){
  var redBox= Text(
    "張風(fēng)捷特烈",style: TextStyle(fontSize: 20,backgroundColor: Colors.red),
  );

  var blueBox= Text(
    "toly",style: TextStyle(fontSize: 50,backgroundColor: Colors.blue),
  );

  var yellowBox=  Text(
    "1994",style: TextStyle(fontSize: 30,backgroundColor: Colors.green),
  );

  var textBaseline =[TextBaseline.alphabetic,TextBaseline.ideographic];

  var show = MultiShower(textBaseline,(e){
    return Flex(
      direction: Axis.horizontal,
      crossAxisAlignment: CrossAxisAlignment.baseline,
      textBaseline: e,
      children: <Widget>[redBox,blueBox,yellowBox],
    );
  },color: Colors.black12,width: 300,height: 140);

  return show;
}

至此面粮,F(xiàn)lutter中的Flex布局就已經(jīng)完全解讀完了少孝。
其中Flutter的孩子Row是direction: Axis.horizontal,Column是direction: Axis.vertical,
其他的屬性都是類似的,相當(dāng)于Flex的簡化版熬苍,所以Flex在手韭山,天下我有。


Expanded與Flex的搭配--- [更新于2019.1.22]

還要一點(diǎn)是關(guān)于Expanded冷溃,也比較保用钱磅,它能與Flex布局結(jié)合,變更孩子尺寸

c1:綠色  c2:紅色  c3:黃色
1).Expanded--c2:c1和c3將不變似枕,c2延伸自己占滿剩余部分
2).同時(shí)Expanded--c2和c3盖淡,最終c2和c3的長度是一樣的
3).同時(shí)Expanded--c1,c2和c3凿歼,最終c1,c2褪迟,c3長度都是一樣的
expaned.png

9.用Flex布局寫個(gè)小例子

光說不練假把式,光練不說空把式,下面就用一個(gè)布局來實(shí)際看一下Flex的強(qiáng)大

image
  • 首先簡單的分析一下
image
1.由上中下三行,可以用Column
2.第一行由圖標(biāo)答憔,文字和文字組成味赃,其中兩頭分處左右,可以用Expanded處理  
3.中間比較復(fù)雜由一個(gè)Row中包含兩部分虐拓,左邊是一個(gè)兩行Column的內(nèi)容,右邊是文字  
4.底部是一個(gè)Row,主軸對齊是start
  • 布局代碼
showItem() {
  var infoStyle = TextStyle(color: Color(0xff999999), fontSize: 13);
  var littleStyle = TextStyle(color: Colors.black, fontSize: 16);

  var top = Row(//頂部,通過Flex布局的Row進(jìn)行橫向排列,Expanded中間
    children: <Widget>[
      Image.asset("images/icon_head.png", width: 20, height: 20),
      Expanded(
        child: Padding(
          child: Text("張風(fēng)捷特烈"),
          padding: EdgeInsets.only(left: 4),
        ),
      ),
      Text(
        "Flutter/Dart",
        style: infoStyle,
      )
    ],
  );

  var content = Column(//中間文字內(nèi)容,交叉軸為start
    mainAxisSize: MainAxisSize.min,
    crossAxisAlignment: CrossAxisAlignment.start,
    children: <Widget>[
      Text(
        "[Flutter必備]-Flex布局完全解讀",
        style: littleStyle,
        maxLines: 2,
        overflow: TextOverflow.ellipsis,
      ),
      Padding(
        child: Text("也就是水平排放還是豎直排放心俗,可以看出默認(rèn)情況下都是主軸頂頭,"
            "交叉軸居中比如horizontal下主軸為水平軸,交叉軸則為豎直蓉驹。也就是水平頂頭城榛,豎直居中"
            "這里使用MultiShower快速展示,更好的對比出不同之處",
            style: infoStyle, maxLines: 2, overflow: TextOverflow.ellipsis),
        padding: EdgeInsets.only(top: 5),
      ),
    ],
  );

  var center = Row(//中間的部分
    children: <Widget>[
      Expanded(
          child: Padding(
        child: content,
        padding: EdgeInsets.all(5),
      )),
      ClipRRect(
        borderRadius: BorderRadius.all(Radius.circular(5)),
        child: Image.asset("images/wy_300x200.jpg",
          width: 80, height: 80, fit: BoxFit.cover),)
    ],
  );

  var end = Row(//底部
    children: <Widget>[
      Icon(
        Icons.grade,
        color: Colors.green,
        size: 20,
      ),
      Text(
        "1000W",
        style: infoStyle,
      ),
      Padding(child:Icon(Icons.tag_faces, color: Colors.lightBlueAccent, size: 20),
          padding: EdgeInsets.symmetric(horizontal: 5),),
      Text("2000W", style: infoStyle),
    ],
  );

  var result = Card(//總體拼合
      child: Container(
          height: 160,
          color: Colors.white,
          padding: EdgeInsets.all(10),
          child: Column(children: <Widget>[top, Expanded(child: center), end])));
  return result;
}

結(jié)語

本文到此接近尾聲了,如果想快速嘗鮮Flutter态兴,《Flutter七日》會(huì)是你的必備佳品;如果想細(xì)細(xì)探究它,那就跟隨我的腳步狠持,完成一次Flutter之旅。
另外本人有一個(gè)Flutter微信交流群瞻润,歡迎小伙伴加入喘垂,共同探討Flutter的問題,本人微信號:zdl1994328绍撞,期待與你的交流與切磋正勒。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市楚午,隨后出現(xiàn)的幾起案子昭齐,更是在濱河造成了極大的恐慌,老刑警劉巖矾柜,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件阱驾,死亡現(xiàn)場離奇詭異就谜,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)里覆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進(jìn)店門丧荐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人喧枷,你說我怎么就攤上這事虹统。” “怎么了隧甚?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵车荔,是天一觀的道長。 經(jīng)常有香客問我戚扳,道長忧便,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任帽借,我火速辦了婚禮珠增,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘砍艾。我一直安慰自己蒂教,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布脆荷。 她就那樣靜靜地躺著凝垛,像睡著了一般。 火紅的嫁衣襯著肌膚如雪简烘。 梳的紋絲不亂的頭發(fā)上苔严,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天,我揣著相機(jī)與錄音孤澎,去河邊找鬼。 笑死欠窒,一個(gè)胖子當(dāng)著我的面吹牛覆旭,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播岖妄,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼型将,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了荐虐?” 一聲冷哼從身側(cè)響起七兜,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎福扬,沒想到半個(gè)月后腕铸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體惜犀,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年狠裹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了虽界。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,981評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡涛菠,死狀恐怖莉御,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情俗冻,我是刑警寧澤礁叔,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站迄薄,受9級特大地震影響琅关,放射性物質(zhì)發(fā)生泄漏犀填。R本人自食惡果不足惜趁桃,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望笋颤。 院中可真熱鬧勤篮,春花似錦都毒、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至金抡,卻和暖如春瀑焦,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背梗肝。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工榛瓮, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人巫击。 一個(gè)月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓禀晓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親坝锰。 傳聞我的和親對象是個(gè)殘疾皇子粹懒,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評論 2 355

推薦閱讀更多精彩內(nèi)容