1. 程式人生 > IOS開發 >Flutter開發實戰初級(2)頁面佈局詳解

Flutter開發實戰初級(2)頁面佈局詳解

  • 初級基礎系列

Flutter開發實戰初級(1)ListView詳解

Flutter開發實戰初級(2)佈局詳解

  • 專案實戰系列

Flutter開發實戰 高仿微信(1)首頁

Flutter開發實戰 高仿微信(2)發現頁

Flutter開發實戰初級(2)頁面佈局詳解

本篇部落格Demo下載點選這裡:Flutter佈局Demo

1. Flutter佈局實戰講解

1.1 佈局座標

首先新建一個Flutter專案 我這裡命名為flutter_layoutdemo,

新建一個Flutter專案

接下來我們建立一個用來練習佈局的layout_demo.dart檔案,直接按快捷鍵“Command + N”

建立一個用來練習佈局的layout_demo.dart檔案

然後找到main.dart裡面的MyApp類,替換掉系統預設的程式碼,如下圖所示:

替換掉系統預設的程式碼

替換掉之後,我們直接按快捷鍵“Control+R” 編譯執行到模擬器上面,可以選擇安卓或者iOS模擬器,也可以選擇執行在真機上面,如下圖選擇你想執行的模擬器:

選擇你想執行的模擬器

這裡我選擇的是iphone 11 模擬器,執行結果如下:

iphone 11 模擬器,執行結果

接下來我們在layoutDemo類的build方法裡面加入一些小部件

class LayoutDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.red,child: Center
( child: Text('kongyulu'),),); } } 複製程式碼

"Control + R " 編譯執行

居中顯示

其實我們還可以通過alignment 屬性是佈局居中顯示,這個類似於IOS 的UILabel的對齊屬性。這樣我們可以修改程式碼如下:

class LayoutDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.red,alignment: Alignment
(0.0,0.0),child: Text('kongyulu2') ); } 複製程式碼

我們熱更新一下,可以看到效果如下:

alignment屬性居中顯示

下面我們簡單介紹一下aligment屬性: 實際上我們上面程式碼用的相對佈局,座標原點在中心,我們aligment屬性 Alignment(x,y)傳入x,y的座標,這裡傳入(0,0)標識在中心位置,如下圖所示:

alignment屬性座標詳解

如上圖所示,Alignment(-1,-1)標識在左上角,Alignment(1,1)在右下角,Alignment(-1,1)在左下角,Alignment(1,-1)在右上角,下面我們可以簡單驗證一下

如果我們把alignment屬性改為Alignment(1,0),效果如下:

把alignment屬性改為Alignment(1,0)
如果我們把alignment屬性改為Alignment(0,1),效果如下:
在這裡插入圖片描述

如果我們把alignment屬性改為Alignment(-1,-1),效果如下:

把alignment屬性改為Alignment(-1,-1)

由此我們可以知道(-1,-1)在左上角, (1,1)在右上角,

1.2 橫向佈局Row

接下來我們講解一下橫向佈局Row,我們修改一下程式碼,增加一個Row佈局,程式碼如下:

class LayoutDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.red,child: Row(
        children: <Widget>[
          Icon(Icons.add),Icon(Icons.access_alarm),Icon(Icons.account_balance_wallet),],)
    );
  }
}
複製程式碼

熱更新一下,效果如下:

橫向佈局Row

Row表示橫向佈局,裡面需要傳入一個Widget陣列,陣列裡面的Widget小部件都橫向排列。我們可以看到小部件預設有點小,我們來修改一下大小將size改為80

class LayoutDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.red,child: Row(
        children: <Widget>[
          Icon(Icons.add,size: 80,Icon(Icons.access_alarm,Icon(Icons.account_balance_wallet,)
    );
  }
}

複製程式碼

重新執行一下效果如下:

size改為80後的大小

如果我們想跟裡面的小部件新增背景顏色,我們只需要將這個小部件放到一個新的Container容器裡麵包裝一下,即可使用Container裡面的相關屬性,設定顏色等屬性。

我們再修改一下程式碼,給小部件新增背景顏色:

class LayoutDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.red,child: Row(
        children: <Widget>[
          Container(child:Icon(Icons.add,color: Colors.blue,Container(child:Icon(Icons.access_alarm,color: Colors.yellow,Container(child:Icon(Icons.account_balance_wallet,color: Colors.green,)
    );
  }
}
複製程式碼

重新執行一下效果如下:

給小部件新增背景顏色

1.3 縱向佈局Column

縱向佈局時垂直方向的佈局,更橫向佈局相對應。我們只需要將上面的橫向佈局程式碼的Row改為Column,如下:

class LayoutDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.red,child: Column(
        children: <Widget>[
          Container(child:Icon(Icons.add,)
    );
  }
}
複製程式碼

熱更新一下,我們來看一下效果:

縱向佈局

1.4 層級佈局Stack

我們再將上面的程式碼修改為Stack層級佈局看看什麼效果,修改程式碼如下:

class LayoutDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.red,child: Stack(
        children: <Widget>[
          Container(child:Icon(Icons.add,)
    );
  }
}
複製程式碼

我們快捷鍵“Command+||” 熱更新一下,執行效果如下:

層級佈局stack

本來是三個,我們只看到了最後一個小部件,說明另外兩個被遮擋了,我們來修改一下每個小部件的大小:

修改小部件大小後的stack佈局效果

由此我們可以知道 Row橫向佈局對應x軸,Column縱向佈局對應y軸,Stack層次佈局對應z軸,我們由x,y,z可以很容易佈局想要的效果。

1.5 主軸 mainAxisAlignment

我們的Row,Column都有兩個非常重要的屬性:主軸mainAxisAlignment 和 交叉軸

其中主軸需要傳入一個物件,我們檢視原始碼可以看到:

主軸和交叉軸定義

主軸屬性傳入一個MainAxisAlignment物件,我們可以看到它有下面結構屬性:

在這裡插入圖片描述

  • MainAxisAlignment.center: 表示沿著主軸方向居中顯示,如果Row橫向佈局,則是沿著x軸從左到右橫著居中排列顯示,如果是Column縱向佈局,則是沿著y軸從上往下,縱向居中顯示

如果Row橫向佈局,則是沿著x軸從左到右橫著居中排列顯示

如果是Column縱向佈局,則是沿著y軸從上往下,縱向居中顯示

  • MainAxisAlignment.end :

如果Row橫向佈局,則是沿著x軸從左到右橫著居中,靠右對齊排列顯示

如果Row橫向佈局,則是沿著x軸從左到右橫著居中,靠右對齊排列顯示

如果是Column縱向佈局,則是沿著y軸從上往下,縱向居中,並且靠底部對齊顯示

如果是Column縱向佈局,則是沿著y軸從上往下,縱向居中,並且靠底部對齊顯示

  • MainAxisAlignment.spaceAround: 就是將主軸方向剩下的空間平均分配給每個子控制元件。

如果Row橫向佈局,則水平方向剩下的空間平均分配在每個空間的周圍

水平方向剩下的空間平均分配在每個空間的周圍

如果是Column縱向佈局,則垂直方向剩下的空間平均分配在每個空間的周圍

垂直方向剩下的空間平均分配在每個空間的周圍
在這裡插入圖片描述

  • MainAxisAlignment.spaceBetween: 剩下的空間平均分配到每個小部件之間的間隔。
    在這裡插入圖片描述

在這裡插入圖片描述

  • MainAxisAlignment.spaceEvently: 剩下空間和小部件一起平均分配,是等間距的分配。

在這裡插入圖片描述
在這裡插入圖片描述

  • MainAxisAlignment.start : 表示主軸開始的方向, 也是預設值

如果是Row佈局,MainAxisAlignment.start 主軸效果如下:

表示主軸開始的方向, 也是預設值
如果是Column佈局,MainAxisAlignment.start 主軸效果如下:
如果是Column佈局,MainAxisAlignment.start主軸效果

1.6 交叉軸 CrossAxisAlignment

CrossAxisAlignment交叉軸擁有的屬性如下:

交叉軸

交叉軸預設的屬性是center 居中顯示

  • CrossAxisAlignment.baseline : 這個baseline屬性不能單獨使用,需要結合其他屬性配合使用,否則會報錯:
    需要結合其他屬性配合使用,否則會報錯
    我們修改一下程式碼,增加textBaseline: TextBaseline.alphabetic屬性,配合使用,因為baseline屬性需要針對文字才能體現效果,所以我們還需要在每個小部件裡面增加一個文字標籤

主軸為x軸,沿交叉軸y軸方向底部對齊

主軸為x軸,沿交叉軸y軸方向底部對齊
我們將標籤的背景大小設定一致更好對比:
將標籤的背景大小設定一致更好對比

縱向佈局時,baseline屬性使字型沿交叉軸左對齊

縱向佈局時,baseline屬性使字型沿交叉軸左對齊

我們再來看一下去掉baseline屬性的效果:

去掉baseline屬性的效果

  • CrossAxisAlignment.center :
    在這裡插入圖片描述

在這裡插入圖片描述

  • CrossAxisAlignment.end :
    在這裡插入圖片描述

在這裡插入圖片描述

  • CrossAxisAlignment.start :
    CrossAxisAlignment.start 作為x軸

Row佈局主軸是x軸,交叉軸是y軸

  • CrossAxisAlignment.stretch :
    在這裡插入圖片描述
    在這裡插入圖片描述

1.7 Expanded自動填充

Expanded 是一種比較靈活的佈局方案,它使得子部件隨之父控制元件的大小自動填充

我們接下來將上面的程式碼修改一下,將每個小部件放入Expanded佈局中,修改後程式碼如下:

class LayoutDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.white,child: Column(
        mainAxisAlignment: MainAxisAlignment.spaceAround,crossAxisAlignment: CrossAxisAlignment.baseline,textBaseline: TextBaseline.alphabetic,children: <Widget>[
          Expanded(child: Container(child:Text('孔雨露',style: TextStyle(fontSize: 15),height: 80,Expanded(child:Container(child:Text('努力',style: TextStyle(fontSize: 30),Expanded(child: Container(child:Text('堅持',style: TextStyle(fontSize: 60),)
    );
  }
}
複製程式碼

執行效果如下:

Expended自動填充佈局

我們將上面的程式碼的佈局Column改為Row橫向佈局,效果如下:

沿x軸自動填充

由此我們知道,如果我們設定了Expanded自動填充,假設我們使用Row橫向佈局我們不需要設定寬度(就算設定了寬度也不會生效,沒有意義),沿主軸x軸每個子部件自動填充拉伸滿,不會在主軸方向留下空隙,同理,如果是縱向佈局,則設定Expanded自動填充後,不需要設定高度(就算設定了高度也不會生效,沒有意義),沿主軸y會自動填充拉伸。

這個屬性對應我們文字很長時,會根據寬度自動換行,如下圖:

超過最大寬度後,自動換行

接下來,如果我們看一下如果上面的三個小部件,不是每個都使用expanded佈局呢,現在我們改一下程式碼,把中間的那個小部件改為不是expanded佈局。

有一個小部件不使用Expanded屬性

1.8 Alignment屬性

我們將上面的程式碼簡化一下,改為如下:

  Widget build(BuildContext context) {
    return Container(
      color: Colors.white,child: Container(child:
      Icon(Icons.add,size: 30,height: 40,color:Colors.blue,)
    );
  }
複製程式碼

執行效果如下:

Alignment屬性

我們一般用alignment根據比例來顯示位置,