前言
拖了好久終于開始看Flutter帝美,為了加深印象鞏固學習效果腺毫,現(xiàn)將每次學習的內(nèi)容總結成筆記骂澄,鞏固效果也方便以后查閱吓蘑。同時,筆記相關的Demo項目已經(jīng)上傳到Github坟冲,這里是傳送門磨镶,歡迎指正。
正文
Flutter相關文檔
1.官方文檔
2.Flutter中文網(wǎng)
3.官方Demo(Github地址)
基礎控件目錄
常用基礎控件
不管在哪個前端平臺健提,常用的基礎控件都一樣琳猫,大致包括:文本、圖片私痹、按鈕脐嫂、輸入框统刮、進度條、單選框和復選框账千、開關切換(Switch)侥蒙、提示窗、對話框匀奏;布局用的控件(Layout)基本包含:橫向布局鞭衩、縱向布局、格子布局娃善、重疊布局醋旦、各類包含不同約束條件的特定布局(內(nèi)外間距,靠邊居中会放,相對位置等)饲齐;然后是一些根據(jù)常用程度封裝的控件包括:列表控件、滑動控件(橫縱方向)咧最,下拉刷新捂人,抽屜(Drawer)等。
然后在Flutter中矢沿,控件分為StatefulWidget和StatelessWidget(有狀態(tài)控件和無狀態(tài)控件)滥搭,無狀態(tài)控件是死的,不會動態(tài)更新捣鲸,所以實際使用的時候大多數(shù)情況下都是封裝自己的StatefulWidget瑟匆,StatefulWidget的狀態(tài)存儲在對應的State類里面,需要更新的時候可以通過調用setState()方法來刷新頁面栽惶。
StatefulWidget基本代碼模板如下:
class DemoStatefulWidget extends StatefulWidget{
@override
State<StatefulWidget> createState() {
return DemoState();
}
}
class DemoState extends State<DemoStatefulWidget>{
var data;
@override
Widget build(BuildContext context) {
return Text(data);
}
void onDataChanged(newData){
setState(() {//刷新控件
data = newData;
});
}
}
接下來愁溜,按照上面梳理出的常用控件,我們一個一個來看外厂。
文本 Text
Text官方文檔
沒啥注意點冕象,屬性看文檔基本都能看懂。
基本使用
Widget build(BuildContext context) {
return new Text(
"A text in container",
style: new TextStyle(
color: Color(0xFF0000CD), fontStyle: FontStyle.normal, fontSize: 15),
);
}
圖片 Image
Image官方文檔
也沒啥注意點汁蝶。
基本使用
Widget build(BuildContext context) {
return Image.network(//圖片來自網(wǎng)絡
imageUrl,
width: 200.0,
height: 150.0,
);
// Image.asset(name);//圖片來自項目內(nèi)的資源
// Image.file(file);//圖片來自文件
// Image.memory(bytes);//圖片來自內(nèi)存
}
按鈕 RaisedButton FlatButton
這兩個按鈕除了風格不同以外沒什么別的區(qū)別渐扮,只有個別屬性彼此有區(qū)分。
RaisedButton官方文檔
FlatButton官方文檔
Widget build(BuildContext context) {
return RaisedButton(
elevation: 5,
color: Color(0xff87CEFA),
child: Text("Print"),
onPressed: () {}
);
}
輸入框 TextField
TextField官方文檔
基本使用
Widget build(BuildContext context) {
return TextField(
maxLines: 5,
style: TextStyle(color: Colors.black),
controller: editController,
obscureText: false,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Text',
)
);
進度條 Slider
Slider官方文檔
注意點:
dividions屬性掖棉,比如設置dividions屬性為4墓律,進度條被分為四等分,滑動時進度會停留在等分點上幔亥;
label屬性耻讽,設置之后,滑動時紫谷,標簽將展示在進度條上齐饮;
效果如下:
代碼:
Widget build(BuildContext context) {
return Slider(
label: 'slider',
value: rating,
divisions: 4,
onChanged: (newValue) {
setState(() {
rating = newValue;
});
print('rating: ${rating}'); //打日志到控制臺)
},
);
CheckBox
很簡單沒啥要注意的捐寥。
CheckBox官方文檔
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.fromLTRB(0.0, 10, 0, 10),
margin: EdgeInsets.fromLTRB(0, 10, 15, 10),
alignment: Alignment(-1, 0),
//min和max為最小進度值和最大進度值,不設置的話默認為0到1
child: Slider(
inactiveColor: Colors.cyan[100],
activeColor: Colors.cyan[400],
min: 0,
max: 2,
label: 'slider',
value: rating,
onChanged: (newValue) {
setState(() {
rating = newValue;
});
print('rating1: ${rating}'); //打日志到控制臺)
},
),
);
}
Radio
Radio官方文檔
這個看文檔有點迷糊祖驱,而且這個使用和Android的不一樣握恳。
這里要注意的是value和groupValue兩個屬性,value是當這個Radio選中的時候更新到onChange方法里的值捺僻,groupValue是乡洼,當它的值和value的值相同時,這個Radio就是選中狀態(tài)匕坯,否則就是非選中狀態(tài)束昵。所以一般使用時都是把groupValue的值設定為一個動態(tài)變量,然后在onChange方法里更新這個動態(tài)變量葛峻。
基本使用
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
//靠左
verticalDirection: VerticalDirection.down,
children: <Widget>[
Container(
margin: EdgeInsets.fromLTRB(0, 10, 15, 0),
child:
Text('Radio:')),
Row(
children: <Widget>[
Text('1'),
Radio(
value: '1',
groupValue: this.radioSelectedPosition,
onChanged: (radioChange) {
setState(() {
this.radioSelectedPosition = radioChange;
});
print('radioChange1: ${radioChange}'); //打日志到控制臺)
},
),
],
),
Row(
children: <Widget>[
Text('2'),
Radio(
value:'2',
groupValue: this.radioSelectedPosition,
onChanged: (radioChange) {
setState(() {
this.radioSelectedPosition = radioChange;
});
print('radioChange2: ${radioChange}'); //打日志到控制臺)
},
),
],
),
Row(
children: <Widget>[
Text('3'),
Radio<String>(
value: '3',
groupValue: this.radioSelectedPosition,
onChanged: (radioChange) {
setState(() {
this.radioSelectedPosition = radioChange;
});
print('radioChange3: ${radioChange}'); //打日志到控制臺)
},
),
],
),
]);
}
效果:
Switch
Widget build(BuildContext context) {
return Switch(
activeColor: Colors.deepOrange[300],
activeTrackColor: Colors.deepOrange[600],
inactiveTrackColor: Colors.blue[300],
inactiveThumbColor: Colors.blue[100],
inactiveThumbImage: NetworkImage(imageUrl),
value: switchOn,
onChanged: (switchOn){
setState(() {
this.switchOn = switchOn;
print('switchOn: ${switchOn}'); //打日志到控制臺)
});
},
);
}
最后锹雏,有一個重要而且特別的屬性
在看第一個控件的時候,我就注意到這個屬性术奖,key礁遵,排在第一位。簡單看文檔看不明白到底是做什么用的采记,然后往下看的時候我注意到每一個控件都有key這個屬性佣耐,而且都是排在第一位。于是我去查看了官方文檔唧龄,結果我的個乖乖兼砖,開頭就是一個整整10分鐘的講解視頻,由于視頻是全英文的并且字幕翻譯的并不好既棺,我反復看了三遍讽挟,才大致摸清楚了key的含義和用法。
要理解這個key的使用必須要對Flutter的控件樹刷新機制有簡單的了解援制。Flutter在構建Widget樹的時候戏挡,同時會構建一個Element樹,這個Element樹才是顯示和刷新頁面的時候真正起作用的東西晨仑,Widget里面只是存了一些控件的屬性值而已。在刷新Element樹的時候拆檬,F(xiàn)lutter會依次對比每個控件的改變狀態(tài)洪己,首先是檢查type,如果兩個控件是相同的類型竟贯,type就是一樣的答捕,然后是檢查key,比如你交換了頁面中兩個Text的位置屑那,改變了Widget樹的結構拱镐,如果此時你對這個控件設置了key艘款,它會檢查出前后狀態(tài)下控件的key不一樣,會判定這里有修改沃琅,然后Flutter會去遍歷和刷新Element樹哗咆,將它調整到正確的交換后的狀態(tài),否則的話益眉,由于兩個Text的type是一樣的晌柬,F(xiàn)lutter檢查之后會認為Element樹沒有必要刷新,此時就會出現(xiàn)錯誤郭脂,你會發(fā)現(xiàn)你交換控件之后頁面上兩個文本沒有絲毫改變年碘,如果你不了解這個機制的話,這個錯誤會顯得莫名其妙并且完全摸不著頭腦展鸡。
然后屿衅,key還包括ValueKey、LocalKey莹弊、GlobleKey涤久,各種場景下適合使用的類型不相同,詳細可見官方文檔箱硕。然后后來找到一篇文章拴竹,基本很詳細的把官方視頻要闡述的內(nèi)容解釋清楚了,好文傳送門剧罩。
尾聲
以上栓拜,第一部分暫時整理這么多,接下來空余時間再逐步梳理剩下的控件惠昔,預計整個常用控件的梳理大概要分3篇筆記幕与。個人從零逐步學習Flutter,水平有限镇防,如發(fā)現(xiàn)問題啦鸣,歡迎斧正!