【发布时间】:2020-10-21 08:41:38
【问题描述】:
编辑
本质上,我只是想知道是否有一种方法可以让两个小部件在 Flutter 中并行运行。就我而言,我希望 Timer 小部件和 Game 小部件一起运行,而不会相互干扰。
我尝试过使用计算和隔离,但显然,隔离不能用于更改小部件状态。
我正在开发一款记忆游戏,我想在卡片组顶部添加一个计时器。下面是我的代码。
问题是,当计时器启动时,
@override
void initState() {
previousClick = _CardTileState();
super.initState();
st.start();
timer = Timer.periodic(Duration(seconds: 1), (Timer t) {
int ms = st.elapsedMilliseconds;
int sec = (ms ~/ 1000) % 60;
int min = (ms ~/ 1000) ~/ 60;
if (min == 2) {
st.stop();
st.reset();
timer.cancel();
} else {
setState(() {
mins = strFormat(min);
secs = strFormat(sec);
});
}
});
}
我不能再点击我的卡片来匹配它们。 GestureDetector 的 onTap() 回调没有被执行。
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
if (widget.isClickable) {
print('clicked ' + widget.index.toString());
widget.parent.handleClick(this);
}
},
我该如何解决这个问题?这是完整的代码:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:save_the_planet/data.dart';
class GameScreen extends StatefulWidget {
GameScreen({Key key, this.title}) : super(key: key);
final String title;
@override
_GameScreenState createState() => _GameScreenState();
}
class _GameScreenState extends State<GameScreen> {
List<CardTile> cards = getCards();
_CardTileState previousClick;
String click = "";
int score = 0;
String mins = "00";
String secs = "00";
Stopwatch st = Stopwatch();
Timer timer;
@override
void initState() {
previousClick = _CardTileState();
super.initState();
st.start();
timer = Timer.periodic(Duration(seconds: 1), (Timer t) {
int ms = st.elapsedMilliseconds;
int sec = (ms ~/ 1000) % 60;
int min = (ms ~/ 1000) ~/ 60;
if (min == 2) {
st.stop();
st.reset();
timer.cancel();
} else {
setState(() {
mins = strFormat(min);
secs = strFormat(sec);
});
}
});
}
String strFormat(int val) {
String res = "";
if (val < 10)
res = "0" + val.toString();
else
res = val.toString();
return res;
}
void handleClick(_CardTileState source) {
try {
if (previousClick.widget.getIsUncovered()) {
if (click == 'first click') {
print('second click');
click = 'second click';
source.setState(() {
source.widget.setIsUncovered(true);
source.widget.setIsClickable(false);
});
Timer(Duration(milliseconds: 1000), () {
if (source.widget.getImagePath() ==
previousClick.widget.getImagePath()) {
score += 100;
print(score);
if (score == 1000) {
print('game over');
}
previousClick = _CardTileState();
} else {
source.setState(() {
source.widget.setIsUncovered(false);
source.widget.setIsClickable(true);
});
previousClick.setState(() {
previousClick.widget.setIsUncovered(false);
previousClick.widget.setIsClickable(true);
});
previousClick = _CardTileState();
}
});
}
}
} catch (e) {
print('first click');
click = 'first click';
source.setState(() {
source.widget.setIsUncovered(true);
source.widget.setIsClickable(false);
});
previousClick = source;
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
height: MediaQuery.of(context).size.height,
color: Colors.black,
child: Column(
children: <Widget>[
Padding(padding: EdgeInsets.only(top: 25)),
SizedBox(
width: MediaQuery.of(context).size.width / 3,
child: Card(
margin: EdgeInsets.all(5),
color: Colors.white54,
child: Row(
children: <Widget>[
Icon(Icons.access_time),
Text(mins + ":" + secs),
],
),
),
),
GridView(
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 100.0, mainAxisSpacing: 0.0),
shrinkWrap: true,
scrollDirection: Axis.vertical,
children: List.generate(
cards.length,
(index) {
cards[index].setIsUncovered(true);
cards[index].setIsClickable(false);
cards[index].setIndex(index);
cards[index].setParent(this);
return cards[index];
},
),
),
],
),
),
);
}
}
// ignore: must_be_immutable
class CardTile extends StatefulWidget {
String imagePath;
bool isClickable;
bool isUncovered;
int index;
_GameScreenState parent;
CardTile(
{Key key,
this.imagePath,
this.isClickable,
this.isUncovered,
this.index,
this.parent})
: super(key: key);
void setImagePath(String path) {
this.imagePath = path;
}
void setIsClickable(bool val) {
this.isClickable = val;
}
void setIsUncovered(bool val) {
this.isUncovered = val;
}
void setIndex(int val) {
this.index = val;
}
void setParent(_GameScreenState val) {
this.parent = val;
}
String getImagePath() {
return this.imagePath;
}
bool getIsClickable() {
return this.isClickable;
}
bool getIsUncovered() {
return this.isUncovered;
}
int getIndex() {
return this.index;
}
_GameScreenState getParent() {
return this.parent;
}
@override
_CardTileState createState() => _CardTileState();
}
class _CardTileState extends State<CardTile> {
@override
void initState() {
super.initState();
Timer(
Duration(seconds: 5),
() {
setState(() {
widget.setIsUncovered(false);
widget.setIsClickable(true);
});
},
);
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
if (widget.isClickable) {
print('clicked ' + widget.index.toString());
widget.parent.handleClick(this);
}
},
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
child: Container(
margin: EdgeInsets.all(5),
child: Container(
child: Image.asset(
widget.isUncovered ? widget.imagePath : 'assets/default1.png'),
),
),
),
);
}
}
【问题讨论】:
标签: flutter dart timer gesturedetector