fix: close keyboard for break duration when tapping outside inputfield

This commit is contained in:
Freek van de Ven 2024-07-25 07:35:16 +02:00
parent 47b179dc4d
commit 959500372e

View file

@ -1,4 +1,5 @@
import "package:flutter/material.dart"; import "package:flutter/material.dart";
import "package:flutter/services.dart";
import "package:flutter_availability/src/util/scope.dart"; import "package:flutter_availability/src/util/scope.dart";
/// An input field for time selection /// An input field for time selection
@ -56,7 +57,7 @@ class TimeInputField extends StatelessWidget {
} }
/// An input field for giving a duration in minutes /// An input field for giving a duration in minutes
class DurationInputField extends StatelessWidget { class DurationInputField extends StatefulWidget {
/// ///
const DurationInputField({ const DurationInputField({
required this.initialValue, required this.initialValue,
@ -70,6 +71,51 @@ class DurationInputField extends StatelessWidget {
/// ///
final void Function(Duration?) onDurationChanged; final void Function(Duration?) onDurationChanged;
@override
State<StatefulWidget> createState() => _DurationInputFieldState();
}
class _DurationInputFieldState extends State<DurationInputField> {
OverlayEntry? _overlayEntry;
@override
void dispose() {
_removeOverlay();
super.dispose();
}
void _onFieldChanged(String value) {
var duration = int.tryParse(value);
if (duration != null) {
widget.onDurationChanged(Duration(minutes: duration));
} else {
widget.onDurationChanged(null);
}
}
void _showOverlay(BuildContext context) {
_overlayEntry = _createOverlayEntry(context);
Overlay.of(context).insert(_overlayEntry!);
}
void _removeOverlay() {
_overlayEntry?.remove();
_overlayEntry = null;
}
OverlayEntry _createOverlayEntry(BuildContext context) => OverlayEntry(
builder: (context) => GestureDetector(
onTap: () {
FocusScope.of(context).unfocus();
_removeOverlay();
},
behavior: HitTestBehavior.translucent,
child: Container(
color: Colors.transparent,
),
),
);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var theme = Theme.of(context); var theme = Theme.of(context);
@ -77,16 +123,15 @@ class DurationInputField extends StatelessWidget {
var options = availabilityScope.options; var options = availabilityScope.options;
var translations = options.translations; var translations = options.translations;
void onFieldChanged(String value) { return Focus(
var duration = int.tryParse(value); onFocusChange: (hasFocus) {
if (duration != null) { if (hasFocus) {
onDurationChanged(Duration(minutes: duration)); _showOverlay(context);
} else { } else {
onDurationChanged(null); _removeOverlay();
} }
} },
child: TextFormField(
return TextFormField(
decoration: InputDecoration( decoration: InputDecoration(
labelText: translations.time, labelText: translations.time,
labelStyle: theme.inputDecorationTheme.hintStyle, labelStyle: theme.inputDecorationTheme.hintStyle,
@ -95,10 +140,13 @@ class DurationInputField extends StatelessWidget {
), ),
suffixIcon: const Icon(Icons.access_time), suffixIcon: const Icon(Icons.access_time),
), ),
initialValue: initialValue?.inMinutes.toString(),
keyboardType: TextInputType.number, keyboardType: TextInputType.number,
style: options.textStyles.inputFieldTextStyle, style: options.textStyles.inputFieldTextStyle,
onChanged: onFieldChanged, onChanged: _onFieldChanged,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
],
),
); );
} }
} }