mirror of
https://github.com/Iconica-Development/flutter_availability.git
synced 2025-05-19 05:03:44 +02:00
fix: close keyboard for break duration when tapping outside inputfield
This commit is contained in:
parent
e37164831b
commit
ae950ce5df
1 changed files with 69 additions and 21 deletions
|
@ -1,4 +1,5 @@
|
|||
import "package:flutter/material.dart";
|
||||
import "package:flutter/services.dart";
|
||||
import "package:flutter_availability/src/util/scope.dart";
|
||||
|
||||
/// An input field for time selection
|
||||
|
@ -56,7 +57,7 @@ class TimeInputField extends StatelessWidget {
|
|||
}
|
||||
|
||||
/// An input field for giving a duration in minutes
|
||||
class DurationInputField extends StatelessWidget {
|
||||
class DurationInputField extends StatefulWidget {
|
||||
///
|
||||
const DurationInputField({
|
||||
required this.initialValue,
|
||||
|
@ -70,6 +71,51 @@ class DurationInputField extends StatelessWidget {
|
|||
///
|
||||
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
|
||||
Widget build(BuildContext context) {
|
||||
var theme = Theme.of(context);
|
||||
|
@ -77,28 +123,30 @@ class DurationInputField extends StatelessWidget {
|
|||
var options = availabilityScope.options;
|
||||
var translations = options.translations;
|
||||
|
||||
void onFieldChanged(String value) {
|
||||
var duration = int.tryParse(value);
|
||||
if (duration != null) {
|
||||
onDurationChanged(Duration(minutes: duration));
|
||||
} else {
|
||||
onDurationChanged(null);
|
||||
}
|
||||
}
|
||||
|
||||
return TextFormField(
|
||||
decoration: InputDecoration(
|
||||
labelText: translations.time,
|
||||
labelStyle: theme.inputDecorationTheme.hintStyle,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
return Focus(
|
||||
onFocusChange: (hasFocus) {
|
||||
if (hasFocus) {
|
||||
_showOverlay(context);
|
||||
} else {
|
||||
_removeOverlay();
|
||||
}
|
||||
},
|
||||
child: TextFormField(
|
||||
decoration: InputDecoration(
|
||||
labelText: translations.time,
|
||||
labelStyle: theme.inputDecorationTheme.hintStyle,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
suffixIcon: const Icon(Icons.access_time),
|
||||
),
|
||||
suffixIcon: const Icon(Icons.access_time),
|
||||
keyboardType: TextInputType.number,
|
||||
style: options.textStyles.inputFieldTextStyle,
|
||||
onChanged: _onFieldChanged,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.digitsOnly,
|
||||
],
|
||||
),
|
||||
initialValue: initialValue?.inMinutes.toString(),
|
||||
keyboardType: TextInputType.number,
|
||||
style: options.textStyles.inputFieldTextStyle,
|
||||
onChanged: onFieldChanged,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue