Flutter元件基礎
Flutter 元件基礎
當元件的狀態發生改變時,元件會重構自身的描述,並且Flutter框架會對比之前的描述,以確定地層渲染樹從當前狀態轉換到下一個狀態所需要的最小更改,最後再執行介面的重新整理。
Flutter中真正代表螢幕現實元素的類是Element。Widget只是描述Element的配置資料而已,並且一個Widget可以對應多個Element。如下圖所示;
StatelessWidget
表示沒有狀態的元件。如果想要建立一個無狀態的元件,只需要繼承 StatelessWidget 根元件,並且重寫 build() 方法即可。
由於沒有狀態,因此StatelessWidget只在初識話階段構建Widget時才會執行一次渲染,因此它無法基於任何時間或使用者操作重繪試圖。
class MyApp extends StatelessWidget{
@override
Widget build(BuildContext context) {
// TODO: implement build
throw UnimplementedError();
}
}
在該繼承和重寫的方法中,出現了一個build方法,有一個引數為context。context是當前Widget在Widget樹中執行相關操作的一個控制代碼。可以使用它向上遍歷Widget樹以及按照Widget型別查詢父級Widget。
StatefulWidget
表示有狀態的Widget。通過與State物件進行關聯來管理元件狀態樹,內部成員變數不需要使用final修飾符,當需要更新內部變數時,直接使用 setState()
如果需要建立一個有狀態的元件,需要繼承 StatefulWidget ,並且重寫 build() 。
class MyApp extends StatefulWidget{ @override State<StatefulWidget> createState() { // TODO: implement createState throw UnimplementedError(); } } class MyAppState extends State<MyApp>{ void method(){ setState(() { //進行狀態的變更 }); } @override Widget build(BuildContext context) { // TODO: implement build throw UnimplementedError(); } }
對比於StatelessWidget而言,StatefulWidget多了一個狀態。當內部東西需要變更時,通常是呼叫setState()方法,從而讓內部的狀態發生改變,從而讓Flutter進行重繪。在StatefulWidget中新引入了一個 State<*> 這個是狀態改變類。
MaterialApp
作為提供入口的Widget
序號 | 名稱 | 作用 |
---|---|---|
1 | title | String型別,Android裝置中APP上方顯示的標題,在IOS中不起作用。 |
2 | home | Widget型別,預設啟動後的第一個Flutter。 |
3 | routes | Map< String, WidgetBuilder >型別,頂級路由表。 |
4 | theme | 定義應用主題 |
5 | theme.primarySwatch | 應用的主題色 |
6 | theme.primaryColor | 單獨設定導航欄的背景顏色 |
AppBar
頂部導航欄元件,可以用來控制路由、標題和溢位下拉選單。
序號 | 名稱 | 解釋 |
---|---|---|
1 | leading | 標題左邊的圖案按鈕,預設是返回箭頭的形式 |
2 | title | 導航欄標題 |
3 | actions | 右邊的動作區域中可以放置多個元件,可以是圖示或者文字 |
4 | flexibleSpace | 位於標題下面的空白空間 |
5 | bottom | 位於導航欄地步的自定義元件 |
6 | elevation | 控制下方陰影欄的座標 |
7 | backgroundColor | 導航欄的顏色 |
8 | brightness | 導航欄材質的亮度 |
9 | textTheme | 文字主題設定 |
10 | primary | 導航欄是否顯示在工作列頂部 |
11 | centerTitle | 標題是否居中現實 |
12 | titleSpacing | 標題的間距 |
13 | toolbarOpacity | 導航欄透明度,從1到0,透明度從完全不透明到完全透明 |
AppBar如下圖所示
Scaffold
具有Material Design佈局風格的Widget,被設計為MaterialApp的頂級容器元件,可以自動填充可用的螢幕空間,佔據整個視窗或者裝置螢幕。
編號 | 名稱 | 說明 |
---|---|---|
1 | appBar | 用於設定頂部的狀態列,如果不設定,那麼不顯示 |
2 | body | Widget型別,現實Scaffold內容的主要容器 |
3 | bottomNavigationBar | 設定Scaffold的底部導航欄,items的數量 > 2 |
4 | drawer | 設定抽屜效果 |
5 | floatingActionButton | 設定右下角的安寧 |
對於Scaffold中,有一個示例程式碼如下:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('首頁'),
),
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
currentIndex: 1,
items: const [
BottomNavigationBarItem(
icon: Icon(Icons.account_balance),
title: Text('銀行')
),
BottomNavigationBarItem(
icon: Icon(Icons.contacts),
title: Text('聯絡人')
),
BottomNavigationBarItem(
icon: Icon(Icons.library_music),
title: Text('音樂')
)
],
),
body: const Center(
child: Text('聯絡人頁面'),
),
),
);
}
}
經過編譯,現實的結果如下:
文字元件
文字元件是Text元件,元件的基本屬性如下表
編號 | 屬性名稱 | 型別 | 說明 |
---|---|---|---|
1 | data | String | 顯示文字的內容 |
2 | style | TextStyle | 文字的樣式 |
3 | strutStyle | StrutStyle | 每行的最小行高 |
4 | textAlign | TextAlign | 文字的對齊方式 |
5 | textDirection | textDirection | 文字方向 |
6 | locale | Locale | 選擇使用者語言和格式設定的識別符號 |
7 | softWrap | bool | 是否支援換行 |
8 | overflow | TextOverflow | 文字的截斷方式 |
9 | textScaleFactor | double | 文字相對於預設字型大小的縮放因子 |
10 | maxLines | int | 文字顯示的最大行數 |
11 | semanticsLabel | String | 給文字新增一個語義標籤 |
按鈕元件
Material元件庫中有多個按鈕元件
- RaisedButton
- FlatButton
- OutlineButton
- IconButton
按鈕的樣例程式碼如下
import 'package:flutter/material.dart';
void main() => runApp(ButtonWidget());
class ButtonWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Button 元件'),),
body: Center(
child: Column(
children: <Widget>[
FlatButton(onPressed: () => print('FlatButton'), child: Text('Flat'),),
RaisedButton(onPressed: ()=>print('RaisedButton'),child: Text("RaisedButton"),),
FloatingActionButton(onPressed: ()=>print('FloatingActionButton'),child: const Text('FloatingActionButton'),),
OutlineButton(onPressed: ()=>print('OutlineButton') ,child: const Text("OutlineButton"),),
IconButton(onPressed: ()=>print("IconButton"), icon: const Icon(Icons.thumb_up))
],
),
),
),
);
}
}
在程式碼中,除了FloatingActionButton和IconButton沒有被廢棄以外,其他均被廢棄,不推薦使用。
編號 | 屬性名稱 | 型別 | 說明 |
---|---|---|---|
1 | textColor | Color | 按鈕的文字顏色 |
2 | disabledTextColor | Color | 按鈕禁用時的文字顏色 |
3 | color | Color | 按鈕的背景顏色 |
4 | highlightColor | Color | 按鈕按下時的背景顏色 |
5 | splashColor | Color | 單擊時產生的水波動畫中的水波顏色 |
6 | colorBrightness | Brightness | 按鈕的主題 |
7 | padding | EdgeInsetsGeometry | 按鈕填充距離 |
8 | shape | ShapeBorder | 按鈕的外形 |
9 | child | Widget | 按鈕的文字內容 |
10 | onPressed | VoidCallback | 按鈕點選回撥 |
圖片元件
圖片元件是用來載入和顯示圖片的元件。可以使用不同的方式進行載入不同形式的圖片。
- Image 通過ImageProvider來載入圖片
- Image.asset 用來載入本地的圖片
- Image.file 用來載入本地 .file 檔案型別的圖片
- Image.network 用來載入網路圖片
- Image.memory 用來載入記憶體快取圖片
編號 | 屬性名 | 型別 | 說明 |
---|---|---|---|
1 | scale | double | 圖片顯示的比例 |
2 | semanticsLabel | String | 給Image加上一個語義標籤 |
3 | width | double | 圖片的寬,如果為null,會以預設的形式顯示 |
4 | height | double | 圖片的高,如果為null,會以預設的形式顯示 |
5 | color | Color | 圖片的混合顏色 |
6 | fit | BoxFit | 圖片的填充模式 |
alignment | Alignment | 圖片的對齊方式 | |
repeat | ImageRepeat | 當圖片本身小雨顯示空間時,指定圖片的重複規則 | |
centerSlice | Rect | 在矩形範圍內的圖片會被當成.9格式的圖片 | |
matchTextDirection | Bool | 圖片的繪製方向,true表示從左往右,false表示從右往左 | |
gaplessPlayback | Bool | 當影象提供者發生更改時,是否保留原影象 | |
filterQuality | FilterQuality | 圖片的過濾質量 |
fit填充模式
- BoxFit.fill 全圖顯示,不夠的部分拉伸
- BoxFit.contain 全圖顯示,超過部分被裁減
- BoxFit.cover 預設顯示規則
- BoxFit.fitWidth 寬度上充滿空間,高度按比例縮放,超出部分被裁剪
- BoxFit.fitHeight 高度充滿空間,寬度按比例,超出部分裁剪
- BoxFit.scaleDown 與contain效果差不多,但是會縮小影象以確保影象位於顯示空間內
- BoxFit.none 沒有填充策略,按原大小顯示
Image元件圖片是有快取的,預設最大快取數量是1000,最大空間為100MB。
圖示元件
Icon元件是圖示元件,也可以使用IconButton。常用元件如下
- IconButton 可互動的Icon元件
- Icons 自帶的Icon元件集合
- IconTheme Icon元件主題
- ImageIcon 通過AssetImages或者圖片顯示Icon元件
Icon的基本的屬性如下
序號 | 屬性名稱 | 型別 | 說明 |
---|---|---|---|
1 | size | double | 圖示的大小 |
2 | color | Color | 圖示的顏色 |
3 | semanticsLabel | String | 給圖示新增一個語義標籤 |
4 | textDirection | TextDirection | 圖示的繪製方向 |
輸入框元件
輸入框元件TextField是一個文字輸入框元件。常見的屬性如下:
序號 | 屬性名稱 | 說明 |
---|---|---|
1 | controller | 輸入框控制器,可以獲取和設定輸入框的內容以及艦艇文字內容的改變,可自動建立 |
2 | focusNode | 控制TextField元件是否獲取輸入焦點,使用者和鍵盤互動的一種常見方式 |
3 | decoration | 用於控制TextField元件的外觀顯示 |
4 | textAlign | 輸入框內文字在水平方向的對齊方式 |
5 | textDirection | 輸入框內文字的方向 |
6 | keyboardType | 用於設定預設的鍵盤輸入型別 |
textInputAction | 回車鍵為動作按鈕圖示 | |
8 | style | 輸入框的樣式 |
9 | autofocus | 是否自動獲取焦點,預設false |
10 | obscureText | 是否隱藏正在編輯的文字內容 |
11 | maxLines | 輸入框文字的最大行數 |
12 | maxLength | 輸入框中允許的最大字元數,使用此屬性會在右下角顯示已輸入的字元數 |
13 | onChange | 輸入框內容改變時的回撥函式 |
14 | onEditingComplete | 輸入框輸入完成時觸發 |
15 | onSubmitted | 輸入框輸入完成時觸發,返回輸入內容 |
16 | inputFormatters | 指定輸入格式 |
17 | enabled | 是否禁用輸入框 |
18 | enableInteractiveSelection | 是否啟用互動式選擇,為true時表示長選文字,並且彈出cut、copy、paste選單 |
19 | keyboardAppearance | 設定鍵盤的亮度模式,IOS專用 |
20 | onTap | TextField元件的點選事件 |
21 | buildCounter | 自定義InputDecorator.counter小部件的回撥方式 |
表單元件
Form是一個包含表單元素的表單元件,可以用來對輸入的資訊進行校驗。表單的一些屬性如下
編號 | 屬性名稱 | 型別 | 說明 |
---|---|---|---|
1 | child | Widget | 表單的子元件 |
2 | autovalidate | bool | 是否自動驗證表單內容,預設false |
3 | onWillPop | WillPopCallback | 表單所在的路由是否可以直接返回 |
4 | onChanged | VoidCallback | 表單子元素髮生變化時觸發的回撥 |
import 'package:flutter/material.dart';
void main(List<String> args) {
runApp(FormWidget());
}
class FormWidget extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return FormWidgetState();
}
}
class FormWidgetState extends State<FormWidget> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
String? _userName;
String? _userPassword;
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "flutter demo",
theme: ThemeData(
primaryColor: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: Text("Form元件"),
),
body: Form(
key: _formKey,
child: Column(
children: [
TextFormField(
decoration: const InputDecoration(
hintText: "使用者名稱",
icon: Icon(Icons.person)
),
validator: (value) {
if (value?.length != null && value!.length <= 5) {
return "使用者名稱需要大於5個字元";
}
},
),
TextFormField(
decoration: const InputDecoration(
hintText: "密碼",
icon: Icon(Icons.lock)
),
obscureText: true,
validator: (value) {
if (value?.length != null && value!.length <= 8) {
return "密碼必須大於8字元";
}
},
),
RaisedButton(
onPressed: () {
if(_formKey.currentState?.validate()==true){
_formKey.currentState?.save();
}
},
padding: EdgeInsets.all(15.0),
child: Text("login"),
color: Theme
.of(context)
.primaryColor,
textColor: Colors.white,
),
],
),
),
),
);
}
}
根據上面的程式碼進行編譯執行後,能得到兩個簡單的輸入框以及一個按鈕,當用戶名或者密碼不符合預期時,便會提示錯誤的資訊。
容器元件
Container是Flutter提供的容器元件,可以包含一個子元件,自身具備alignment、margin、padding等基礎屬性。其包括的屬性如下:
序號 | 屬性名稱 | 型別 | 說明 |
---|---|---|---|
1 | key | Key | Widget的標識,用於查詢更新 |
2 | alignment | AlignmentGeometry | 容器內子元件的對齊方式 |
3 | padding | EdgeInsetsGeometry | 容器的內邊距 |
4 | color | Color | 容器的背景顏色 |
5 | decoration | Decoration | 容器的背景裝飾 |
6 | foregroundDecoration | Decoration | 容器的前景裝飾 |
7 | width | double | 容器的寬度 |
8 | height | double | 容器的高度 |
9 | constraints | BoxConstraints | 容器的約束條件 |
10 | margin | EdgeInsetsGeometry | 容器的外邊距 |
11 | transform | Matrix4 | 容器的變化矩陣 |
12 | child | Widget | 容器裡面的子元件 |
padding包含容器內部的邊距,margin是外部的邊距。點選padding中的區域會有事件響應,而margin的區域則不會。
盒約束模型
指元件可以按照指定限制條件來決定如何佈局自身位置。常見的元件包括
- ConstrainedBox
- SizedBox
- UnconstrainedBox
ConstrainedBox
常見的盒約束元件,用來對子元件新增額外的約束。
ConstrainedBox{
Key key,
@required this.constraints,
Widget child
}
SizedBox
用於給子元素指定固定的寬和高
SizedBox{
double width,
double height,
Widget child
}
SizedBox是ConstrainedBox的子類。
UnconstrainedBox
不會對子元件產生任何限制,允許子元件按照自己本身的大小進行繪製,比較少用到。
參考書籍 《Flutter跨平臺開發入門與實戰》
這是小睿的部落格,如果需要轉載,請標註出處啦~ヾ(≧▽≦*)o謝謝。