包含 Flutter 常用的組件、布局、方法等。初學者的完整快速參考
$ sudo softwareupdate --install-rosetta --agree-to-license
在 上,還需要安裝 環境因為 一些輔助工具 仍然需要,通過手動運行上面的命令來安裝
安裝包來獲取最新的 stable Flutter SDK:
Intel
Apple 芯片
想要獲取到其他版本的安裝包,請參閱 頁面
將文件解壓到目標路徑, 比如:
$ cd ~/development
$ unzip ~/Downloads/flutter_macos_3.3.8-stable.zip
配置 flutter
的 PATH 環境變量:
$ export PATH="$PATH:`pwd`/flutter/bin"
運行 flutter doctor
命令
flutter
目錄整個放在你想放置 Flutter SDK
的路徑中(例如 C:\src\flutter
)path
環境變量,在開始菜單的搜索功能鍵入「env」
,然后選擇 編輯系統環境變量
。在 用戶變量
一欄中,檢查是否有 Path
這個條目:
;
分隔已有的內容,加入 flutter\bin
目錄的完整路徑。flutter\bin
所在的完整路徑作為新變量的值如果你不想安裝指定版本的安裝包。可以忽略步驟 1
和 2
。從 GitHub
上的 Flutter repo
獲取源代碼,并根據需要,切換到指定的分支或標簽
C:\src>git clone //github.com/flutter/flutter.git -b stable
Text("Hello world",
textAlign: TextAlign.left,
);
Text("Hello world! I'm Jack. "*4,
maxLines: 1,
overflow: TextOverflow.ellipsis,
);
Text("Hello world",
textScaleFactor: 1.5,
);
Text("Hello world",
style: TextStyle(
color: Colors.blue,
fontSize: 18.0,
height: 1.2,
fontFamily: "Courier",
background: Paint()..color=Colors.yellow,
decoration:TextDecoration.underline,
decorationStyle: TextDecorationStyle.dashed
),
);
Text.rich(TextSpan(
children: [
TextSpan(
text: "Home: "
),
TextSpan(
text: "//flutter.dev",
style: TextStyle(
color: Colors.blue
),
recognizer: _tapRecognizer
),
]
))
DefaultTextStyle(
// 1.設置文本默認樣式
style: TextStyle(
color:Colors.red,
fontSize: 20.0,
),
textAlign: TextAlign.start,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text("hello world"),
Text("I am Jack"),
Text("I am Jack",
style: TextStyle(
inherit: false, //2.不繼承默認樣式
color: Colors.grey
),
),
],
),
);
在 asset 中聲明,要先在 pubspec.yaml
中聲明它
flutter:
fonts:
- family: Raleway
fonts:
- asset: assets/fonts/Raleway-Regular.ttf
- asset: assets/fonts/Raleway-Medium.ttf
weight: 500
- asset: assets/fonts/Raleway-SemiBold.ttf
weight: 600
- family: AbrilFatface
fonts:
- asset: assets/fonts/abrilfatface/AbrilFatface-Regular.ttf
將字體文件復制到在 pubspec.yaml
中指定的位置
使用字體
// 聲明文本樣式
const textStyle = const TextStyle(
fontFamily: 'Raleway',
);
// 使用文本樣式
var buttonText = const Text(
"Use the font for this text",
style: textStyle,
);
ElevatedButton(
child: Text("normal"),
onPressed: () {},
);
TextButton(
child: Text("normal"),
onPressed: () {},
)
OutlineButton(
child: Text("normal"),
onPressed: () {},
)
IconButton(
icon: Icon(Icons.thumb_up),
onPressed: () {},
)
ElevatedButton.icon(
icon: Icon(Icons.send),
label: Text("發送"),
onPressed: _onPressed,
),
OutlineButton.icon(
icon: Icon(Icons.add),
label: Text("添加"),
onPressed: _onPressed,
),
TextButton.icon(
icon: Icon(Icons.info),
label: Text("詳情"),
onPressed: _onPressed,
),
在工程根目錄下創建一個images目錄
,并將圖片 aaa.png
拷貝到該目錄。
在 pubspec.yaml
中的 flutter
部分添加如下內容:
assets:
- images/aaa.png
注意: 由于 yaml 文件對縮進嚴格,所以必須嚴格按照每一層兩個空格的方式進行縮進,此處 assets 前面應有兩個空格。
加載該圖片
Image(
image: AssetImage("images/aaa.png"),
width: 100.0
);
Image 也提供了一個快捷的構造函數 Image.asset
用于從 asset
中加載、顯示圖片:
Image.asset("images/aaa.png",
width: 100.0,
)
Image(
image: NetworkImage(
"//avatars2.githubusercontent.com/u/20411648?s=460&v=4"),
width: 100.0,
)
Image 也提供了一個快捷的構造函數 Image.network
用于從網絡加載、顯示圖片:
Image.network(
"//avatars2.githubusercontent.com/u/20411648?s=460&v=4",
width: 100.0,
)
const Image({
...
this.width, // 圖片的寬
this.height, // 圖片高度
this.color, // 圖片的混合色值
this.colorBlendMode, // 混合模式
this.fit,// 縮放模式
// 對齊方式
this.alignment = Alignment.center,
// 重復方式
this.repeat = ImageRepeat.noRepeat,
...
})
Switch(
value: true,//當前狀態
onChanged:(value){
// 重新構建頁面
},
),
Checkbox(
value: true,
// 選中時的顏色
activeColor: Colors.red,
onChanged:(value){
// ...
},
)
TextField(
autofocus: true,
onChanged: (v) {
print("onChange: $v");
}
)
模糊進度條(會執行一個動畫)
LinearProgressIndicator(
backgroundColor: Colors.grey[200],
valueColor: AlwaysStoppedAnimation(Colors.blue),
),
進度條顯示 50%
LinearProgressIndicator(
backgroundColor: Colors.grey[200],
valueColor: AlwaysStoppedAnimation(Colors.blue),
value: .5,
)
模糊進度條(會執行一個旋轉動畫)
CircularProgressIndicator(
backgroundColor: Colors.grey[200],
valueColor: AlwaysStoppedAnimation(Colors.blue),
),
進度條顯示 50%
,會顯示一個半圓
CircularProgressIndicator(
backgroundColor: Colors.grey[200],
valueColor: AlwaysStoppedAnimation(Colors.blue),
value: .5,
),
線性進度條高度指定為 3
SizedBox(
height: 3,
child: LinearProgressIndicator(
backgroundColor: Colors.grey[200],
valueColor: AlwaysStoppedAnimation(Colors.blue),
value: .5,
),
),
圓形進度條直徑指定為 100
SizedBox(
height: 100,
width: 100,
child: CircularProgressIndicator(
backgroundColor: Colors.grey[200],
valueColor: AlwaysStoppedAnimation(Colors.blue),
value: .7,
),
),
在實際開發中,Container常常用于對一個組件進行包裝修飾。
Container(
width: 100,
height: 100,
color: Colors.blue,
alignment: Alignment.center,
child: Text('Hello world'),
),
將 Contianer
大小固定為 100 * 100
, 背景色為藍色。把 Text
包裹在 Container
中,并將其居中
列布局(Column),可以將多個子組件沿著垂直的方向擺放(豎的擺放)
// 將container 和 button 擺放到同一列。
Column(
children: [
Container(
width: 100,
height: 100,
color: Colors.blue,
alignment: Alignment.center,
child: Text('Hello world'),
),
ElevatedButton(
onPressed: () {},
child: Text('Button'),
),
],
),
行布局(Row),可以將多個組件沿水平的方向擺放。
Row(
children: [
ElevatedButton(
onPressed: () {},
child: const Text('1'),
),
ElevatedButton(
onPressed: () {},
child: const Text('2'),
),
ElevatedButton(
onPressed: () {},
child: const Text('3'),
),
],
),
在同一行擺放 3 個 Button
將子組件從左到右依次排列,當空間不足時自動換行。
Wrap(
children: [
FlutterLogo(),
FlutterLogo(),
FlutterLogo(),
FlutterLogo(),
FlutterLogo(),
FlutterLogo(),
],
),
顯示多個 Flutter
的 logo
并自動換行
Stack 可以將一多個子組件疊在一起顯示。堆疊順序按照children屬性中的列表依次堆疊擺放,默認將子控件沿左上角對齊。
需要控制子控件位置可以嵌套Positoned
控件。
Stack(
children: [
Container(
height: 300,
width: 300,
color: Colors.blue,
),
Container(
height: 200,
width: 200,
color: Colors.black,
),
Container(
height: 100,
width: 100,
color: Colors.yellow,
),
],
),
依次堆疊 300*300
的藍色色塊、200*200
的黑色色塊、100*100
的黃色色塊
若需要控制Stack中子控件的位置,則可以嵌套改控件。
Stack(
children: [
// 默認擺放在左上位置
Container(
height: 300,
width: 300,
color: Colors.blue,
),
// 距離左邊40個、距離上面40個邏輯像素的位置
Positioned(
left: 40,
top: 40,
child: Container(
height: 200,
width: 200,
color: Colors.black,
),
),
// 距離左邊80個、距離上面80個邏輯像素的位置
Positioned(
left: 80,
top: 80,
child: Container(
height: 100,
width: 100,
color: Colors.yellow,
),
),
],
),
Align組件用于決定子組件對齊方式
// 使用Align將Button 居中在Container中
Container(
width: 100,
height: 100,
color: Colors.green,
child: Align(
alignment: Alignment.center,
child: ElevatedButton(
onPressed: () {},
child: Text('Center'),
),
),
),
Center 組件實際上繼承于Align。用于專門劇中。
//與 Align中代碼效果一致
Container(
width: 100,
height: 100,
color: Colors.green,
child: Center(
child: ElevatedButton(
onPressed: () {},
child: Text('Center'),
),
),
),
Flex 的用法與 Row
或 Column
類似,但只需要額外傳入 direction
參數
Row
和 Column
組件都繼承 Flex
組件direction
為 Axis.horizontal
表示水平方向(Row
),為 Axis.vertical
則為垂直方向(Column
)垂直方向依次擺放3個flutter logo
Flex(
direction: Axis.vertiacl,
children;[
Fluterlogo(),
Fluterlogo(),
Fluterlogo(),
],
),
水平方向依次擺放 3 個 flutter logo
Flex(
dirction: Axis.horizontal,
children: [
Flutterlogo(),
Flutterlogo(),
Flutterlogo(),
],
),
Expanded 用于擴張一個子組件。可以通過 flex
屬性,用于表示該組件相對其他彈性組件放大的倍數(可以理解為一個權重)。
// Container 會占滿剩余的全部空用空間
Row(
children: [
FlutterLogo(),
Expanded(
child: Container(
child: FlutterLogo(),
color: Colors.green,
),
),
FlutterLogo(),
],
),
// 按照1:2 的比例分配一整行的空間
Row(
children: [
Expanded(
flex: 1,
child: Container(
child: FlutterLogo(),
color: Colors.green,
),
),
Expanded(
flex: 2,
child: Container(
child: FlutterLogo(),
color: Colors.blue,
),
),
],
),
Flexible
是 Expanded
組件的父類。
與 Expanded
不同的是,Flexible
可以通過 fit
屬性設置子控件是否必須占滿 Flexibal
擴展的空間。而 Expaned
默認子控件必須占滿
// 如果將fit設置為tight,
// 則綠色Container 和藍色Container大小一樣。
// 如果將fit設置為loose,
// 則兩個Flexible擴展的空間大小是一樣的,
// 但綠色Container并不會填充整個擴展的空間。
Row(
children: [
Flexible(
flex: 2,
// fit: FlexFit.tight,
child: Container(
child: FlutterLogo(),
color: Colors.green,
),
),
Expanded(
flex: 2,
child: Container(
child: FlutterLogo(),
color: Colors.blue,
),
),
],
),
將 Flexible
的 fit
屬性設置為 tingt
,就等價于使用 Expanded
Spacer 用于在布局中留白
Row(
children: [
Text('Item'),
Spacer(),
FlutterLogo(),
],
),
例如,需要文本和圖標位于一個行的兩端,而中間留白時。就可以使用 Spacer
ListView
是一個支持滾動的列表組件。該組件默認支持上下滑動。
ListView
的默認構造函數,會立即初始化children
中的所有子widget
,無法動態加載。
ListView(
children: [
Text('1'),
Text('2'),
Text('3'),
Text('4'),
],
),
需要動態加載,則可以使用 ListView.builder()
命名構函數。
// 動態生成4個Text
ListView.builder(
itemBuilder: (BuildContext context, int index) {
return Text('$index');
},
itemCount: 4,
),
需要在對ListView
中的Item
添加分割線,則可以借助ListView.separated()
。
// separatorBuilder 函數用于在元素之間插入分割線。
// 也可以返回其他widget。該widget會被插入各個元素之間。
ListView.separated(
itemBuilder: (BuildContext context, int index) {
return Text('$index');
},
itemCount: 4,
separatorBuilder: (BuildContext context, int index) {
// 使用Divider widget 畫一條粗為5,顏色為紅色的線
return const Divider(
height: 5,
thickness: 5,
color: Colors.red,
);
},
),
GridView
可將元素顯示為二維網格狀的列表組件,并支持主軸方向滾動。
使用GridView() 構造函數,需要傳入gridDelegate和children。Flutter中已經提供了兩種實現方式,分別是:
SliverGridDelegateWithFixedCrossAxisCount()
用于交叉軸方向固定數。SliverGridDelegateWithMaxCrossAxisExtent()
用于交叉軸方向限制最大長度。// 使用SliverGridDelegateWithFixedCrossAxisCount
GridView(
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 4),
children: List.generate(
8,
(index) => Container(
color: Colors.red[index % 8 * 100],
child: Text("index $index"),
)),
),
// 使用SliverGridDelegateWithMaxCrossAxisExtent
GridView(
gridDelegate:
SliverGridDelegateWithMaxCrossAxisExtent(maxCrossAxisExtent: 200),
children: List.generate(
8,
(index) => Container(
color: Colors.red[index % 8 * 100],
child: Text("index $index"),
),
),
),
GridView.builder()
命名構造可以實現元素的動態加載,與ListView.builder()
類似
GridView.builder(
itemCount: 8,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4),
itemBuilder: (context, index) => Container(
color: Colors.red[index % 8 * 100],
child: Text("index $index"),
),
),
Gridview.count()
一個簡單的構造函數,只需要傳入crossAxisCount
(交叉軸元素的個數)和children
即可。
GridView.count(
crossAxisCount: 4, // 每行固定為4個
children: List.generate(
8,
(index) => Container(
color: Colors.red[index % 8 * 100],
child: Text("index $index"),
)),
),
GridView.extent()
用于設定每個元素在交叉軸方向的最大尺寸。當程序運行在較大屏幕時通常能看到更多的元素,而不是少量元素的放大版。通過傳入maxCrossAxisExtent
,Gridview
會根據屏幕尺寸自動選擇合適的行數量。
GridView.extent(
maxCrossAxisExtent: 200,
children: List.generate(
8,
(index) => Container(
color: Colors.red[index % 8 * 100],
child: Text("index $index"),
)),
),
GridView.count()
和GridView.extent()`可以看作GridView的語法糖。
使用PageView
可以實現整屏頁面滾動,默認為水平方向翻頁。與ListView
類似。
pageSnapping
參數可以設置滑動時Page
停留在任意位置。scrollDirection
參數設置滾動方向(默認為水平方向)。PageView(
pageSnapping: false, // 取消頁面固定
scrollDirection: Axis.vertical, // 設置為垂直方向滾動
children: [
for (int i = 0; i < 4; i++)
Container(
color: Colors.red[i % 4 * 100],
)
],
),
使用PageView.builder()
命名構造,可以動態加載頁面。與ListView.builder()
類似。
PageView.builder(
pageSnapping: false,
scrollDirection: Axis.vertical,
itemBuilder: (BuildContext context, int index) => Container(
color: Colors.red[index % 4 * 100],
),
),