如何在手势点击时更改计时器的值?
How to change value of timer on gesture tap?
所以我 运行 我的计时器出现了另一个问题。
我有一个大小不一的盒子,当我点击它时,我希望计时器的值从 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();
},
);
}
您的 buildTime
函数根据秒数创建一个 Text
小部件。如果您想以其他方式格式化它,您需要自己将秒数格式化为 String
。例如:
var minutes = seconds ~/ 60;
var remainderSeconds = seconds % 60;
return Text('$minutes:${remainderSeconds.toString().padLeft(2, '0')}',
...);
另见:
- Flutter/Dart - Format Duration to show just Minutes, Seconds and Milliseconds?
所以我 运行 我的计时器出现了另一个问题。
我有一个大小不一的盒子,当我点击它时,我希望计时器的值从 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();
},
);
}
您的 buildTime
函数根据秒数创建一个 Text
小部件。如果您想以其他方式格式化它,您需要自己将秒数格式化为 String
。例如:
var minutes = seconds ~/ 60;
var remainderSeconds = seconds % 60;
return Text('$minutes:${remainderSeconds.toString().padLeft(2, '0')}',
...);
另见:
- Flutter/Dart - Format Duration to show just Minutes, Seconds and Milliseconds?