Skip to content

Commit d00ddac

Browse files
committed
Using simpler method of date and time picker dialogs - works with mobile too.
1 parent cf6041c commit d00ddac

10 files changed

+89
-170
lines changed

.flutter-plugins

Lines changed: 0 additions & 6 deletions
This file was deleted.

.flutter-plugins-dependencies

Lines changed: 0 additions & 1 deletion
This file was deleted.

.run/tests in test.run.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<component name="ProjectRunConfigurationManager">
2+
<configuration default="false" name="tests in test" type="FlutterTestConfigType" factoryName="Flutter Test" nameIsGenerated="true">
3+
<option name="testDir" value="$PROJECT_DIR$/test" />
4+
<option name="useRegexp" value="false" />
5+
<option name="additionalArgs" value="" />
6+
<method v="2" />
7+
</configuration>
8+
</component>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<component name="ProjectRunConfigurationManager">
2+
<configuration default="false" name="tests in vsc_datetime_field_test.dart - Update Goldens" type="FlutterTestConfigType" factoryName="Flutter Test">
3+
<option name="testFile" value="$PROJECT_DIR$/test/vsc_datetime_field_test.dart" />
4+
<option name="useRegexp" value="false" />
5+
<option name="additionalArgs" value="--update-goldens" />
6+
<method v="2" />
7+
</configuration>
8+
</component>
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<component name="ProjectRunConfigurationManager">
2+
<configuration default="false" name="tests in vsc_datetime_field_test.dart" type="FlutterTestConfigType" factoryName="Flutter Test" nameIsGenerated="true">
3+
<option name="testFile" value="$PROJECT_DIR$/test/vsc_datetime_field_test.dart" />
4+
<option name="useRegexp" value="false" />
5+
<option name="additionalArgs" value="" />
6+
<method v="2" />
7+
</configuration>
8+
</component>

example/pubspec.lock

Lines changed: 1 addition & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -62,54 +62,6 @@ packages:
6262
description: flutter
6363
source: sdk
6464
version: "0.0.0"
65-
flutter_keyboard_visibility:
66-
dependency: transitive
67-
description:
68-
name: flutter_keyboard_visibility
69-
sha256: "86b71bbaffa38e885f5c21b1182408b9be6951fd125432cf6652c636254cef2d"
70-
url: "https://pub.dev"
71-
source: hosted
72-
version: "5.4.0"
73-
flutter_keyboard_visibility_linux:
74-
dependency: transitive
75-
description:
76-
name: flutter_keyboard_visibility_linux
77-
sha256: "6fba7cd9bb033b6ddd8c2beb4c99ad02d728f1e6e6d9b9446667398b2ac39f08"
78-
url: "https://pub.dev"
79-
source: hosted
80-
version: "1.0.0"
81-
flutter_keyboard_visibility_macos:
82-
dependency: transitive
83-
description:
84-
name: flutter_keyboard_visibility_macos
85-
sha256: c5c49b16fff453dfdafdc16f26bdd8fb8d55812a1d50b0ce25fc8d9f2e53d086
86-
url: "https://pub.dev"
87-
source: hosted
88-
version: "1.0.0"
89-
flutter_keyboard_visibility_platform_interface:
90-
dependency: transitive
91-
description:
92-
name: flutter_keyboard_visibility_platform_interface
93-
sha256: e43a89845873f7be10cb3884345ceb9aebf00a659f479d1c8f4293fcb37022a4
94-
url: "https://pub.dev"
95-
source: hosted
96-
version: "2.0.0"
97-
flutter_keyboard_visibility_web:
98-
dependency: transitive
99-
description:
100-
name: flutter_keyboard_visibility_web
101-
sha256: d3771a2e752880c79203f8d80658401d0c998e4183edca05a149f5098ce6e3d1
102-
url: "https://pub.dev"
103-
source: hosted
104-
version: "2.0.0"
105-
flutter_keyboard_visibility_windows:
106-
dependency: transitive
107-
description:
108-
name: flutter_keyboard_visibility_windows
109-
sha256: fc4b0f0b6be9b93ae527f3d527fb56ee2d918cd88bbca438c478af7bcfd0ef73
110-
url: "https://pub.dev"
111-
source: hosted
112-
version: "1.0.0"
11365
flutter_lints:
11466
dependency: "direct dev"
11567
description:
@@ -123,11 +75,6 @@ packages:
12375
description: flutter
12476
source: sdk
12577
version: "0.0.0"
126-
flutter_web_plugins:
127-
dependency: transitive
128-
description: flutter
129-
source: sdk
130-
version: "0.0.0"
13178
intl:
13279
dependency: transitive
13380
description:
@@ -184,14 +131,6 @@ packages:
184131
url: "https://pub.dev"
185132
source: hosted
186133
version: "1.8.2"
187-
plugin_platform_interface:
188-
dependency: transitive
189-
description:
190-
name: plugin_platform_interface
191-
sha256: dbf0f707c78beedc9200146ad3cb0ab4d5da13c246336987be6940f026500d3a
192-
url: "https://pub.dev"
193-
source: hosted
194-
version: "2.1.3"
195134
sky_engine:
196135
dependency: transitive
197136
description: flutter
@@ -262,4 +201,4 @@ packages:
262201
version: "0.0.1"
263202
sdks:
264203
dart: ">=2.18.0 <3.0.0"
265-
flutter: ">=1.20.0"
204+
flutter: ">=1.17.0"

lib/vsc_datetime_field.dart

Lines changed: 54 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,10 @@
11
import 'dart:async';
2-
import 'dart:io';
32

4-
import 'package:flutter/foundation.dart';
53
import 'package:flutter/material.dart';
64
import 'package:flutter/services.dart';
7-
import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart';
85
import 'package:intl/intl.dart' hide TextDirection;
96
import 'package:vsc_datetime_field/datetime_parser.dart';
107

11-
final _kbdSupportedPlatform = (kIsWeb || Platform.isAndroid || Platform.isIOS);
12-
13-
// Unfortunately stolen from flutter/lib/src/material/calendar_date_picker.dart
14-
const double _dayPickerRowHeight = 42.0;
15-
const int _maxDayPickerRowCount = 6; // A 31 day month that starts on Saturday.
16-
// One extra row for the day-of-week header.
17-
const double _maxDayPickerHeight =
18-
_dayPickerRowHeight * (_maxDayPickerRowCount + 1);
19-
// Value is from flutter/lib/src/material/date_picker.dart:
20-
const _pickerWidth = 330.0;
21-
228
final _yearSuffixRegexp = RegExp(r'[-/]y+');
239

2410
const _timePatterns24h = [
@@ -41,16 +27,6 @@ const _timePatternsAmPm = [
4127

4228
enum VscDatetimeFieldType { date, datetime, time }
4329

44-
/*
45-
* TODO
46-
* - Sometimes there's just not enough room with the kbd open on mobile. Don't show any picker in this case.
47-
* But if the mobile kbd closes, recalculate available size
48-
* - Sometimes on mobile the screen doesn't scroll with the kbd up, even though the example has a scroll widget,
49-
* it doesn't have enough height to perform scrolling.
50-
* - Maybe on mobile if there is not enough height, don't show the picker but if the calendar icon is tapped,
51-
* show the dialog instead.
52-
*/
53-
5430
class VscDatetimeField extends StatefulWidget {
5531
/// Type of field desired.
5632
final VscDatetimeFieldType type;
@@ -245,11 +221,6 @@ class VscDatetimeFieldState extends State<VscDatetimeField> {
245221
widget.textFieldConfiguration.focusNode ?? _focusNode;
246222
late VoidCallback _focusNodeListener;
247223

248-
// Keyboard detection
249-
final Stream<bool>? _keyboardVisibility =
250-
(_kbdSupportedPlatform) ? KeyboardVisibilityController().onChange : null;
251-
late StreamSubscription<bool>? _keyboardVisibilitySubscription;
252-
253224
final _textFieldGlobalKey = GlobalKey();
254225

255226
DateTime? _value;
@@ -278,7 +249,6 @@ class VscDatetimeFieldState extends State<VscDatetimeField> {
278249

279250
@override
280251
void dispose() {
281-
_keyboardVisibilitySubscription?.cancel();
282252
_effectiveFocusNode.removeListener(_focusNodeListener);
283253
_focusNode.dispose();
284254
_textEditingController.dispose();
@@ -364,18 +334,11 @@ class VscDatetimeFieldState extends State<VscDatetimeField> {
364334
Future<void> _openPicker() async {
365335
switch (widget.type) {
366336
case VscDatetimeFieldType.date:
367-
case VscDatetimeFieldType.datetime:
368-
final selected = await showDatePicker(
369-
context: context,
370-
initialDate: _value ?? DateTime.now(),
371-
firstDate: widget.minValue,
372-
lastDate: widget.maxValue,
373-
);
374-
337+
final selected = await _showCustomizedDatePicker();
375338
_effectiveFocusNode.requestFocus();
376339

377340
if (selected != null) {
378-
// Modify the field's DateTime, sans the time component.
341+
// Modify the field's DateTime date component.
379342
final currValue = _value ?? testableNow();
380343
_setValue(
381344
DateTime(
@@ -391,30 +354,39 @@ class VscDatetimeFieldState extends State<VscDatetimeField> {
391354
setTextAndMoveCursorToEnd: true,
392355
);
393356
}
394-
395357
break;
358+
case VscDatetimeFieldType.datetime:
359+
final selectedDate = await _showCustomizedDatePicker();
360+
if (selectedDate == null) break;
396361

397-
case VscDatetimeFieldType.time:
398-
final selected = await showTimePicker(
399-
context: context,
400-
initialTime: TimeOfDay.now(),
401-
// TODO
402-
// initialDate: _value ?? DateTime.now(),
403-
// firstDate: widget.minValue,
404-
// lastDate: widget.maxValue,
405-
builder: (context, Widget? child) {
406-
return MediaQuery(
407-
data:
408-
MediaQuery.of(context).copyWith(alwaysUse24HourFormat: false),
409-
child: child!,
410-
);
411-
},
362+
var selectedTime = await _showCustomizedTimePicker();
363+
_effectiveFocusNode.requestFocus();
364+
365+
selectedTime ??= _value == null
366+
? const TimeOfDay(hour: 0, minute: 0)
367+
: TimeOfDay.fromDateTime(_value!);
368+
369+
_setValue(
370+
DateTime(
371+
selectedDate.year,
372+
selectedDate.month,
373+
selectedDate.day,
374+
selectedTime.hour,
375+
selectedTime.minute,
376+
0,
377+
0,
378+
0,
379+
),
380+
setTextAndMoveCursorToEnd: true,
412381
);
382+
break;
413383

384+
case VscDatetimeFieldType.time:
385+
final selected = await _showCustomizedTimePicker();
414386
_effectiveFocusNode.requestFocus();
415387

416388
if (selected != null) {
417-
// Modify the field's DateTime, sans the date component.
389+
// Modify the field's DateTime time component.
418390
final currValue = _value ?? testableNow();
419391
_setValue(
420392
DateTime(
@@ -434,6 +406,32 @@ class VscDatetimeFieldState extends State<VscDatetimeField> {
434406
}
435407
}
436408

409+
Future<TimeOfDay?> _showCustomizedTimePicker() async {
410+
final selected = await showTimePicker(
411+
context: context,
412+
initialTime: _value == null
413+
? const TimeOfDay(hour: 0, minute: 0)
414+
: TimeOfDay.fromDateTime(_value!),
415+
builder: (context, Widget? child) {
416+
return MediaQuery(
417+
data: MediaQuery.of(context).copyWith(alwaysUse24HourFormat: false),
418+
child: child!,
419+
);
420+
},
421+
);
422+
return selected;
423+
}
424+
425+
Future<DateTime?> _showCustomizedDatePicker() async {
426+
final selected = await showDatePicker(
427+
context: context,
428+
initialDate: _value ?? testableNow(),
429+
firstDate: widget.minValue,
430+
lastDate: widget.maxValue,
431+
);
432+
return selected;
433+
}
434+
437435
void _setValue(
438436
DateTime? newValue, {
439437
bool setText = false,

pubspec.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ dependencies:
1111
flutter:
1212
sdk: flutter
1313

14-
flutter_keyboard_visibility: ^5.2.0
1514
intl: ^0.18.0
1615

1716
dev_dependencies:

test/goldens/date_only_post_focus.png

2.68 KB
Loading

0 commit comments

Comments
 (0)