diameter/lib/components/forms/number_form_field.dart

130 lines
3.9 KiB
Dart
Raw Normal View History

2022-03-21 00:07:29 +00:00
import 'package:diameter/components/repeat_on_hold_button.dart';
import 'package:diameter/utils/utils.dart';
import 'package:flutter/material.dart';
class NumberFormField extends StatefulWidget {
final TextEditingController controller;
final double min;
final double? max;
final double step;
final String label;
final String? suffix;
final void Function(double?) onChanged;
final bool readOnly;
final bool showSteppers;
final bool autoRoundToMultipleOfStep;
final String? Function(String?)? validator;
const NumberFormField({
Key? key,
required this.controller,
required this.label,
required this.onChanged,
this.suffix,
this.min = 0,
this.max,
this.step = 1,
this.readOnly = false,
this.showSteppers = true,
this.autoRoundToMultipleOfStep = false,
this.validator,
}) : super(key: key);
@override
_NumberFormFieldState createState() => _NumberFormFieldState();
}
class _NumberFormFieldState extends State<NumberFormField> {
int precision = 1;
@override
void initState() {
super.initState();
precision = Utils.getFractionDigitsLength(widget.step) + 1;
}
bool onIncrease() {
double? currentValue = double.tryParse(widget.controller.text);
if (currentValue != null &&
(widget.max == null || currentValue + widget.step <= widget.max!)) {
widget.onChanged(
Utils.addDoublesWithPrecision(currentValue, widget.step, precision));
setState(() {});
return true;
}
return false;
}
bool onDecrease() {
double? currentValue = double.tryParse(widget.controller.text);
if (currentValue != null && (currentValue - widget.step >= widget.min)) {
widget.onChanged(
Utils.addDoublesWithPrecision(currentValue, -widget.step, precision));
setState(() {});
return true;
}
return false;
}
@override
Widget build(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
widget.showSteppers
? RepeatOnHoldButton(
onTap: onDecrease,
child: IconButton(
onPressed: double.tryParse(widget.controller.text) != null &&
(double.parse(widget.controller.text) - widget.step >=
widget.min)
? onDecrease
: null,
icon: const Icon(Icons.remove),
),
)
: Container(),
2022-03-21 00:08:05 +00:00
Flexible(
2022-03-21 00:07:29 +00:00
child: TextFormField(
readOnly: widget.readOnly,
controller: widget.controller,
decoration: InputDecoration(
labelText: widget.label,
suffixText: widget.suffix,
),
keyboardType: TextInputType.numberWithOptions(
decimal: widget.step > 0 && widget.step < 1,
signed: widget.min.isNegative),
onChanged: (input) async {
await Future.delayed(const Duration(seconds: 1));
double? value = double.tryParse(input);
if (widget.autoRoundToMultipleOfStep) {
value = value != null ? Utils.roundToMultipleOfBase(value, widget.step) : null;
}
widget.onChanged(value);
},
validator: widget.validator,
),
),
widget.showSteppers
? RepeatOnHoldButton(
onTap: onIncrease,
child: IconButton(
onPressed: double.tryParse(widget.controller.text) != null &&
(widget.max == null ||
double.parse(widget.controller.text) +
widget.step <=
widget.max!)
? onIncrease
: null,
icon: const Icon(Icons.add),
),
)
: Container(),
],
);
}
}