Flutter開發實戰初級(2)頁面佈局詳解
- 初級基礎系列
- 專案實戰系列
Flutter開發實戰初級(2)頁面佈局詳解
本篇部落格Demo下載點選這裡:Flutter佈局Demo
1. Flutter佈局實戰講解
1.1 佈局座標
首先新建一個Flutter專案 我這裡命名為flutter_layoutdemo,
接下來我們建立一個用來練習佈局的layout_demo.dart檔案,直接按快捷鍵“Command + N”
然後找到main.dart裡面的MyApp類,替換掉系統預設的程式碼,如下圖所示:
替換掉之後,我們直接按快捷鍵“Control+R” 編譯執行到模擬器上面,可以選擇安卓或者iOS模擬器,也可以選擇執行在真機上面,如下圖選擇你想執行的模擬器:
這裡我選擇的是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')
);
}
複製程式碼
我們熱更新一下,可以看到效果如下:
下面我們簡單介紹一下aligment屬性: 實際上我們上面程式碼用的相對佈局,座標原點在中心,我們aligment屬性 Alignment(x,y)傳入x,y的座標,這裡傳入(0,0)標識在中心位置,如下圖所示:
如上圖所示,Alignment(-1,-1)標識在左上角,Alignment(1,1)在右下角,Alignment(-1,1)在左下角,Alignment(1,-1)在右上角,下面我們可以簡單驗證一下
如果我們把alignment屬性改為Alignment(1,0),效果如下:
如果我們把alignment屬性改為Alignment(0,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表示橫向佈局,裡面需要傳入一個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,)
);
}
}
複製程式碼
重新執行一下效果如下:
如果我們想跟裡面的小部件新增背景顏色,我們只需要將這個小部件放到一個新的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+||” 熱更新一下,執行效果如下:
本來是三個,我們只看到了最後一個小部件,說明另外兩個被遮擋了,我們來修改一下每個小部件的大小:
由此我們可以知道 Row橫向佈局對應x軸,Column縱向佈局對應y軸,Stack層次佈局對應z軸,我們由x,y,z可以很容易佈局想要的效果。
1.5 主軸 mainAxisAlignment
我們的Row,Column都有兩個非常重要的屬性:主軸mainAxisAlignment
和 交叉軸
其中主軸需要傳入一個物件,我們檢視原始碼可以看到:
主軸屬性傳入一個MainAxisAlignment
物件,我們可以看到它有下面結構屬性:
- MainAxisAlignment.center: 表示沿著主軸方向居中顯示,如果Row橫向佈局,則是沿著x軸從左到右橫著居中排列顯示,如果是Column縱向佈局,則是沿著y軸從上往下,縱向居中顯示
- MainAxisAlignment.end :
如果Row橫向佈局,則是沿著x軸從左到右橫著居中,靠右對齊排列顯示
如果是Column縱向佈局,則是沿著y軸從上往下,縱向居中,並且靠底部對齊顯示
- MainAxisAlignment.spaceAround: 就是將主軸方向剩下的空間平均分配給每個子控制元件。
如果Row橫向佈局,則水平方向剩下的空間平均分配在每個空間的周圍
如果是Column縱向佈局,則垂直方向剩下的空間平均分配在每個空間的周圍
- MainAxisAlignment.spaceBetween: 剩下的空間平均分配到每個小部件之間的間隔。
- MainAxisAlignment.spaceEvently: 剩下空間和小部件一起平均分配,是等間距的分配。
- MainAxisAlignment.start : 表示主軸開始的方向, 也是預設值
如果是Row佈局,MainAxisAlignment.start
主軸效果如下:
MainAxisAlignment.start
主軸效果如下:
1.6 交叉軸 CrossAxisAlignment
CrossAxisAlignment交叉軸擁有的屬性如下:
交叉軸預設的屬性是center
居中顯示
-
CrossAxisAlignment.baseline :
這個baseline屬性不能單獨使用,需要結合其他屬性配合使用,否則會報錯:
我們修改一下程式碼,增加
textBaseline: TextBaseline.alphabetic
屬性,配合使用,因為baseline屬性需要針對文字才能體現效果,所以我們還需要在每個小部件裡面增加一個文字標籤
主軸為x軸,沿交叉軸y軸方向底部對齊
我們將標籤的背景大小設定一致更好對比:縱向佈局時,baseline
屬性使字型沿交叉軸左對齊
我們再來看一下去掉baseline屬性的效果:
- CrossAxisAlignment.center :
- CrossAxisAlignment.end :
- CrossAxisAlignment.start :
- 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),)
);
}
}
複製程式碼
執行效果如下:
我們將上面的程式碼的佈局Column改為Row橫向佈局,效果如下:
由此我們知道,如果我們設定了Expanded
自動填充,假設我們使用Row橫向佈局我們不需要設定寬度(就算設定了寬度也不會生效,沒有意義),沿主軸x軸每個子部件自動填充拉伸滿,不會在主軸方向留下空隙,同理,如果是縱向佈局,則設定Expanded
自動填充後,不需要設定高度(就算設定了高度也不會生效,沒有意義),沿主軸y會自動填充拉伸。
這個屬性對應我們文字很長時,會根據寬度自動換行,如下圖:
接下來,如果我們看一下如果上面的三個小部件,不是每個都使用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根據比例來顯示位置,