Flutter如何自定義一個(gè)Stateful(有狀態(tài))組件
你將學(xué)到:
- 什么是stateful 組件
- 如何創(chuàng)建一個(gè)stateful 組件
- 自定義有狀態(tài)組件的實(shí)例
實(shí)例的樣子:

什么是stateful widget
stateful widget 是指有狀態(tài)變化的組件,例如系統(tǒng)提供的 Checkbox, Radio, Slider, InkWell, Form, and TextField 都是 stateful widgets, 他們都是 StatefulWidget的子類。
相對(duì)應(yīng)的就有stateless widget 沒有內(nèi)部狀態(tài)變化的組件,例如 Icon、 IconButton, 和Text 都是無狀態(tài)widget, 他們都是 StatelessWidget的子類。
通俗點(diǎn)講就是:
stateful組件就是和用戶交互后會(huì)有狀態(tài)變化,例如滾動(dòng)條Slider。
stateless組件就是交互后沒有狀態(tài)變化,例如顯示的一個(gè)文本Text。
如何創(chuàng)建一個(gè)stateful 組件
創(chuàng)建有狀態(tài)的組件可以遵循以下步驟:
- 1.創(chuàng)建一個(gè)繼承自
StatefulWidget的類來表示你要自定義的可變控件 - 2.創(chuàng)建一個(gè)繼承自
State的類來處理這個(gè)可變控件的狀態(tài)和顯示樣式(build方法)。 - 3.當(dāng)用戶交互發(fā)生,例如
onPressed點(diǎn)擊事件被觸發(fā)時(shí),可以調(diào)用setState方法告訴組件需要重繪
自定義有狀態(tài)組件的實(shí)例
1.分析一下要實(shí)現(xiàn)的例子,這里需要先繼承自StatefulWidget類定義一個(gè)屬于這個(gè)組件的類:
class FavoriteWidget extends StatefulWidget { //組件名:FavoriteWidget
@override
_FavoriteWidgetState createState() { // 分析1
return _FavoriteWidgetState();
}
}
分析1:
Flutter中定義Stateful類必須返回一個(gè)State類的對(duì)象,所以這里定義了一個(gè)叫_FavoriteWidgetState的state類,這個(gè)類名前面加了下劃線 _ 代表這個(gè)是私有的類。
2.實(shí)現(xiàn)State的子類_FavoriteWidgetState
_FavoriteWidgetState類如上面講到的需要保存組件的狀態(tài),并且要在build方法中處理組件的展示樣式。這里使用變量_isFavorited代表是否點(diǎn)擊過喜歡,_favoriteCount代表當(dāng)前喜歡的次數(shù)。
先定義變量:
class _FavoriteWidgetState extends State<FavoriteWidget> {
bool _isFavorited = true; //代表是否點(diǎn)擊過喜歡
int _favoriteCount = 55; //代表當(dāng)前喜歡的次數(shù)
}
然后處理點(diǎn)擊事件的方法:
點(diǎn)擊后如果_isFavorited是true表示喜歡,我們將次數(shù)_favoriteCount加一,否則就減一。
class _FavoriteWidgetState extends State<FavoriteWidget> {
bool _isFavorited = true;
int _favoriteCount = 55;
void _toggleFavorite() { //分析2
setState(() {
if (_isFavorited) {
_favoriteCount -= 1;
_isFavorited = false;
// Otherwise, favorite it.
} else {
_favoriteCount += 1;
_isFavorited = true;
}
});
}
分析2:用_toggleFavorite方法來處理狀態(tài)的變化,里面用setState方法告訴組件需要重繪,里面將狀態(tài)的值盡心修改。
- 最后一步根據(jù)狀態(tài)的值來繪制組件長(zhǎng)的樣子
這里添加一個(gè)IconButton和一個(gè)text:
@override
Widget build(BuildContext context) {
return new Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new Container(
padding: new EdgeInsets.all(0.0),
child: new IconButton(
icon: (_isFavorited
? new Icon(Icons.star)
: new Icon(Icons.star_border)),
onPressed: _toggleFavorite),
),
new SizedBox(
width: 18.0,
child: new Container(child: new Text('$_favoriteCount')),
),
],
);
}
該widget使用IconButton(而不是Icon), 因?yàn)樗哂幸粋€(gè)onPressed屬性,該屬性定義了處理點(diǎn)擊的回調(diào)方法onPressed,在回調(diào)方法中我們調(diào)用了上面的改變狀態(tài)的方法。