Compare commits
3 Commits
d2e3b158cb
...
17c92496a9
| Author | SHA1 | Date | |
|---|---|---|---|
| 17c92496a9 | |||
| 8872ec0889 | |||
| c8cc5861ad |
262
lib/widgets/duration_picker.dart
Normal file
262
lib/widgets/duration_picker.dart
Normal file
@@ -0,0 +1,262 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class DurationPicker extends StatefulWidget {
|
||||||
|
const DurationPicker({
|
||||||
|
super.key,
|
||||||
|
required this.onChangedCallback,
|
||||||
|
required this.width,
|
||||||
|
required this.height,
|
||||||
|
});
|
||||||
|
|
||||||
|
final void Function(Duration duration) onChangedCallback;
|
||||||
|
final double width;
|
||||||
|
final double height;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<DurationPicker> createState() => _DurationPickerState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DurationPickerState extends State<DurationPicker> {
|
||||||
|
String _timeString = '';
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
width: widget.width,
|
||||||
|
height: widget.height / 4,
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
_timeString.padLeft(4, '0').substring(0, 2),
|
||||||
|
style: Theme.of(context).textTheme.displayMedium,
|
||||||
|
),
|
||||||
|
Padding(padding: EdgeInsets.only(left: 5)),
|
||||||
|
Text(
|
||||||
|
'h',
|
||||||
|
style:
|
||||||
|
Theme.of(context).textTheme.bodyLarge!.copyWith(height: 2),
|
||||||
|
),
|
||||||
|
Padding(padding: EdgeInsets.only(left: 10)),
|
||||||
|
Text(
|
||||||
|
_timeString.padLeft(4, '0').substring(2, 4),
|
||||||
|
style: Theme.of(context).textTheme.displayMedium,
|
||||||
|
),
|
||||||
|
Padding(padding: EdgeInsets.only(left: 5)),
|
||||||
|
Text(
|
||||||
|
'm',
|
||||||
|
style:
|
||||||
|
Theme.of(context).textTheme.bodyLarge!.copyWith(height: 2),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(padding: EdgeInsets.only(top: 10)),
|
||||||
|
Row(
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
width: widget.width / 3,
|
||||||
|
height: widget.height / 4,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(8, 0, 8, 8),
|
||||||
|
child: ElevatedButton(
|
||||||
|
style: _buttonTheme,
|
||||||
|
onPressed: () => _addTime(7),
|
||||||
|
child: _getTextWidget('7'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: widget.width / 3,
|
||||||
|
height: widget.height / 4,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(8, 0, 8, 8),
|
||||||
|
child: ElevatedButton(
|
||||||
|
style: _buttonTheme,
|
||||||
|
onPressed: () => _addTime(8),
|
||||||
|
child: _getTextWidget('8'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: widget.width / 3,
|
||||||
|
height: widget.height / 4,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(8, 0, 8, 8),
|
||||||
|
child: ElevatedButton(
|
||||||
|
style: _buttonTheme,
|
||||||
|
onPressed: () => _addTime(9),
|
||||||
|
child: _getTextWidget('9'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
width: widget.width / 3,
|
||||||
|
height: widget.height / 4,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(8, 0, 8, 8),
|
||||||
|
child: ElevatedButton(
|
||||||
|
style: _buttonTheme,
|
||||||
|
onPressed: () => _addTime(4),
|
||||||
|
child: _getTextWidget('4'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: widget.width / 3,
|
||||||
|
height: widget.height / 4,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(8, 0, 8, 8),
|
||||||
|
child: ElevatedButton(
|
||||||
|
style: _buttonTheme,
|
||||||
|
onPressed: () => _addTime(5),
|
||||||
|
child: _getTextWidget('5'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: widget.width / 3,
|
||||||
|
height: widget.height / 4,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(8, 0, 8, 8),
|
||||||
|
child: ElevatedButton(
|
||||||
|
style: _buttonTheme,
|
||||||
|
onPressed: () => _addTime(6),
|
||||||
|
child: _getTextWidget('6'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
width: widget.width / 3,
|
||||||
|
height: widget.height / 4,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(8, 0, 8, 8),
|
||||||
|
child: ElevatedButton(
|
||||||
|
style: _buttonTheme,
|
||||||
|
onPressed: () => _addTime(1),
|
||||||
|
child: _getTextWidget('1'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: widget.width / 3,
|
||||||
|
height: widget.height / 4,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(8, 0, 8, 8),
|
||||||
|
child: ElevatedButton(
|
||||||
|
style: _buttonTheme,
|
||||||
|
onPressed: () => _addTime(2),
|
||||||
|
child: _getTextWidget('2'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: widget.width / 3,
|
||||||
|
height: widget.height / 4,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(8, 0, 8, 8),
|
||||||
|
child: ElevatedButton(
|
||||||
|
style: _buttonTheme,
|
||||||
|
onPressed: () => _addTime(3),
|
||||||
|
child: _getTextWidget('3'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
width: widget.width / 3,
|
||||||
|
height: widget.height / 4,
|
||||||
|
child: Padding(padding: EdgeInsets.all(0)),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: widget.width / 3,
|
||||||
|
height: widget.height / 4,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(8, 0, 8, 8),
|
||||||
|
child: ElevatedButton(
|
||||||
|
style: _buttonTheme,
|
||||||
|
onPressed: () => _addTime(0),
|
||||||
|
child: _getTextWidget('0'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: widget.width / 3,
|
||||||
|
height: widget.height / 4,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(8, 0, 8, 8),
|
||||||
|
child: ElevatedButton(
|
||||||
|
style: _buttonTheme,
|
||||||
|
onPressed: _removeTime,
|
||||||
|
child: Icon(
|
||||||
|
Icons.backspace,
|
||||||
|
size: 24,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Text _getTextWidget(String text) {
|
||||||
|
return Text(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _addTime(int time) {
|
||||||
|
if (_timeString.length >= 4) return;
|
||||||
|
if (_timeString.isEmpty && time == 0) return;
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
_timeString += time.toString();
|
||||||
|
});
|
||||||
|
|
||||||
|
widget.onChangedCallback(_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _removeTime() {
|
||||||
|
if (_timeString.isEmpty) return;
|
||||||
|
setState(() {
|
||||||
|
_timeString = _timeString.substring(0, _timeString.length - 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
widget.onChangedCallback(_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
Duration get _duration {
|
||||||
|
return Duration(
|
||||||
|
hours: int.parse(_timeString.padLeft(4, '0').substring(0, 2)),
|
||||||
|
minutes: int.parse(_timeString.padLeft(4, '0').substring(2, 4)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ButtonStyle get _buttonTheme => ElevatedButton.styleFrom(
|
||||||
|
textStyle: Theme.of(context).textTheme.displaySmall,
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user