[英]How to create a Table of buttons in Flutter and randomly select any button from it?
我正在嘗試在 Flutter 中創建一個自定義的 Housie Game Ticket Generator,其中我必須從 4X3 按鈕表中隨機選擇一個按鈕,並顯示一個 no。 在那個按鈕上。 單擊按鈕時,它的顏色從綠色變為紅色。
我通過硬編碼所有單元格創建了一個 4X3 按鈕表,如下所示。 現在我想從表格中隨機選擇一些按鈕並在它們上設置一個 onPressed 函數。 我該如何繼續?
body: new Container(
child: new Table(
border: TableBorder.all(),
children: [
TableRow(
children: [
new FlatButton(
color: Colors.white,
onPressed: () {},
),
new FlatButton(
color: Colors.white,
onPressed: () {},
),
new FlatButton(
color: Colors.white,
onPressed: () {},
),
new FlatButton(
color: Colors.white,
onPressed: () {},
)
]
),
TableRow(
children: [
new FlatButton(
color: Colors.white,
onPressed: () {},
),
new FlatButton(
color: Colors.white,
onPressed: () {},
),
new FlatButton(
color: Colors.white,
onPressed: () {},
),
new FlatButton(
color: Colors.white,
onPressed: () {},
)
]
),
TableRow(
children: [
new FlatButton(
color: Colors.white,
onPressed: () {},
),
new FlatButton(
color: Colors.white,
onPressed: () {},
),
new FlatButton(
color: Colors.white,
onPressed: () {},
),
new FlatButton(
color: Colors.white,
onPressed: () {},
)
]
),
]
),
)
現在我想從表格中隨機選擇一些按鈕並在它們上設置一個 onPressed 函數。 我該如何繼續?
存儲按鈕“身份”的最安全位置,無論是第一個、第 10 個還是第 100 個按鈕都在其中。
class GameButton extends StatelessWidget {
final int id;
const GameButton({
this.id,
})
...
當單擊按鈕時,您希望在單擊的那一刻獲得該信息 - 讓我們讓按鈕告訴我們這些信息:
class GameButton extends StatelessWidget {
final int id;
final Function(int) onPressed;
const GameButton({
this.id,
this.onPressed,
})
...
注意這里添加的Function(int) onPressed
- 它是一個傳遞整數的回調,我們將在按鈕被點擊時調用它並讓按鈕將它的id
傳遞給這個函數:
class GameButton extends StatelessWidget {
final int id;
final Function(int) onPressed;
const GameButton({this.id, this.onPressed});
@override
Widget build(BuildContext context) {
return FlatButton(
onPressed: () {
// on click, we pass id to onPressed(int)
onPressed(this.id);
},
child: null,
);
}
}
我們將在創建每個按鈕時定義如何處理這個id
:
...
new GameButton(
id: id,
onPressed: onButtonClicked,
),
...
創建按鈕的表格你可以把它們先寫List<TableRow>
填寫每一行與按鈕的所需數量,然后設置行作為整個列表的children
到Table
:
List<TableRow> buildButtons() {
// list for all rows
List<TableRow> rows = [];
// each button get's unique id
int id = 0;
for (var i = 0; i < widget.rows; i++) {
// new empty row
List<Widget> rowChildren = [];
// ---------------------- id incremented here
for (var y = 0; y < widget.cols; y++,id++) {
// fill row with buttons
rowChildren.add(
new GameButton(
id: id,
onPressed: onButtonClicked,
),
);
}
rows.add(new TableRow(children: rowChildren));
}
return rows;
}
這是處理程序:
onButtonClicked(int id) {
// this id ^ variable is the one coming from any clicked button
// use it e.g. to compare with any other variables from State
print("clicked button $id");
}
這是獲取隨機數的代碼:
int max = widget.rows * widget.cols - 1;
this.randomSelection =
Random.secure().nextInt(max);
最終結果可能如下所示:
import 'package:flutter/material.dart';
import 'dart:math';
class ButtonTable extends StatefulWidget {
final int rows;
final int cols;
const ButtonTable({Key key, this.rows: 6, this.cols: 4}) : super(key: key);
get max => rows * cols - 1;
@override
_ButtonTableState createState() => _ButtonTableState();
}
class _ButtonTableState extends State<ButtonTable> {
int randomNumber = -1;
List<int> pot;
List<int> crossedNumbers;
List<int> initialTicket;
String resultText = "";
String statusText = "Roll it";
@override
void initState() {
super.initState();
restart();
}
void restart() {
initialTicket = generateTicket();
pot = List.generate(widget.max, (index) => index);
crossedNumbers = [];
randomNumber = -1;
}
List<int> generateTicket() {
var temp = List.generate(widget.max, (index) => index);
List<int> ticket = [];
for (int i = 0; i < widget.max / 2; i++) {
final randomIndex = Random.secure().nextInt(temp.length);
ticket.add(temp.removeAt(randomIndex));
}
return ticket;
}
@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
new Table(
border: TableBorder.all(),
children: buildButtons(),
),
Text("$statusText"),
Text("$resultText"),
Center(
child: Row(
children: <Widget>[
FlatButton(
color: Colors.grey,
onPressed: rollNext,
child: Text("Roll"),
),
FlatButton(
color: Colors.grey,
onPressed: () {
setState(() {
restart();
});
},
child: Text("Restart")),
],
),
),
Text("Pot:" + pot.toString())
],
));
}
onButtonClicked(id) {
setState(() {
if (id == randomNumber) {
if (isNumberPlaying(id)) {
resultText = Random.secure().nextBool() ? "Housie" : "Whoo";
statusText = "Pull next number";
crossedNumbers.add(id);
} else {
resultText = Random.secure().nextBool()
? "You can't cheat machine code"
: "Nice try, but you don't have it on your ticket!";
}
} else {
resultText =
Random.secure().nextBool() ? "Missed, are u ok?" : "Try harder";
}
});
}
List<TableRow> buildButtons() {
List<TableRow> rows = [];
int id = 0;
for (var i = 0; i < widget.rows; i++) {
// new empty row
List<Widget> rowChildren = [];
for (var y = 0; y < widget.cols; y++, id++) {
// fill row with buttons
rowChildren.add(
new GameButton(
id: id,
playing: isNumberPlaying(id),
crossed: isCrossed(id),
onPressed: onButtonClicked,
),
);
}
rows.add(new TableRow(children: rowChildren));
}
return rows;
}
rollNext() {
setState(() {
if (pot.length > 0) {
int randomIndex = Random.secure().nextInt(pot.length);
this.randomNumber = pot.removeAt(randomIndex);
this.statusText = "Rolled: $randomNumber";
this.resultText = "playing one more time...";
} else {
restart();
}
});
}
isNumberPlaying(int id) {
return initialTicket.contains(id);
}
isCrossed(int id) {
return crossedNumbers.contains(id);
}
}
class GameButton extends StatelessWidget {
final int id;
final Function(int) onPressed;
final bool playing;
final bool crossed;
const GameButton({
Key key,
this.id,
this.onPressed,
this.playing,
this.crossed,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return FlatButton(
color: decideColor(),
onPressed: () {
onPressed(this.id);
},
child: Stack(
children: <Widget>[
Visibility(
visible: crossed,
child: Icon(
Icons.done,
size: 48,
color: Colors.brown,
)),
decideText()
],
),
);
}
Color decideColor() {
// if id is not active = white
if (!this.playing)
return Colors.white;
else if (this.crossed) {
return Colors.yellow;
}
}
decideText() {
return Text(
playing ? "$id" : '',
style: TextStyle(
color: crossed ? Colors.green : Colors.black,
fontWeight: crossed ? FontWeight.bold : FontWeight.normal,
),
);
}
}
玩得開心
我沒明白你的問題,你能解釋一下嗎? 但是您可以像這樣更改按鈕顏色。
聲明一個變量: bool didColourChange = false;
FlatButton(
color: didColourChange ? Colors.red: Colors.green,
onPressed: () {
setState(() {
didColourChange = !didColourChange;
});
},
)
如果您想添加一些動畫,您可以將AnimatedContainer小部件與GestureDetector一起使用,而不是使用FlatButton
小部件。
為了避免對您的children
硬編碼,您可能希望使用List類的map方法,但這僅適用於將數字存儲在列表中的情況。
這是輸出:
這是完整的代碼:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<List<int>> someListsOfNumbers = [
List.generate(4, (int idx) => idx),
List.generate(4, (int idx) => idx + 4),
List.generate(4, (int idx) => idx + 8),
];
Map<int, bool> pressedValues = Map.fromIterable(
List.generate(12, (int idx) => idx),
key: (item) => item,
value: (item) => false,
);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: new Container(
child: new Table(
border: TableBorder.all(),
children: someListsOfNumbers.map(
(List<int> someList) => TableRow(
children: someList.map((int val) => GestureDetector(
onTap: (){
setState((){
pressedValues[val] = !pressedValues[val];
});
},
child: AnimatedContainer(
duration: const Duration(milliseconds: 700),
height: 56.0,
color: pressedValues[val] ? Colors.red : Colors.green,
child: Center(
child: pressedValues[val] ? Text(val.toString()) : Text(""),
)
)
)
).toList()
)
).toList()
)
)
);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.