前一天的文章30天Flutter手滑系列 - 井字遊戲實作(Tic Tac Toe)(2),我們停在點擊按鈕後控制OX的部分,今天我們來完成它。
為了達到點擊按鈕,然後更新按鈕文字的目的,我們需要用到之前文章提到的狀態管理
方式,透過setState
的方式,讓flutter知道Widget的狀態已經改變,才能即時更新我們需要的內容。
首先,我們先定義一個類別,簡單包含id
、text
、enabled
這三個屬性,方便記錄之後每個按鈕的變化。
class GameButton {
final id;
String text;
bool enabled;
GameButton({this.id, this.text = "", this.enabled = false});
}
為了讓每個按鈕有對應的狀態,我們先宣告一個內容為GameButton
的List
變數gameButtons
。
List<GameButton> gameButtons;
透過initState
,初始化整個gameButtons
的狀態。因為有9個按鈕,這裡我們需要new
9個GameButton
。
void initState() {
gameButtons = <GameButton>[
new GameButton(),
new GameButton(),
new GameButton(),
new GameButton(),
new GameButton(),
new GameButton(),
new GameButton(),
new GameButton(),
new GameButton(),
];
}
如前面文章提到,狀態的改變可以透過setState()
這個方法,因此我們加入一個_playGame
的函數,並傳入index
當參數,讓按鈕點擊時可以去呼叫這個函數,去進行資料更新的動作。
void _playGame(index) {
setState(() {
gameButtons[index].enabled = true;
});
}
定義好上述變數與函數後,就是把這些與Button的onPressed
做連結。
onPressed: () {
_playGame(index); // 這邊的index,來自於List.generate(9, index)
}
而顯示X
的文字部分,我們可以加入判斷如下。
child: Text(
gameButtons[index].enabled ? "X" : "",
style: TextStyle(fontSize: 50.0),
)
如此一來,我們就可以根據點擊到的按鈕,再改變其狀態填入文字了。
class GameButton {
final id;
String text;
bool enabled;
GameButton({this.id, this.text = "", this.enabled = false});
}
class _TicTacToePageState extends State<TicTacToePage> {
List<GameButton> gameButtons;
void initState() {
gameButtons = <GameButton>[
new GameButton(),
new GameButton(),
new GameButton(),
new GameButton(),
new GameButton(),
new GameButton(),
new GameButton(),
new GameButton(),
new GameButton(),
];
}
void _playGame(index) {
setState(() {
gameButtons[index].enabled = true;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
GridView.count(
crossAxisCount: 3,
shrinkWrap: true,
children: List.generate(9, (index) {
return Container(
padding: EdgeInsets.all(8.0),
child: FlatButton(
child: Text(
gameButtons[index].enabled ? "X" : "",
style: TextStyle(fontSize: 50.0),
),
color: Colors.grey,
textColor: Colors.white,
onPressed: () {
_playGame(index);
},
),
);
})),
Center(
child: ButtonTheme(
minWidth: 200,
height: 80,
child: RaisedButton(
color: Colors.blue,
child: Text('Start Game'),
onPressed: null,
),
),
)
],
),
);
}
}