I have built a working countdown clock that displays the time remaining in the format, hours:minutes:senconds. inside a stateful widget. that uses a fullscreen inkwell to start and stop it. What I want to do is transfer this code to a change notifier. (I already a change notifier setup ready to go called CountdownTimers) so i can see this countdown running from multiple pages on my app.
Here is the code for the working countdown clock in the stateful widget:
class ChessClock2 extends StatefulWidget {
const ChessClock2({Key? key}) : super(key: key);
@override
State<ChessClock2> createState() => _ChessClock2State();
}
class _ChessClock2State extends State<ChessClock2> {
static const countdownDuration = Duration(hours: 5, minutes: 10, seconds: 10);
Duration duration = Duration();
Timer? timer;
bool beenPressed = false;
@override
void initState() {
super.initState();
Reset();
}
void Reset() {
setState(() => duration = countdownDuration);
}
void AddTime() {
final minusSeconds = -1;
setState(() {
final seconds = duration.inSeconds + minusSeconds;
if (seconds < 0) {
timer?.cancel();
} else {
duration = Duration(seconds: seconds);
}
});
}
void StartTimer() {
timer = Timer.periodic(
Duration(seconds: 1),
(_) => AddTime(),
);
}
void StopTimer() {
setState(() => timer?.cancel());
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: InkWell(
onTap: () {
setState(() {
beenPressed = !beenPressed;
});
beenPressed ? StartTimer() : StopTimer();
},
child: Container(
width: double.infinity,
height: double.infinity,
decoration: BoxDecoration(
color: beenPressed ? kOrange : kBlueGrey900,
borderRadius: BorderRadius.circular(30),
),
child: Center(
child: TimeDisplay(),
),
),
),
),
);
}
Widget TimeDisplay() {
String twoDigits(int n) => n.toString().padLeft(2, '0');
final hours = twoDigits(
duration.inHours.remainder(60),
);
final minutes = twoDigits(
duration.inMinutes.remainder(60),
);
final seconds = twoDigits(
duration.inSeconds.remainder(60),
);
return Text(
'$hours:$minutes:$seconds',
style: TextStyle(fontSize: 50),
);
}
}
When I transfer the code over, I'm running into trouble because I can't use setState in the change notifier and I'm unsure how to translate the code to get it to work. so far, by moving the individual variables over as well as the widget TimDisplay, I'm able to get the timer to display correctly from the change notifier but am not sure how to get it to work from the change notifier. here is where I am now:
type hereclass ChessClock3 extends StatefulWidget {
const ChessClock3({Key? key}) : super(key: key);
@override
State<ChessClock3> createState() => _ChessClock3State();
}
class _ChessClock3State extends State<ChessClock3> {
@override
void initState() {
super.initState();
Reset();
}
void Reset() {
setState(() => duration = countdownDuration);
}
void AddTime() {
final minusSeconds = -1;
setState(() {
final seconds = duration.inSeconds + minusSeconds;
if (seconds < 0) {
timer?.cancel();
} else {
duration = Duration(seconds: seconds);
}
});
}
void StartTimer() {
timer = Timer.periodic(
Duration(seconds: 1),
(_) => AddTime(),
);
}
void StopTimer() {
setState(() => timer?.cancel());
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: InkWell(
onTap: () {
setState(() {
context.read<CountdownTimers>().BeenPressed();
});
context.read<CountdownTimers>().beenPressed
? StartTimer()
: StopTimer();
},
child: Container(
width: double.infinity,
height: double.infinity,
decoration: BoxDecoration(
color: context.watch<CountdownTimers>().beenPressed
? kKillTeamOrange
: kBlueGrey900,
borderRadius: BorderRadius.circular(30),
),
child: Center(
child: context.read<CountdownTimers>().TimeDisplay(),
),
),
),
),
);
}
}
class CountdownTimers with ChangeNotifier {
Duration _countdownDuration = Duration(hours: 5, minutes: 10, seconds: 10);
Duration _duration = Duration();
Timer? timer;
bool _beenPressed = false;
Duration get countdownDuration => _countdownDuration;
Duration get duration => _duration;
bool get beenPressed => _beenPressed;
void BeenPressed() {
_beenPressed = !_beenPressed;
}
Widget TimeDisplay() {
String twoDigits(int n) => n.toString().padLeft(2, '0');
final hours = twoDigits(
_duration.inHours.remainder(60),
);
final minutes = twoDigits(
_duration.inMinutes.remainder(60),
);
final seconds = twoDigits(
_duration.inSeconds.remainder(60),
);
return Text(
'$hours:$minutes:$seconds',
style: TextStyle(fontSize: 50),
);
}
}
If anyone can show me how to translate the code over It would be very much appreciated. thanks so much!