I want to use a time countdown timer for date based on day, hour, minute and second. I found a code that does this for me.
This is the code:
import 'dart:async';
import 'package:flutter/material.dart';
class Time extends StatefulWidget {
const Time({Key? key}) : super(key: key);
@override
State<Time> createState() => _TimeState();
}
final eventTime = DateTime.parse('2024-01-10 03:41:00');
class _TimeState extends State<Time> {
static const duration = Duration(seconds: 1);
int timeDiff = eventTime.difference(DateTime.now()).inSeconds;
late Timer timer;
bool isActive = true;
void handleTick() {
if (timeDiff > 0) {
if (isActive) {
setState(() {
if (eventTime != DateTime.now()) {
timeDiff = timeDiff - 1;
} else {
print('Times up!');
//Do something
}
});
}
}
}
@override
void dispose() {
super.dispose();
}
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
timer = Timer.periodic(duration, (Timer t) {
handleTick();
});
int days = timeDiff ~/ (24 * 60 * 60) % 24;
int hours = timeDiff ~/ (60 * 60) % 24;
int minutes = (timeDiff ~/ 60) % 60;
int seconds = timeDiff % 60;
return Scaffold(
appBar: AppBar(
backgroundColor: const Color(0x00fafafa),
elevation: 0,
leading: const BackButton(color: Colors.deepOrange,),
),
body: SingleChildScrollView(
child: Column(
children: [
Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
LabelText(
label: 'DAYS', value: days.toString().padLeft(2, '0')),
LabelText(
label: 'HRS', value: hours.toString().padLeft(2, '0')),
LabelText(
label: 'MIN', value: minutes.toString().padLeft(2, '0')),
LabelText(
label: 'SEC', value: seconds.toString().padLeft(2, '0')),
],
),
],
),
],
),
)
);
}
}
class LabelText extends StatelessWidget {
const LabelText({super.key, required this.label, required this.value});
final String label;
final String value;
@override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.symmetric(horizontal: 5),
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
color: Colors.grey,
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
value,
style: const TextStyle(
color: Colors.white, fontSize: 20, fontWeight: FontWeight.bold),
),
Text(
label,
style: const TextStyle(
color: Colors.white70,
),
),
],
),
);
}
}
But these codes cannot show the number of remaining days correctly.
I want it to show the number of days and hours left.
And another problem that exists is that the counting speed is very high and it is not compatible with real time
2
Answers
Please do edit the timediff variable to the following in order to get the remaining days:
In order to get the remaining days, please do use the following way:
In order match the speed of the realtime. Please do use the Timer.Periodic() method available in flutter. Which provides a option of callback exposed where you can handle the BL for the application.
start timer in initState.
what happening in your code is timer variable is getting assigned Timer multiple time. causing multiple function call for handleTick().
like when SetState() is called in handleTick() method it trigger the build method to be called and whole widget get rebuilt.
but here timer get a new Timer.periodic() assigned
but old Timer.periodic() is still running and handleTick() is being called and timeDiff is keep decreasing and after Timer.periodic() will be assigned to timer variable causing all timer running in parallel and also calling handleTick() multiple times
instead of every 1 second.