1. 程式人生 > 其它 >Flutter元件基礎

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()

即可。如果Flutter監聽到狀態樹發生變化,那麼會觸發檢視重繪。

如果需要建立一個有狀態的元件,需要繼承 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謝謝。