I'm building a Pomodoro timer in Flutter and want to automatically navigate to a different page when the timer completes. Here's my current setup:
Images:
StartPomodoro Page
Desired 'StartShortBreak' Page
Code:
so, if time is over in StartPomodoro I want to switch it to StartShortBreak automatically
class StartPomodoro extends StatefulWidget {
const StartPomodoro({Key? key}) : super(key: key);
@override
State<StartPomodoro> createState() => _StartPomodoro();
}
class _StartPomodoro extends State<StartPomodoro>
with TickerProviderStateMixin {
late AnimationController controller;
String get countText {
Duration count = controller.duration! * controller.value;
return controller.isDismissed
? '${controller.duration!.inHours.toString().padLeft(2, '0')}:${(controller.duration!.inMinutes % 60).toString().padLeft(2, '0')}:${(controller.duration!.inSeconds % 60).toString().padLeft(2, '0')}'
: '${count.inHours.toString().padLeft(2, '0')}:${(count.inMinutes % 60).toString().padLeft(2, '0')}:${(count.inSeconds % 60).toString().padLeft(2, '0')}';
}
double progress = 1.0;
bool Pomodoro = false;
void notify() {
if (countText == '00:00:00') {
FlutterRingtonePlayer.playNotification();
}
}
@override
void initState() {
super.initState();
controller = AnimationController(
vsync: this,
duration: Duration(seconds: 10),
);
controller.addListener(() {
notify();
if (controller.isAnimating) {
setState(() {
progress = controller.value;
});
} else {
setState(() {
progress = 1.0;
Pomodoro = false;
});
}
});
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
ThemeData themeData = Theme.of(context);
return Scaffold(
backgroundColor: Color(0xffF2B749),
body: GestureDetector(
onTap: () {
if (controller.isDismissed) {
showModalBottomSheet(
context: context,
builder: (context) => Container(
height: 300,
child: CupertinoTimerPicker(
initialTimerDuration: controller.duration!,
onTimerDurationChanged: (time) {
setState(() {
controller.duration = time;
});
},
),
),
);
}
},
child: AnimatedBuilder(
animation: controller,
builder: (context, child) {
return Stack(
children: <Widget>[
Align(
alignment: Alignment.bottomCenter,
child: Container(
color: Color(0xffD94530),
height:
controller.value * MediaQuery.of(context).size.height,
),
),
Padding(
padding: EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child:
Align(
alignment: FractionalOffset.bottomCenter,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
Pomodoro? "Time to work" : "Time to work",
style: TextStyle(
fontSize: 30,
color: Colors.white
),
),
Text(
countText,
style: TextStyle(
fontSize: 90.0,
color: Color(0xffF2F2F2),),
),
],
),
),
),
),
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
AnimatedBuilder(
animation: controller,
builder: (context, child) {
return Padding(
padding: EdgeInsets.symmetric(vertical: 2.0, horizontal: 15.0),
child: FloatingActionButton.extended(
backgroundColor: Color(0xffF2F2F2),
onPressed: () {
setState ((){
Pomodoro? "POMODORO" : "POMODORO";
});
if (controller.isAnimating)
controller.stop();
else {
controller.reverse(
from: controller.value == 0.0
? 1.0
: controller.value);
}
},
icon: Icon(
controller.isAnimating
? Icons.work_history
: Icons.emoji_food_beverage,
color: Color(0xff3B3B3B),),
label: Text(
controller.isAnimating
? "POMODORO"
: "POMODORO",
style: TextStyle(color: Color(0xff3B3B3B)),)),
);
}),
],
),
),
SizedBox(height: 10,),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
AnimatedBuilder(
animation: controller,
builder: (context, child) {
return Padding(
padding: EdgeInsets.symmetric(vertical: 2.0, horizontal: 15.0),
child: FloatingActionButton.extended(
backgroundColor: Color(0xffF2F2F2),
onPressed: () {
if (controller.isAnimating) {
controller.stop();
setState(() {
Pomodoro = false;
});
} else {
controller.reverse(
from: controller.value == 0 ? 1.0 : controller.value);
setState(() {
Pomodoro = true;
});
}
},
icon: Icon(
controller.isAnimating
? Icons.play_arrow
: Icons.pause,
color: Color(0xff3B3B3B),),
label: Text(
controller.isAnimating ? "PLAY" :"PAUSE",
style: TextStyle(color: Color(0xff3B3B3B)),)),
);
}),
SizedBox(width: 20,),
AnimatedBuilder(
animation: controller,
builder: (context, child) {
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: [
Padding(
padding: const EdgeInsets.fromLTRB(48.0, 2.0, 3.0, 4.0),
child: FloatingActionButton.extended(
backgroundColor: Color(0xffF2F2F2),
onPressed: () {
if (controller.isAnimating)
controller.reset();
else (controller.isAnimating);
controller.reset();
},
icon: Icon(Icons.refresh,
color: Color(0xff3B3B3B),),
label: Text("RESTART",
style: TextStyle(color:Color(0xff3B3B3B)),),),
),
],
),
);
}),
],
)
],
),
),
],
);
}),
),
);
}
}
StartShortBreak.dart
class StartShortBreak extends StatefulWidget {
const StartShortBreak({Key? key}) : super(key: key);
@override
State<StartShortBreak> createState() => _StartShortBreak();
}
class _StartShortBreak extends State<StartShortBreak>
with TickerProviderStateMixin {
late AnimationController controller;
String get countText {
Duration count = controller.duration! * controller.value;
return controller.isDismissed
? '${controller.duration!.inHours.toString().padLeft(2, '0')}:${(controller.duration!.inMinutes % 60).toString().padLeft(2, '0')}:${(controller.duration!.inSeconds % 60).toString().padLeft(2, '0')}'
: '${count.inHours.toString().padLeft(2, '0')}:${(count.inMinutes % 60).toString().padLeft(2, '0')}:${(count.inSeconds % 60).toString().padLeft(2, '0')}';
}
double progress = 1.0;
bool ShortBreak = false;
void notify() {
if (countText == '00:00:00') {
FlutterRingtonePlayer.playNotification();
}
}
@override
void initState() {
super.initState();
controller = AnimationController(
vsync: this,
duration: Duration(seconds: 10),
);
controller.addListener(() {
notify();
if (controller.isAnimating) {
setState(() {
progress = controller.value;
});
} else {
setState(() {
progress = 1.0;
ShortBreak = false;
});
}
});
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
ThemeData themeData = Theme.of(context);
return Scaffold(
backgroundColor: Color(0xffD94530),
body: GestureDetector(
onTap: () {
if (controller.isDismissed) {
showModalBottomSheet(
context: context,
builder: (context) => Container(
height: 300,
child: CupertinoTimerPicker(
initialTimerDuration: controller.duration!,
onTimerDurationChanged: (time) {
setState(() {
controller.duration = time;
});
},
),
),
);
}
},
child: AnimatedBuilder(
animation: controller,
builder: (context, child) {
return Stack(
children: <Widget>[
Align(
alignment: Alignment.bottomCenter,
child: Container(
color: Color(0xffF2B749),
height:
controller.value * MediaQuery.of(context).size.height,
),
),
Padding(
padding: EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child:
Align(
alignment: FractionalOffset.bottomCenter,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
ShortBreak? "Short Break" : "Short Break",
style: TextStyle(
fontSize: 30,
color: Colors.white
),
),
Text(
countText,
style: TextStyle(
fontSize: 90.0,
color: Color(0xffF2F2F2),),
),
],
),
),
),
),
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
AnimatedBuilder(
animation: controller,
builder: (context, child) {
return Padding(
padding: EdgeInsets.symmetric(vertical: 2.0, horizontal: 15.0),
child: FloatingActionButton.extended(
backgroundColor: Color(0xffF2F2F2),
onPressed: () {
setState ((){
ShortBreak? "Short Break" : "Short Break";
});
if (controller.isAnimating)
controller.stop();
else {
controller.reverse(
from: controller.value == 0.0
? 1.0
: controller.value);
}
},
icon: Icon(
controller.isAnimating
? Icons.emoji_food_beverage
: Icons.emoji_food_beverage,
color: Color(0xff3B3B3B),),
label: Text(
controller.isAnimating
? "Short Break"
: "Short Break",
style: TextStyle(color: Color(0xff3B3B3B)),)),
);
}),
],
),
),
SizedBox(height: 10,),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
AnimatedBuilder(
animation: controller,
builder: (context, child) {
return Padding(
padding: EdgeInsets.symmetric(vertical: 2.0, horizontal: 15.0),
child: FloatingActionButton.extended(
backgroundColor: Color(0xffF2F2F2),
onPressed: () {
if (controller.isAnimating) {
controller.stop();
setState(() {
ShortBreak = false;
});
} else {
controller.reverse(
from: controller.value == 0 ? 1.0 : controller.value);
setState(() {
ShortBreak = true;
});
}
},
icon: Icon(
controller.isAnimating
? Icons.play_arrow
: Icons.pause,
color: Color(0xff3B3B3B),),
label: Text(
controller.isAnimating ? "PLAY" :"PAUSE",
style: TextStyle(color: Color(0xff3B3B3B)),)),
);
}),
SizedBox(width: 20,),
AnimatedBuilder(
animation: controller,
builder: (context, child) {
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: [
Padding(
padding: const EdgeInsets.fromLTRB(48.0, 2.0, 3.0, 4.0),
child: FloatingActionButton.extended(
backgroundColor: Color(0xffF2F2F2),
onPressed: () {
if (controller.isAnimating)
controller.reset();
else (controller.isAnimating);
controller.reset();
},
icon: Icon(Icons.refresh,
color: Color(0xff3B3B3B),),
label: Text("RESTART",
style: TextStyle(color:Color(0xff3B3B3B)),),),
),
],
),
);
}),
],
)
],
),
),
],
);
}),
),
);
}
}
What I've Tried:
Specific Request:
Could you please guide me on how to:
StartPomodoro
reaches zero.StartPomodoro
to StartShortBreak
upon timer completion.void notify() {
if (countText == '00:00:00') {
FlutterRingtonePlayer.playNotification();
Navigator.pushReplacement(context, MaterialPageRoute(builder: (context)=>
StartShortBreak()));
});
}
}
You have a notify method which is triggered when the time is 0. You can add navigator in that method