So i have made a timer and it fully works for the most part. It has start, stop and pause buttons which works. Starting the timer works as long as i have input something in each of the three textfields (hour, minute and seconds) but as soon as one of them has no input (null) the timer wont start and spits out the error code
Exception caught by Gesture Invalid number (at character 1).
I have tried to put ?? 0 at lots of places in the code but i am quite new at this so that might be a totally dumb solution and it wont work.
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_plugg/main.dart';
class TimerView extends StatefulWidget {
@override
_TimerViewState createState() => _TimerViewState();
}
class _TimerViewState extends State<TimerView> with TickerProviderStateMixin {
TextEditingController _minuteController = TextEditingController();
TextEditingController _hourController = TextEditingController();
TextEditingController _secondController = TextEditingController();
AnimationController _controller;
Animation<int> _animation;
@override
void dispose() {
_controller.dispose();
super.dispose();
}
void _pauseTimer() {
_controller.stop();
}
void _stopTimer() {
_controller.reset();
}
void _startTimer() {
int timerInput = int.parse(_hourController.text) * 3600 +
int.parse(_minuteController.text) * 60 +
int.parse(_secondController.text);
_controller = AnimationController(
vsync: this,
duration: Duration(seconds: timerInput),
);
_animation = StepTween(begin: timerInput, end: 0).animate(_controller)
..addListener(() {
_setTimerValues();
});
_controller.forward();
}
void _setTimerValues() {
setState(() {
print(_animation.value);
_hourController.text = (_animation.value ~/ 3600).toString();
_minuteController.text = ((_animation.value % 3600) ~/ 60).toString();
_secondController.text = (_animation.value % 60).toString();
});
}
Widget _textInput({TextEditingController controller}) {
return Container(
width: 100,
height: 60,
child: TextField(
showCursor: false,
enableInteractiveSelection: false,
controller: controller,
style: TextStyle(
fontSize: 60,
),
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
keyboardType: TextInputType.number,
textAlign: TextAlign.center,
maxLength: 2,
decoration: InputDecoration(
contentPadding: EdgeInsets.zero,
hintStyle: TextStyle(color: Colors.grey),
counterText: "",
hintMaxLines: 1,
hintText: "00",
border: InputBorder.none,
),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
drawer: PersistentDrawer(currentPage: "Timer"),
appBar: AppBar(
title: Text("Timer"),
),
body: Column(
children: [
SizedBox(height: 80),
Row(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.center,
children: [
_textInput(
controller: _hourController,
),
Text(
"h",
style: TextStyle(fontSize: 24),
),
_textInput(
controller: _minuteController,
),
Text(
"m",
style: TextStyle(fontSize: 24),
),
_textInput(controller: _secondController),
Text(
"s",
style: TextStyle(fontSize: 24),
)
],
),
SizedBox(
height: 60,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(right: 15),
child: ElevatedButton(
onPressed: () {
_controller?.isAnimating ?? false ? _pauseTimer() : _startTimer();
setState(() {});
},
child: _controller?.isAnimating ?? false
? Text("Pause Timer")
: Text("Start Timer"),
),
),
Padding(
padding: const EdgeInsets.only(left: 15),
child: ElevatedButton(
onPressed: _stopTimer,
child: Text("Stop Timer"),),
)
],
),
],
),
);
}
}