- 原文博客地址: Flutter之基礎Widget
- Flutter和Dart系列文章
- 項目GitHub地址
-
Flutter
作為一種全新的響應式,跨平臺,高性能, 完全免費、開源的移動開發框架 -
Widget
是Flutter
開發中的主要組成部分, 是Flutter
的基礎,Flutter
的核心設計思想便是: 一切皆Widget
-
Flutter
中的widget
的概念更廣泛,它不僅可以表示UI
元素,也可以表示一些功能性的組件如:用于手勢檢測的GestureDetector
widget
、用于應用主題數據傳遞的Theme
等等
Widget與Element
-
Widget
實際上就是Element
的配置數據,Widget
的功能是描述一個UI元素的一個配置數據, 而真正的UI渲染是由Element
構成 - 由于
Element
是通過Widget
生成,所以它們之間有對應關系,所以在大多數場景,我們可以寬泛地認為Widget
就是指UI控件或UI渲染 - 一個
Widget
對象可以對應多個Element
對象。這很好理解,根據同一份配置(Widget
),可以創建多個實例(Element
)
Widget
類的聲明
@immutable
abstract class Widget extends DiagnosticableTree {
/// Initializes [key] for subclasses.
const Widget({ this.key });
/// See also the discussions at [Key] and [GlobalKey].
final Key key;
/// multiple times.
@protected
Element createElement();
/// A short, textual description of this widget.
@override
String toStringShort() {
return key == null ? '$runtimeType' : '$runtimeType-$key';
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.defaultDiagnosticsTreeStyle = DiagnosticsTreeStyle.dense;
}
static bool canUpdate(Widget oldWidget, Widget newWidget) {
return oldWidget.runtimeType == newWidget.runtimeType
&& oldWidget.key == newWidget.key;
}
}
-
Widget
類繼承自DiagnosticableTree
,主要作用是提供調試信息。 -
Key
: 這個key
屬性類似于React/Vue
中的key
,主要的作用是決定是否在下一次build
時復用舊的widget
,決定的條件在canUpdate()
方法中 -
createElement()
:正如前文所述一個Widget可以對應多個Element
;Flutter Framework
在構建UI時,會先調用此方法生成對應節點的Element
對象。此方法是Flutter Framework
隱式調用的,在我們開發過程中基本不會調用到。 -
debugFillProperties
復寫父類的方法,主要是設置DiagnosticableTree
的一些特性。 -
canUpdate
是一個靜態方法,它主要用于在Widget
樹重新build
時復用舊的widget
- 具體來說就是:是否用新的
Widget
對象去更新舊UI上所對應的Element
對象的配置; - 通過其源碼我們可以看到,只要
newWidget
與oldWidget
的runtimeType
和key
同時相等時就會用newWidget
去更新Element
對象的配置,否則就會創建新的Element
- 具體來說就是:是否用新的
StatelessWidget和StatefulWidget的區別
-
StatelessWidget
是狀態不可變的widget
, 初始狀態設置以后就不可再變化, 如果需要變化需要重新創建;StatefulWidget
可以保存自己的狀態 - 在
Flutter
中通過引入State
來保存狀態, 當State
的狀態改變時,能重新構建本節點以及孩子的Widget
樹來進行UI變化 - 如果需要主動改變
State
的狀態,需要通過setState()
方法進行觸發,單純改變數據是不會引發UI改變的 - 下面介紹部分的
Widget
組件
Text
UI上面文字的展示基本上都要靠Text
組件來完成
// 兩種構造函數
// 顯示普通的文本
const Text(this.data, {
Key key,
this.style,
this.textAlign,
this.textDirection,
this.locale,
this.softWrap,
this.overflow,
this.textScaleFactor,
this.maxLines,
this.semanticsLabel,
}) : assert(data != null),
textSpan = null,
super(key: key);
/// 段落式文本,可以給文本中的每個textSpan設置其樣式
const Text.rich(this.textSpan, {
Key key,
this.style,
this.textAlign,
this.textDirection,
this.locale,
this.softWrap,
this.overflow,
this.textScaleFactor,
this.maxLines,
this.semanticsLabel,
}): assert(textSpan != null),
data = null,
super(key: key);
參數介紹
data
文本的內容
Text('titanjun')
style
文本的樣式
const TextStyle({
this.inherit = true,
this.color,
this.fontSize,
this.fontWeight,
this.fontStyle,
this.letterSpacing,
this.wordSpacing,
this.textBaseline,
this.height,
this.locale,
this.foreground,
this.background,
this.shadows,
this.decoration,
this.decorationColor,
this.decorationStyle,
this.debugLabel,
String fontFamily,
String package,
}) : fontFamily = package == null ? fontFamily : 'packages/$package/$fontFamily',
assert(inherit != null),
assert(color == null || foreground == null, _kColorForegroundWarning);
// 相關屬性介紹
1. inherit: 為false時不顯示
2. color: 字體顏色
3. fontSize: 字體大小, 默認是14.0
4. fontWeight: 字體的粗體
5. fontStyle: 字體的樣式
normal正常 italic 斜體
6. letterSpacing: 字符間距
7. wordSpacing: 單詞間距
8. textBaseline
alphabetic:用于對齊字母字符底部的水平線
ideographic:用于對齊表意字符的水平線
9. height: 用在Text控件上的時候,會乘以fontSize做為行高,
10. locale: 國際化
11. foreground: 用paint來渲染text,也可以用他來改變字體顏色等
12. background: 背景顏色
13. decoration:
下劃線 underline、 刪除線 lineThrough、上劃線 overline,默認是無 none
14. decorationStyle: decoration線的樣式
solid: 直線, double: 兩條線, dotted: 短虛線, dashed: 長虛線, wavy: 波浪線
15. decorationColor: decoration線的顏色
16. debugLabel: 文本樣式的描述, 該屬性只在調試中維護
17. fontFamily和package(自定義字體的時候用的到,后面再詳解)
使用樣式示例
style: TextStyle(
inherit: true,
color: Colors.red,
fontSize: 50,
fontWeight: FontWeight.bold,
fontStyle: FontStyle.italic,
letterSpacing: 2,
wordSpacing: 5,
textBaseline: TextBaseline.alphabetic,
height: 2,
locale: Locale('CH'),
decoration: TextDecoration.lineThrough,
decorationColor: Colors.blue,
decorationStyle: TextDecorationStyle.wavy,
),
textAlign
文本顯示方向
left: 居左顯示
center: 居中顯示
right: 居右顯示
justify: 文本的拉伸行,其末尾用軟換行符填充寬度
start: 對齊容器前緣的文本。
對于從左到右的文本([TextDirection.ltr]),這是左邊緣。
對于從右到左的文本([TextDirection.rtl]),這是右邊緣。
end: 對齊容器尾部邊緣的文本。
對于從左到右的文本([TextDirection.ltr]),這是右邊緣。
對于從右到左的文本([TextDirection.rtl]),這是左邊緣。
textDirection
和上述TextAlign.start和TextAlign.end
一樣
softWrap
文本是否能換行,bool類型
overflow
用來指定超出文本的表示方式,是截斷文本啊還是用三個點顯示等
ellipsis: ...形式顯示
clip: 直接截斷
fade: 效果和clip一樣
maxLines
用來指定文本最多顯示多少行
textScaleFactor
文本字體的縮放倍數,如:1.5則在默認字體上變成1.5倍大小字體,0.5則是0.5倍
Text構造函數
child: Text(
// 需要顯示的文字
'titanjun.top' * 3,
textAlign: TextAlign.left,
textDirection: TextDirection.ltr,
locale: Locale('CH'),
maxLines: 1,
overflow: TextOverflow.fade,
style: TextStyle(
inherit: true,
color: Colors.red,
fontSize: 50,
fontWeight: FontWeight.bold,
fontStyle: FontStyle.italic,
letterSpacing: 2,
wordSpacing: 5,
textBaseline: TextBaseline.alphabetic,
height: 2,
locale: Locale('CH'),
decoration: TextDecoration.lineThrough,
decorationColor: Colors.blue,
decorationStyle: TextDecorationStyle.wavy,
),
),
Text.rich構造函數
這個構造函數和iOS
中用到的富文本類似
child: Text.rich(
TextSpan(
text: '博客地址: ',
children: [
TextSpan(
text: 'https://',
style: TextStyle(color: Colors.red)
),
TextSpan(
text: 'titanjun.top',
style: TextStyle(color: Colors.blue),
),
TextSpan(
text: '歡迎訪問',
style: TextStyle(color: Colors.orange)
),
]
),
),
其中TextSpan
的構造函數如下
const TextSpan({
this.style,
this.text,
// 接受List<TextSpan>類型的數組
this.children,
// 文本的手勢操作, 后面說這個
this.recognizer,
});
Image
- 一個用于展示圖片的組件。支持 JPEG、PNG、GIF、Animated GIF、WebP、Animated WebP、BMP 和 WBMP 等格式
-
Image
共有五種構造函數
Image()
const Image({
Key key,
// 一個圖片對象ImageProvider, 可設置NetworkImage(), FileImage(), MemoryImage()三種對象
@required this.image,
// 圖片的描述, String
this.semanticLabel,
this.excludeFromSemantics = false,
// 圖片的寬度, double
this.width,
// 圖片的高度, double
this.height,
// 圖像的顏色, 用于和圖片混合的顏色, 結合colorBlendMode使用
this.color,
// 顏色和圖片混合的狀態, BlendMode
this.colorBlendMode,
// 圖像在布局中分配的空間, BoxFit
this.fit,
// 圖像邊界內對齊圖像, Alignment
this.alignment = Alignment.center,
// 未充分填充容器時,是否重復顯示圖片
this.repeat = ImageRepeat.noRepeat,
// 九片圖像的中心切點, Rect
this.centerSlice,
// 是否在圖像的方向上繪制圖像 TextDirection
this.matchTextDirection = false,
// 當圖像提供者發生變化時,是繼續顯示舊圖像(true)還是暫時不顯示(false)
this.gaplessPlayback = false,
// 設置圖片的過濾質量
this.filterQuality = FilterQuality.low,
})
部分屬性詳解
fit
圖像在布局中分配的空間, BoxFit
枚舉值
-
fill
: 填充滿容器空間, 圖片會被拉伸 -
contain
: 以容器的大小等比例縮放圖片 -
cover
: 填充整個容器, 圖片會被剪切 -
fitWidth
: 以容器的寬度, 等比例縮放圖片 -
fitHeight
: 以容器的高度, 等比例的縮放圖片 -
none
: 以圖片的實際大小顯示 -
scaleDown
: 居中顯示, 圖片不會拉伸, 以寬高中最小的尺寸為標準
alignment
圖像邊界內對齊圖像, Alignment
類, 不是枚舉值
/// 定義方式為垂直方向-水平方向
static const Alignment topLeft = Alignment(-1.0, -1.0);
static const Alignment topCenter = Alignment(0.0, -1.0);
static const Alignment topRight = Alignment(1.0, -1.0);
static const Alignment centerLeft = Alignment(-1.0, 0.0);
static const Alignment center = Alignment(0.0, 0.0);
static const Alignment centerRight = Alignment(1.0, 0.0);
static const Alignment bottomLeft = Alignment(-1.0, 1.0);
static const Alignment bottomCenter = Alignment(0.0, 1.0);
static const Alignment bottomRight = Alignment(1.0, 1.0);
/// 使用方式
alignment: Alignment.topLeft,
// 或者
alignment: Alignment(0.0, 1.0)
Image(
image: NetworkImage('https://titanjun.oss-cn-hangzhou.aliyuncs.com/flutter/flutter.jpeg?x-oss-process=style/titanjun'),
fit: BoxFit.scaleDown,
alignment: Alignment.topLeft,
),
Image.network
用于顯示網絡圖片
Image.network(
'https://titanjun.oss-cn-hangzhou.aliyuncs.com/flutter/catimage.jpg',
width: 100,
height: 100,
fit: BoxFit.scaleDown,
alignment: Alignment.center,
)
網絡請求Image
是最常見的操作, 這里重點說明兩個點
緩存
-
ImageCache
是ImageProvider
默認使用的圖片緩存。ImageCache
使用的是LRU
的算法 - 默認可以存儲1000張圖片。如果覺得緩存太大,可以通過設置
ImageCache
的maximumSize
屬性來控制緩存圖片的數量。 - 也可以通過設置
maximumSizeBytes
來控制緩存的大小(默認緩存大小10MB)
CDN優化
如果想要使用cdn
優化,可以通過url
增加后綴的方式實現。默認實現中沒有這個點,但是考慮到cdn
優化的可觀收益,建議大家利用好這個優化
Image.asset
-
Flutter
應用程序可以包含代碼和assets
(有時稱為資源) -
asset
是打包到程序安裝包中的,可在運行時訪問 - 常見類型的
asset
包括靜態數據(例如JSON文件),配置文件,圖標和圖片(JPEG,WebP,GIF,動畫WebP / GIF,PNG,BMP和WBMP) -
Flutter
使用pubspec.yaml
文件(位于項目根目錄),來識別應用程序所需的asset
需要注意的是
- 圖片所在的文件夾
images
和pubspec.yaml
需要在同一目錄下, 否則pubspec.yaml
文件中, 設置資源路徑的時候要對應修改 -
images
圖片文件夾中2.0x和3.0x
圖片要分別創建兩個文件夾, 并把2倍和3倍圖分別放在不同的文件夾中, 切文件的名字不要在帶@2x和@3x
字樣
Image.asset(
'images/home.png',
width: 100,
height: 100,
fit: BoxFit.scaleDown,
alignment: Alignment.center,
)
Image.file
Image.file(File file, {
Key key,
double scale = 1.0,
this.semanticLabel,
this.excludeFromSemantics = false,
this.width,
this.height,
this.color,
this.colorBlendMode,
this.fit,
this.alignment = Alignment.center,
this.repeat = ImageRepeat.noRepeat,
this.centerSlice,
this.matchTextDirection = false,
this.gaplessPlayback = false,
this.filterQuality = FilterQuality.low,
})
- 主要解析file參數,其他與
Image()
構造的參數一致! -
file
: 對文件系統上的文件的引用。 - File 實例是一個對象,它包含可以在其上執行操作的路徑
Image.memory
Image.memory(Uint8List bytes, {
Key key,
double scale = 1.0,
this.semanticLabel,
this.excludeFromSemantics = false,
this.width,
this.height,
this.color,
this.colorBlendMode,
this.fit,
this.alignment = Alignment.center,
this.repeat = ImageRepeat.noRepeat,
this.centerSlice,
this.matchTextDirection = false,
this.gaplessPlayback = false,
this.filterQuality = FilterQuality.low,
})
- 加載
Uint8List
資源圖片 - 主要解析
bytes
參數,其他與Image()
構造的參數一致!
Icon
-
Flutter
中,Icon
是類似于web
開發中一樣使用iconfont
(字體圖標),它是將圖標做成字體文件,然后通過指定不同的字符而顯示不同的圖片 - 在字體文件中,每一個字符都對應一個位碼,而每一個位碼對應一個顯示字形,不同的字體就是指字形不同,即字符對應的字形是不同的
- 而在
iconfont
中,只是將位碼對應的字形做成了圖標,所以不同的字符最終就會渲染成不同的圖標。 - 在
Flutter
中iconfont
相較于圖片的優勢如下:- 體積小:可以減小安裝包大小。
- 矢量的:
iconfont
都是矢量圖標,放大不會影響其清晰度。 - 可以應用文本樣式:可以像文本一樣改變字體圖標的顏色、大小對齊等。
- 可以通過
TextSpan
和文本混用。
使用Material Design字體圖標
Flutter
默認包含了一套Material Design
的字體圖標,在pubspec.yaml
文件中的配置如下
flutter:
uses-material-design: true
<div class="note warning"><p>如果設置成false, 則圖片效果如下, 圖片顏色為自己設置的顏色</p></div>
-
Material Design
所有圖標可以在其官網查看:https://material.io/tools/icons/ -
Material Design
所有圖標對應的字符編碼可在material-design-icons中搜索查找
在Text中使用
下面看一個在Text
中使用iconfont
的示例
String iconStr = "";
// accessible:  or 0xE914 or E914
iconStr += "\uE914";
// error:  or 0xE000 or E000
iconStr += " \uE000";
// fingerprint:  or 0xE90D or E90D
iconStr += " \uE90D";
Text(iconStr,
style: TextStyle(
fontFamily: "MaterialIcons",
fontSize: 80.0,
color: Colors.green
),
)
上述代碼的運行效果如下
任何一個圖片我們都可以使用
Text
文本進行展示, 但是這需要我們提供每一個圖標的字符碼點, 可在material-design-icons中搜索查找, 而且并不能固定指定圖片的大小, 只能設置字體的大小, 這并對開發者不友好
Icon介紹
Flutter
封裝了一個Icon
來專門顯示字體圖標,上面的例子也可以用如下方式實現
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.accessible, color: Colors.green, size: 80),
Icon(Icons.error, color: Colors.green, size: 80),
Icon(Icons.fingerprint, color: Colors.green, size: 80),
],
)
Icons
類中包含了所有Material Design
圖標的IconData
靜態變量定義, .....我大概算了一下, Icons
中大概一共定義了984中圖標
// icon的構造函數
const Icon(this.icon, {
Key key,
// double, 設置圖片的大小, 同事設置寬高
this.size,
// Color, 設置圖片的顏色
this.color,
// String, 圖標的語義標簽
this.semanticLabel,
// TextDirection, 從左/右開始排列
this.textDirection,
})
按鈕
-
Flutter
提供了RaisedButton
、FlatButton
、OutlineButton
和IconButton
四種按鈕, 除了IconButton
之外都是繼承自MaterialButton
- 所有
Material
庫中的按鈕都有如下相同點:- 按下時都會有“水波動畫”。
- 有一個
onPressed
屬性來設置點擊回調,當按鈕按下時會執行該回調,如果不提供該回調則按鈕會處于禁用狀態,禁用狀態不響應用戶點擊
MaterialButton
MaterialButton
是除IconButton
按鈕之外的其他按鈕的父類, 下面介紹一下各屬性的使用
const MaterialButton({
Key key,
// 點擊事件
@required this.onPressed,
// 高亮狀態變化回調,參數:是否高亮,按下時高亮,抬起不高亮
this.onHighlightChanged,
// 字體的主體
this.textTheme,
// 按鈕文字顏色
this.textColor,
// 禁用狀態下按鈕字體顏色
this.disabledTextColor,
// 按鈕背景顏色
this.color,
// 禁用狀態下背景顏色
this.disabledColor,
// 高亮狀態(按下時的背景顏色)
this.highlightColor,
// 按鈕的水波紋的顏色
this.splashColor,
// 字體亮度
this.colorBrightness,
// 按鈕底部陰影效果的偏移量, double
this.elevation,
// 高亮狀態下, 按鈕底部陰影效果的偏移量, double
this.highlightElevation,
// 禁用狀態下, 按鈕底部陰影效果的偏移量, double
this.disabledElevation,
// 內邊距
this.padding,
// 按鈕的形狀
this.shape,
this.clipBehavior = Clip.none,
this.materialTapTargetSize,
this.animationDuration,
// 按鈕的最小寬度
this.minWidth,
// 按鈕的高度
this.height,
// 子widget
this.child,
})
onPressed
按鈕觸發時觸發的函數,如果不設置此屬性Button
為不可用狀態
onPressed: () => print('被點擊了'),
textTheme
按鈕字體的主題, 在onPressed
不為空的時候才有效果
/// 三個取值
ButtonTextTheme.normal
ButtonTextTheme.accent
ButtonTextTheme.primary
colorBrightness
設置按鈕的字體亮度, 取值分別是Brightness.light
和Brightness.darks
padding
內邊距,其接收值的類型是EdgeInsetsGeometry
類型的,EdgeInsetsGeometry
是一個抽象類, 只能使用其子類EdgeInsets
來實現
padding: EdgeInsets.all(10)
shape
- 設置按鈕的形狀,其接收值是
ShapeBorder
類型,ShapeBorder
也是一個抽象類 -
ShapeBorder
的子類中比較常用的幾個如下所示-
BeveledRectangleBorder
帶斜角的長方形邊框 -
CircleBorder
圓形邊框 -
RoundedRectangleBorder
圓角矩形 -
StadiumBorder
兩端是半圓的邊框
-
// 帶斜角的長方形邊框
const BeveledRectangleBorder({
// 邊框的樣式
this.side = BorderSide.none,
// 圓角大小
this.borderRadius = BorderRadius.zero,
})
// 圓形邊框
const CircleBorder({
this.side = BorderSide.none
})
// 圓角矩形
const RoundedRectangleBorder({
this.side = BorderSide.none,
this.borderRadius = BorderRadius.zero,
})
// 兩端是半圓的邊框
const StadiumBorder({
this.side = BorderSide.none
})
// 邊框樣式的設置
const BorderSide({
// 邊框顏色, 默認黑色
this.color = const Color(0xFF000000),
// 邊框寬度, 默認1.0
this.width = 1.0,
// 邊框樣式, solid: 實線邊框(默認值), none: 不顯示邊框
this.style = BorderStyle.solid,
})
下面就來看一下shape
的配置和使用, 設置默認狀態(即所有的邊框樣式和圓角都是默認值)的效果如下
children: <Widget>[
// BeveledRectangleBorder
RaisedButton(
child: Text('BeveledRectangleBorder'),
onPressed: () => print('RaisedButton'),
shape: BeveledRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
side: BorderSide(
color: Colors.red,
width: 2,
style: BorderStyle.solid
)
),
),
RaisedButton(
child: Icon(Icons.supervisor_account, color: Colors.green, size: 40),
onPressed: () => print('RaisedButton'),
padding: EdgeInsets.all(10),
shape: CircleBorder(
side: BorderSide(
color: Colors.red,
width: 2,
style: BorderStyle.solid
)
),
),
RaisedButton(
child: Text('RoundedRectangleBorder'),
onPressed: () => print('RaisedButton'),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
side: BorderSide(
color: Colors.red,
width: 2,
style: BorderStyle.solid
)
),
),
RaisedButton(
child: Text('StadiumBorder'),
onPressed: () => print('RaisedButton'),
shape: StadiumBorder(
side: BorderSide(
color: Colors.red,
width: 2,
style: BorderStyle.solid
)
),
),
],
上述代碼是分別設置圓角和邊框后的代碼, 效果如下
RaisedButton
-
RaisedButton
即"漂浮"按鈕,它默認帶有陰影和灰色背景。按下后陰影會變大 -
RaisedButton
繼承自MaterialButton
, 相關屬性和父類一樣
RaisedButton(
child: Text('RaisedButton'),
onPressed: () => print('RaisedButton'),
)
FlatButton
-
FlatButton
即扁平按鈕,默認背景透明并不帶陰影。按下后,會有背景色 -
RaisedButton
繼承自MaterialButton
, 相關屬性和父類一樣
FlatButton(
child: Text('FlatButton'),
onPressed: () => print('FlatButton'),
)
OutlineButton
-
OutlineButton
默認有一個邊框,不帶陰影且背景透明。按下后,邊框顏色會變亮、同時出現背景和陰影(較弱) -
RaisedButton
繼承自MaterialButton
, 相關屬性和父類一樣
OutlineButton(
child: Text('OutlineButton'),
onPressed: () => print('OutlineButton'),
)
IconButton
IconButton
是一個可點擊的Icon,不包括文字,默認沒有背景,點擊后會出現背景
// 繼承自StatelessWidget
class IconButton extends StatelessWidget {
const IconButton({
Key key,
// 按鈕的大小
this.iconSize = 24.0,
// 內邊距
this.padding = const EdgeInsets.all(8.0),
// 按鈕中圖片的對齊方式
this.alignment = Alignment.center,
// 圖片按鈕的圖片Icon
@required this.icon,
// 背景色
this.color,
// 高亮狀態下的背景色
this.highlightColor,
// 按鈕按下時, 水波紋的顏色
this.splashColor,
// 禁用狀態下, 按鈕的背景色
this.disabledColor,
// 點擊事件
@required this.onPressed,
// String, 描述按鈕按下時的描述文本, 需要長按才能出現(黑框顯示文本)
this.tooltip
})
}
使用示例
IconButton(
icon: Icon(Icons.mail_outline, color:Colors.orange, size: 40),
color: Colors.yellow,
iconSize: 100,
alignment: Alignment.topLeft,
onPressed: () => print('IconButton'),
tooltip: 'titanjun.top',
)
圖文按鈕
每一個繼承自MaterialButton
的按鈕Widget
都有一個工廠構造函數, 返回一個圖片在左, 文字在右的按鈕
factory RaisedButton.icon({
// 這里包含MaterialButton的所有屬性
....
// 圖片Widget
@required Widget icon,
// 文字Widget
@required Widget label,
})
factory FlatButton.icon({
....
@required Widget icon,
@required Widget label,
})
factory OutlineButton.icon({
....
@required Widget icon,
@required Widget label,
})
// 使用示例
RaisedButton.icon(
label: Text('data'),
icon: Icon(Icons.mail),
onPressed: () => {},
),
單選開關和復選框
-
Material widgets
庫中提供了Material
風格的單選開關Switch
和復選框Checkbox
,它們都是繼承自StatelessWidget
- 它們本身不會保存當前選擇狀態,所以一般都是在父
widget
中管理選中狀態 - 當用戶點擊
Switch
或Checkbox
時,它們會觸發onChanged
回調,我們可以在此回調中處理選中狀態改變邏輯
// Switch屬性
const Switch({
Key key,
// Switch的狀態值, true開啟, false關閉
@required this.value,
// Switch改變狀態所執行的操作
@required this.onChanged,
// 開啟狀態下選項條的顏色
this.activeColor,
// 開啟狀態下圓球的顏色
this.activeTrackColor,
// 關閉狀態下選項條的顏色
this.inactiveThumbColor,
// 關閉狀態下圓球的顏色
this.inactiveTrackColor,
// 設置開啟狀態下圓球的圖片
this.activeThumbImage,
// 設置關閉狀態下圓球的圖片
this.inactiveThumbImage,
// 設置Switch的尺寸樣式, padded: 建議大小48, shrinkWrap: 可能的最小尺寸
this.materialTapTargetSize,
})
// Checkbox屬性
const Checkbox({
Key key,
// Switch的狀態值, true選中, false未選中
@required this.value,
// 如果為 true,那么復選框的值可以是 true,false 或 null
// 如果為false(默認值), 那么只有true和false兩種狀態
this.tristate = false,
// 改變狀態時執行的函數
@required this.onChanged,
// 選中時的顏色
this.activeColor,
// 設置Checkbox的尺寸樣式, padded: 建議大小48, shrinkWrap: 可能的最小尺寸
this.materialTapTargetSize,
})
使用代碼
children: <Widget>[
Switch(
value: false,
onChanged: (value) {},
activeColor: Colors.red,
activeTrackColor: Colors.yellow,
inactiveThumbColor: Colors.blue,
inactiveTrackColor: Colors.cyan,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap
),
Checkbox(
value: true,
onChanged: (value) { },
activeColor: Colors.orange,
tristate: true,
)
],
歡迎您掃一掃下面的微信公眾號,訂閱我的博客!