【发布时间】:2021-09-27 17:17:15
【问题描述】:
所以我的计时器遇到了另一个问题。
我有一个大小合适的盒子,当我点击它时,我希望计时器将值从 5 分钟更改为 15 分钟(或者最好,当我第一次点击时,它会从 5 分钟> 10 分钟增加到第二次点击 15 分钟,第三次点击 20 分钟,第四次点击 25 分钟) 为此,计时器不应处于活动状态(用户只能在计时器未运行时更改它) - 但我遇到了“未定义名称'isRunning'”的问题。来自我在另一个小部件中的最终结果
这是我的代码(还有一个问题,目前计时器只显示秒,我怎样才能让它显示实际的 5 分钟,如 5:00)
class timeryypage extends State<timerry> {
static const maxSeconds = 5;
int seconds = maxSeconds;
Timer? timer;
void resetTimer() => setState(() => seconds = maxSeconds);
void startTimer({bool reset = true}) {
if (reset) {
resetTimer();
}
timer = Timer.periodic(Duration(seconds: 1), (_) {
//add here instead seconds say minutes/miliseconds
if (!mounted) // Putting this line of code with return under, fixed my issue i been having about mounted
return;
else if (seconds > 0) {
setState(() => seconds--);
} else {
stopTimer(reset: false);
}
});
}
void stopTimer({bool reset = true}) {
if (reset == mounted) {
resetTimer();
}
setState(() => timer?.cancel());
}
@override
Widget buildButtons() {
final isRunning = timer == null ? false : timer!.isActive;
final isCompleted = seconds == maxSeconds || seconds == 0;
return isRunning || !isCompleted
? Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ButtonWidget(
text: isRunning ? "Pause" : "Resume",
onClicked: () {
if (isRunning) {
stopTimer(reset: false);
} else {
startTimer(reset: false);
}
},
),
const SizedBox(width: 12),
ButtonWidget(text: "Cancel", onClicked: stopTimer)
],
)
: ButtonWidget(
text: "Start Timer!",
color: Colors.black,
backgroundColor: Colors.white,
onClicked: () {
startTimer();
},
);
}
Widget buildTimer() => SizedBox(
width: 200,
height: 200,
child: Stack(
fit: StackFit.expand,
children: [
CircularProgressIndicator(
value: seconds / maxSeconds,
//if you delete 1 - then it goes to other direction
valueColor: AlwaysStoppedAnimation(Colors.white),
strokeWidth: 12,
backgroundColor: Colors.greenAccent,
),
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
if (isRunning) {
print("do nothing");
} else {
const snackBar = SnackBar(content: Text('Tap'));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
print("tapped");
// later on i want to change timer from 5 minutes 10 minutes on first tap, then second tap to 15 minutes
}
},
child: Center(child: buildTime()),
),
//Center(child: buildTime()),
],
),
);
Widget buildTime() {
if (seconds == 0) {
return Icon(Icons.done, color: Colors.greenAccent, size: 112);
} else {
return Text(
"$seconds",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white,
fontSize: 80,
),
);
}
}
非常感谢您的帮助!
编辑添加额外代码:
bool get isRunning => _timer?.isActive ?? false;
int _seconds = 00;
int _minutes = setminutes;
static const setminutes = 25;
Timer? _timer;
var f = NumberFormat("00");
void _stopTimer({bool reset = true}) {
if (reset == true) {
resetTimer();
}
setState(() => _timer?.cancel());
;
}
void resetTimer() => setState(() => _minutes = setminutes);
void _startTimer({bool reset = true}) {
if (reset) {
resetTimer();
}
if (_timer != null) {
_stopTimer();
}
if (_minutes > 0) {
_seconds = _minutes * 60;
}
if (_seconds > 60) {
_minutes = (_seconds / 60).floor();
_seconds -= (_minutes * 60);
}
_timer = Timer.periodic(Duration(seconds: 1), (_) {
if (!mounted)
return;
else if (_seconds > 0) {
setState(() => _seconds--);
}
setState(() {
if (_seconds > 0) {
_seconds--;
} else {
if (_minutes > 0) {
_seconds = 59;
_minutes--;
} else {
_stopTimer(reset: false);
}
}
});
});
}
@override
Widget buildButtons() {
//final isRunning = timer == null ? false : timer!.isActive;
final isCompleted = _minutes == setminutes || _seconds == 0;
return isRunning || !isCompleted
? Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ButtonWidget(
text: isRunning ? "Pause" : "Resume",
onClicked: () {
if (isRunning) {
_stopTimer(reset: false);
} else {
_startTimer(reset: false);
}
},
),
const SizedBox(width: 12),
ButtonWidget(
text: "Cancel",
onClicked: () {
_stopTimer(reset: true);
})
],
)
: ButtonWidget(
text: "Start Timer!",
color: Colors.black,
backgroundColor: Colors.white,
onClicked: () {
_startTimer();
},
);
}
【问题讨论】:
-
isRunning是buildButtons函数的局部变量。如果你想在那个函数之外引用它,你应该做一个 getter(你可以稍微简化一下):bool get isRunning => timer?.isActive ?? false;. -
非常感谢!有用!。你知道我怎么能做到,而不是在 5 秒内显示“5”,而是显示 5:00(5 分钟)?是否有一些快速修复我的代码或者我必须以某种方式重写大部分代码?
-
感谢您的帮助!我有错误,因为它告诉我“方法'padLeft'没有为'int'类型定义。”任何想法:?
-
谢谢!作品。但是,当我将静态 const maxSeconds 例如更改为 120(2 分钟)时,它显示 2:120,我该如何编辑代码,以便当我输入 120 秒时它会显示 2:00 :?我认为我的整个代码都需要重写:|
-
糟糕,抱歉。我只是写一个答案,以便我可以纠正我的错误。 =)
标签: android flutter dart timer