diff --git a/example/ios/Flutter/AppFrameworkInfo.plist b/example/ios/Flutter/AppFrameworkInfo.plist index 9367d483..9625e105 100644 --- a/example/ios/Flutter/AppFrameworkInfo.plist +++ b/example/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 8.0 + 11.0 diff --git a/example/ios/Flutter/flutter_export_environment.sh b/example/ios/Flutter/flutter_export_environment.sh index da2211a4..3e061154 100755 --- a/example/ios/Flutter/flutter_export_environment.sh +++ b/example/ios/Flutter/flutter_export_environment.sh @@ -1,16 +1,13 @@ #!/bin/sh # This is a generated file; do not edit or check into version control. -export "FLUTTER_ROOT=/Users/liuyanbo/flutter" -export "FLUTTER_APPLICATION_PATH=/Users/liuyanbo/Documents/GitHub/flutter_datetime_picker/example" -export "FLUTTER_TARGET=/Users/liuyanbo/Documents/GitHub/flutter_datetime_picker/example/lib/main.dart" +export "FLUTTER_ROOT=/Users/zh/Library/Huawei/flutter_flutter" +export "FLUTTER_APPLICATION_PATH=/Users/zh/Documents/fork/flutter_datetime_picker/example" +export "COCOAPODS_PARALLEL_CODE_SIGN=true" +export "FLUTTER_TARGET=lib/main.dart" export "FLUTTER_BUILD_DIR=build" -export "SYMROOT=${SOURCE_ROOT}/../build/ios" -export "OTHER_LDFLAGS=$(inherited) -framework Flutter" -export "FLUTTER_FRAMEWORK_DIR=/Users/liuyanbo/flutter/bin/cache/artifacts/engine/ios" export "FLUTTER_BUILD_NAME=1.0.0" export "FLUTTER_BUILD_NUMBER=1" -export "DART_DEFINES=flutter.inspector.structuredErrors%3Dtrue" export "DART_OBFUSCATION=false" export "TRACK_WIDGET_CREATION=true" export "TREE_SHAKE_ICONS=false" -export "PACKAGE_CONFIG=.packages" +export "PACKAGE_CONFIG=.dart_tool/package_config.json" diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index 1c85b6d7..3d4f0cb6 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 46; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -140,7 +140,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0910; + LastUpgradeCheck = 1300; ORGANIZATIONNAME = "The Chromium Authors"; TargetAttributes = { 97C146ED1CF9000F007C117D = { @@ -184,6 +184,7 @@ /* Begin PBXShellScriptBuildPhase section */ 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -198,6 +199,7 @@ }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -290,7 +292,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -337,7 +339,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata index 1d526a16..919434a6 100644 --- a/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ b/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -2,6 +2,6 @@ + location = "self:"> diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 1263ac84..1c19f4b8 100644 --- a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ UIViewControllerBasedStatusBarAppearance + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + diff --git a/example/lib/main.dart b/example/lib/main.dart index 1ab0e793..2c34fad2 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_datetime_picker/flutter_datetime_picker.dart'; +import 'package:flutter_datetime_picker/src/my_datetime_picker_theme.dart'; void main() => runApp(new MyApp()); @@ -8,8 +9,7 @@ class CustomPicker extends CommonPickerModel { return '$value'.padLeft(length, "0"); } - CustomPicker({DateTime? currentTime, LocaleType? locale}) - : super(locale: locale) { + CustomPicker({DateTime? currentTime, LocaleType? locale}) : super(locale: locale) { this.currentTime = currentTime ?? DateTime.now(); this.setLeftIndex(this.currentTime.hour); this.setMiddleIndex(this.currentTime.minute); @@ -45,36 +45,26 @@ class CustomPicker extends CommonPickerModel { @override String leftDivider() { - return "|"; + return ""; } @override String rightDivider() { - return "|"; + return ""; } @override List layoutProportions() { - return [1, 2, 1]; + return [2, 1, 1]; } @override DateTime finalTime() { return currentTime.isUtc ? DateTime.utc( - currentTime.year, - currentTime.month, - currentTime.day, - this.currentLeftIndex(), - this.currentMiddleIndex(), - this.currentRightIndex()) + currentTime.year, currentTime.month, currentTime.day, this.currentLeftIndex(), this.currentMiddleIndex(), this.currentRightIndex()) : DateTime( - currentTime.year, - currentTime.month, - currentTime.day, - this.currentLeftIndex(), - this.currentMiddleIndex(), - this.currentRightIndex()); + currentTime.year, currentTime.month, currentTime.day, this.currentLeftIndex(), this.currentMiddleIndex(), this.currentRightIndex()); } } @@ -102,154 +92,144 @@ class HomePage extends StatelessWidget { body: Center( child: Column( children: [ + // TextButton( + // onPressed: () { + // DatePicker.showDatePicker(context, + // showTitleActions: true, + // minTime: DateTime(2018, 3, 5), + // maxTime: DateTime(2019, 6, 7), + // theme: DatePickerTheme( + // headerColor: Colors.orange, + // backgroundColor: Colors.blue, + // itemStyle: TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 18), + // doneStyle: TextStyle(color: Colors.white, fontSize: 16)), onChanged: (date) { + // print('change $date in time zone ' + date.timeZoneOffset.inHours.toString()); + // }, onConfirm: (date) { + // print('confirm $date'); + // }, currentTime: DateTime.now(), locale: LocaleType.en); + // }, + // child: Text( + // 'show date picker(custom theme &date time range)', + // style: TextStyle(color: Colors.blue), + // )), + // TextButton( + // onPressed: () { + // DatePicker.showTimePicker(context, showTitleActions: true, onChanged: (date) { + // print('change $date in time zone ' + date.timeZoneOffset.inHours.toString()); + // }, onConfirm: (date) { + // print('confirm $date'); + // }, currentTime: DateTime.now()); + // }, + // child: Text( + // 'show time picker', + // style: TextStyle(color: Colors.blue), + // )), + // TextButton( + // onPressed: () { + // DatePicker.showTime12hPicker(context, showTitleActions: true, onChanged: (date) { + // print('change $date in time zone ' + date.timeZoneOffset.inHours.toString()); + // }, onConfirm: (date) { + // print('confirm $date'); + // }, currentTime: DateTime.now()); + // }, + // child: Text( + // 'show 12H time picker with AM/PM', + // style: TextStyle(color: Colors.blue), + // )), TextButton( onPressed: () { - DatePicker.showDatePicker(context, - showTitleActions: true, - minTime: DateTime(2018, 3, 5), - maxTime: DateTime(2019, 6, 7), - theme: DatePickerTheme( - headerColor: Colors.orange, - backgroundColor: Colors.blue, - itemStyle: TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, - fontSize: 18), - doneStyle: - TextStyle(color: Colors.white, fontSize: 16)), - onChanged: (date) { - print('change $date in time zone ' + - date.timeZoneOffset.inHours.toString()); - }, onConfirm: (date) { - print('confirm $date'); - }, currentTime: DateTime.now(), locale: LocaleType.en); + DatePicker.showGreeRouteDateTimePicker( + context, + showTitleActions: true, + minTime: DateTime.now(), + maxTime: DateTime.now().add(Duration(days: 1000)), + theme: MyDatePickerTheme(title: '开始时间'), + onChanged: (date) { + print('change $date in time zone ' + date.timeZoneOffset.inHours.toString()); + }, + onConfirm: (date) { + print('confirm $date'); + }, + locale: LocaleType.zh, + ); }, child: Text( - 'show date picker(custom theme &date time range)', - style: TextStyle(color: Colors.blue), - )), - TextButton( - onPressed: () { - DatePicker.showTimePicker(context, showTitleActions: true, - onChanged: (date) { - print('change $date in time zone ' + - date.timeZoneOffset.inHours.toString()); - }, onConfirm: (date) { - print('confirm $date'); - }, currentTime: DateTime.now()); - }, - child: Text( - 'show time picker', - style: TextStyle(color: Colors.blue), - )), - TextButton( - onPressed: () { - DatePicker.showTime12hPicker(context, showTitleActions: true, - onChanged: (date) { - print('change $date in time zone ' + - date.timeZoneOffset.inHours.toString()); - }, onConfirm: (date) { - print('confirm $date'); - }, currentTime: DateTime.now()); - }, - child: Text( - 'show 12H time picker with AM/PM', - style: TextStyle(color: Colors.blue), - )), - TextButton( - onPressed: () { - DatePicker.showDateTimePicker(context, - showTitleActions: true, - minTime: DateTime(2020, 5, 5, 20, 50), - maxTime: DateTime(2020, 6, 7, 05, 09), onChanged: (date) { - print('change $date in time zone ' + - date.timeZoneOffset.inHours.toString()); - }, onConfirm: (date) { - print('confirm $date'); - }, locale: LocaleType.zh); - }, - child: Text( - 'show date time picker (Chinese)', - style: TextStyle(color: Colors.blue), - )), - TextButton( - onPressed: () { - DatePicker.showDateTimePicker(context, showTitleActions: true, - onChanged: (date) { - print('change $date in time zone ' + - date.timeZoneOffset.inHours.toString()); - }, onConfirm: (date) { - print('confirm $date'); - }, currentTime: DateTime(2008, 12, 31, 23, 12, 34)); - }, - child: Text( - 'show date time picker (English-America)', - style: TextStyle(color: Colors.blue), - )), - TextButton( - onPressed: () { - DatePicker.showDateTimePicker(context, showTitleActions: true, - onChanged: (date) { - print('change $date in time zone ' + - date.timeZoneOffset.inHours.toString()); - }, onConfirm: (date) { - print('confirm $date'); - }, - currentTime: DateTime(2008, 12, 31, 23, 12, 34), - locale: LocaleType.nl); - }, - child: Text( - 'show date time picker (Dutch)', - style: TextStyle(color: Colors.blue), - )), - TextButton( - onPressed: () { - DatePicker.showDateTimePicker(context, showTitleActions: true, - onChanged: (date) { - print('change $date in time zone ' + - date.timeZoneOffset.inHours.toString()); - }, onConfirm: (date) { - print('confirm $date'); - }, - currentTime: DateTime(2008, 12, 31, 23, 12, 34), - locale: LocaleType.ru); - }, - child: Text( - 'show date time picker (Russian)', - style: TextStyle(color: Colors.blue), - )), - TextButton( - onPressed: () { - DatePicker.showDateTimePicker(context, showTitleActions: true, - onChanged: (date) { - print('change $date in time zone ' + - date.timeZoneOffset.inHours.toString()); - }, onConfirm: (date) { - print('confirm $date'); - }, - currentTime: DateTime.utc(2019, 12, 31, 23, 12, 34), - locale: LocaleType.de); - }, - child: Text( - 'show date time picker in UTC (German)', - style: TextStyle(color: Colors.blue), - )), - TextButton( - onPressed: () { - DatePicker.showPicker(context, showTitleActions: true, - onChanged: (date) { - print('change $date in time zone ' + - date.timeZoneOffset.inHours.toString()); - }, onConfirm: (date) { - print('confirm $date'); - }, - pickerModel: CustomPicker(currentTime: DateTime.now()), - locale: LocaleType.en); - }, - child: Text( - 'show custom time picker,\nyou can custom picker model like this', + '导航 DatePicker', style: TextStyle(color: Colors.blue), )), + // TextButton( + // onPressed: () { + // DatePicker.showDateTimePicker(context, showTitleActions: true, onChanged: (date) { + // print('change $date in time zone ' + date.timeZoneOffset.inHours.toString()); + // }, onConfirm: (date) { + // print('confirm $date'); + // }, currentTime: DateTime(2008, 12, 31, 23, 12, 34)); + // }, + // child: Text( + // 'show date time picker (English-America)', + // style: TextStyle(color: Colors.blue), + // )), + // TextButton( + // onPressed: () { + // DatePicker.showDateTimePicker(context, showTitleActions: true, onChanged: (date) { + // print('change $date in time zone ' + date.timeZoneOffset.inHours.toString()); + // }, onConfirm: (date) { + // print('confirm $date'); + // }, currentTime: DateTime(2008, 12, 31, 23, 12, 34), locale: LocaleType.nl); + // }, + // child: Text( + // 'show date time picker (Dutch)', + // style: TextStyle(color: Colors.blue), + // )), + // TextButton( + // onPressed: () { + // DatePicker.showDateTimePicker(context, showTitleActions: true, onChanged: (date) { + // print('change $date in time zone ' + date.timeZoneOffset.inHours.toString()); + // }, onConfirm: (date) { + // print('confirm $date'); + // }, currentTime: DateTime(2008, 12, 31, 23, 12, 34), locale: LocaleType.ru); + // }, + // child: Text( + // 'show date time picker (Russian)', + // style: TextStyle(color: Colors.blue), + // )), + // TextButton( + // onPressed: () { + // DatePicker.showDateTimePicker(context, showTitleActions: true, onChanged: (date) { + // print('change $date in time zone ' + date.timeZoneOffset.inHours.toString()); + // }, onConfirm: (date) { + // print('confirm $date'); + // }, currentTime: DateTime.utc(2019, 12, 31, 23, 12, 34), locale: LocaleType.de); + // }, + // child: Text( + // 'show date time picker in UTC (German)', + // style: TextStyle(color: Colors.blue), + // )), + // TextButton( + // onPressed: () { + // DatePicker.showPicker(context, showTitleActions: true, onChanged: (date) { + // print('change $date in time zone ' + date.timeZoneOffset.inHours.toString()); + // }, onConfirm: (date) { + // print('confirm $date'); + // }, pickerModel: CustomPicker(currentTime: DateTime.now()), locale: LocaleType.en); + // }, + // child: Text( + // 'show custom time picker,\nyou can custom picker model like this', + // style: TextStyle(color: Colors.blue), + // )), + // TextButton( + // onPressed: () { + // DatePicker.showPicker( + // context, + // pickerModel: CustomPicker(locale: LocaleType.zh), + // onChanged: (date) {}, + // onConfirm: (date) {}, + // ); + // }, + // child: Text( + // '路线规划 DatePicker', + // style: TextStyle(color: Colors.blue), + // )), ], ), ), diff --git a/lib/flutter_datetime_picker.dart b/lib/flutter_datetime_picker.dart index dba6b566..a80b4f29 100644 --- a/lib/flutter_datetime_picker.dart +++ b/lib/flutter_datetime_picker.dart @@ -4,11 +4,11 @@ import 'dart:async'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/painting.dart'; -import 'package:flutter_datetime_picker/src/datetime_picker_theme.dart'; +import 'package:flutter_datetime_picker/src/GreeRouteDatePickerModel.dart'; import 'package:flutter_datetime_picker/src/date_model.dart'; import 'package:flutter_datetime_picker/src/i18n_model.dart'; +import 'package:flutter_datetime_picker/src/my_datetime_picker_theme.dart'; -export 'package:flutter_datetime_picker/src/datetime_picker_theme.dart'; export 'package:flutter_datetime_picker/src/date_model.dart'; export 'package:flutter_datetime_picker/src/i18n_model.dart'; @@ -17,10 +17,112 @@ typedef DateCancelledCallback(); typedef String? StringAtIndexCallBack(int index); class DatePicker { + // /// + // /// Display date picker bottom sheet. + // /// + // static Future showDatePicker( + // BuildContext context, { + // bool showTitleActions: true, + // DateTime? minTime, + // DateTime? maxTime, + // DateChangedCallback? onChanged, + // DateChangedCallback? onConfirm, + // DateCancelledCallback? onCancel, + // locale: LocaleType.en, + // DateTime? currentTime, + // DatePickerTheme? theme, + // }) async { + // return await Navigator.push( + // context, + // _DatePickerRoute( + // showTitleActions: showTitleActions, + // onChanged: onChanged, + // onConfirm: onConfirm, + // onCancel: onCancel, + // locale: locale, + // theme: theme, + // barrierLabel: + // MaterialLocalizations.of(context).modalBarrierDismissLabel, + // pickerModel: DatePickerModel( + // currentTime: currentTime, + // maxTime: maxTime, + // minTime: minTime, + // locale: locale, + // ), + // ), + // ); + // } + // + // /// + // /// Display time picker bottom sheet. + // /// + // static Future showTimePicker( + // BuildContext context, { + // bool showTitleActions: true, + // bool showSecondsColumn: true, + // DateChangedCallback? onChanged, + // DateChangedCallback? onConfirm, + // DateCancelledCallback? onCancel, + // locale: LocaleType.en, + // DateTime? currentTime, + // DatePickerTheme? theme, + // }) async { + // return await Navigator.push( + // context, + // _DatePickerRoute( + // showTitleActions: showTitleActions, + // onChanged: onChanged, + // onConfirm: onConfirm, + // onCancel: onCancel, + // locale: locale, + // theme: theme, + // barrierLabel: + // MaterialLocalizations.of(context).modalBarrierDismissLabel, + // pickerModel: TimePickerModel( + // currentTime: currentTime, + // locale: locale, + // showSecondsColumn: showSecondsColumn, + // ), + // ), + // ); + // } + // + // /// + // /// Display time picker bottom sheet with AM/PM. + // /// + // static Future showTime12hPicker( + // BuildContext context, { + // bool showTitleActions: true, + // DateChangedCallback? onChanged, + // DateChangedCallback? onConfirm, + // DateCancelledCallback? onCancel, + // locale: LocaleType.en, + // DateTime? currentTime, + // DatePickerTheme? theme, + // }) async { + // return await Navigator.push( + // context, + // _DatePickerRoute( + // showTitleActions: showTitleActions, + // onChanged: onChanged, + // onConfirm: onConfirm, + // onCancel: onCancel, + // locale: locale, + // theme: theme, + // barrierLabel: + // MaterialLocalizations.of(context).modalBarrierDismissLabel, + // pickerModel: Time12hPickerModel( + // currentTime: currentTime, + // locale: locale, + // ), + // ), + // ); + // } + /// - /// Display date picker bottom sheet. + /// Display date&time picker bottom sheet. /// - static Future showDatePicker( + static Future showDateTimePicker( BuildContext context, { bool showTitleActions: true, DateTime? minTime, @@ -30,7 +132,7 @@ class DatePicker { DateCancelledCallback? onCancel, locale: LocaleType.en, DateTime? currentTime, - DatePickerTheme? theme, + MyDatePickerTheme? theme, }) async { return await Navigator.push( context, @@ -41,88 +143,18 @@ class DatePicker { onCancel: onCancel, locale: locale, theme: theme, - barrierLabel: - MaterialLocalizations.of(context).modalBarrierDismissLabel, - pickerModel: DatePickerModel( + barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel, + pickerModel: DateTimePickerModel( currentTime: currentTime, - maxTime: maxTime, minTime: minTime, + maxTime: maxTime, locale: locale, ), ), ); } - /// - /// Display time picker bottom sheet. - /// - static Future showTimePicker( - BuildContext context, { - bool showTitleActions: true, - bool showSecondsColumn: true, - DateChangedCallback? onChanged, - DateChangedCallback? onConfirm, - DateCancelledCallback? onCancel, - locale: LocaleType.en, - DateTime? currentTime, - DatePickerTheme? theme, - }) async { - return await Navigator.push( - context, - _DatePickerRoute( - showTitleActions: showTitleActions, - onChanged: onChanged, - onConfirm: onConfirm, - onCancel: onCancel, - locale: locale, - theme: theme, - barrierLabel: - MaterialLocalizations.of(context).modalBarrierDismissLabel, - pickerModel: TimePickerModel( - currentTime: currentTime, - locale: locale, - showSecondsColumn: showSecondsColumn, - ), - ), - ); - } - - /// - /// Display time picker bottom sheet with AM/PM. - /// - static Future showTime12hPicker( - BuildContext context, { - bool showTitleActions: true, - DateChangedCallback? onChanged, - DateChangedCallback? onConfirm, - DateCancelledCallback? onCancel, - locale: LocaleType.en, - DateTime? currentTime, - DatePickerTheme? theme, - }) async { - return await Navigator.push( - context, - _DatePickerRoute( - showTitleActions: showTitleActions, - onChanged: onChanged, - onConfirm: onConfirm, - onCancel: onCancel, - locale: locale, - theme: theme, - barrierLabel: - MaterialLocalizations.of(context).modalBarrierDismissLabel, - pickerModel: Time12hPickerModel( - currentTime: currentTime, - locale: locale, - ), - ), - ); - } - - /// - /// Display date&time picker bottom sheet. - /// - static Future showDateTimePicker( + static Future showGreeRouteDateTimePicker( BuildContext context, { bool showTitleActions: true, DateTime? minTime, @@ -132,7 +164,7 @@ class DatePicker { DateCancelledCallback? onCancel, locale: LocaleType.en, DateTime? currentTime, - DatePickerTheme? theme, + MyDatePickerTheme? theme, }) async { return await Navigator.push( context, @@ -143,9 +175,8 @@ class DatePicker { onCancel: onCancel, locale: locale, theme: theme, - barrierLabel: - MaterialLocalizations.of(context).modalBarrierDismissLabel, - pickerModel: DateTimePickerModel( + barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel, + pickerModel: GreeRouteDatePickerModel( currentTime: currentTime, minTime: minTime, maxTime: maxTime, @@ -155,34 +186,72 @@ class DatePicker { ); } - /// - /// Display date picker bottom sheet witch custom picker model. - /// - static Future showPicker( - BuildContext context, { - bool showTitleActions: true, - DateChangedCallback? onChanged, - DateChangedCallback? onConfirm, - DateCancelledCallback? onCancel, - locale: LocaleType.en, - BasePickerModel? pickerModel, - DatePickerTheme? theme, - }) async { - return await Navigator.push( - context, - _DatePickerRoute( - showTitleActions: showTitleActions, - onChanged: onChanged, - onConfirm: onConfirm, - onCancel: onCancel, - locale: locale, - theme: theme, - barrierLabel: - MaterialLocalizations.of(context).modalBarrierDismissLabel, - pickerModel: pickerModel, - ), - ); - } +// +// +// /// +// /// 格力路径规划时间选择器 +// /// +// static Future showGreeRouteDatePicker( +// BuildContext context, { +// bool showTitleActions: true, +// DateTime? minTime, +// DateTime? maxTime, +// DateChangedCallback? onChanged, +// DateChangedCallback? onConfirm, +// DateCancelledCallback? onCancel, +// locale: LocaleType.en, +// DateTime? currentTime, +// DatePickerTheme? theme, +// }) async { +// return await Navigator.push( +// context, +// _DatePickerRoute( +// showTitleActions: showTitleActions, +// onChanged: onChanged, +// onConfirm: onConfirm, +// onCancel: onCancel, +// locale: locale, +// theme: theme, +// barrierLabel: +// MaterialLocalizations.of(context).modalBarrierDismissLabel, +// pickerModel: DateTimePickerModel( +// currentTime: currentTime, +// minTime: minTime, +// maxTime: maxTime, +// locale: locale, +// ), +// ), +// ); +// } +// +// /// +// /// Display date picker bottom sheet witch custom picker model. +// /// +// static Future showPicker( +// BuildContext context, { +// bool showTitleActions: true, +// DateChangedCallback? onChanged, +// DateChangedCallback? onConfirm, +// DateCancelledCallback? onCancel, +// locale: LocaleType.en, +// BasePickerModel? pickerModel, +// DatePickerTheme? theme, +// }) async { +// return await Navigator.push( +// context, +// _DatePickerRoute( +// showTitleActions: showTitleActions, +// onChanged: onChanged, +// onConfirm: onConfirm, +// onCancel: onCancel, +// locale: locale, +// theme: theme, +// barrierLabel: +// MaterialLocalizations.of(context).modalBarrierDismissLabel, +// pickerModel: pickerModel, +// ), +// ); +// } } class _DatePickerRoute extends PopupRoute { @@ -191,13 +260,13 @@ class _DatePickerRoute extends PopupRoute { this.onChanged, this.onConfirm, this.onCancel, - DatePickerTheme? theme, + MyDatePickerTheme? theme, this.barrierLabel, this.locale, RouteSettings? settings, BasePickerModel? pickerModel, }) : this.pickerModel = pickerModel ?? DatePickerModel(), - this.theme = theme ?? DatePickerTheme(), + this.theme = theme ?? MyDatePickerTheme(), super(settings: settings); final bool? showTitleActions; @@ -205,7 +274,7 @@ class _DatePickerRoute extends PopupRoute { final DateChangedCallback? onConfirm; final DateCancelledCallback? onCancel; final LocaleType? locale; - final DatePickerTheme theme; + final MyDatePickerTheme theme; final BasePickerModel pickerModel; @override @@ -225,14 +294,12 @@ class _DatePickerRoute extends PopupRoute { @override AnimationController createAnimationController() { assert(_animationController == null); - _animationController = - BottomSheet.createAnimationController(navigator!.overlay!); + _animationController = BottomSheet.createAnimationController(navigator!.overlay!); return _animationController!; } @override - Widget buildPage(BuildContext context, Animation animation, - Animation secondaryAnimation) { + Widget buildPage(BuildContext context, Animation animation, Animation secondaryAnimation) { Widget bottomSheet = MediaQuery.removePadding( context: context, removeTop: true, @@ -271,9 +338,7 @@ class _DatePickerComponent extends StatefulWidget { } class _DatePickerState extends State<_DatePickerComponent> { - late FixedExtentScrollController leftScrollCtrl, - middleScrollCtrl, - rightScrollCtrl; + late FixedExtentScrollController leftScrollCtrl, middleScrollCtrl, rightScrollCtrl; @override void initState() { @@ -283,17 +348,14 @@ class _DatePickerState extends State<_DatePickerComponent> { void refreshScrollOffset() { // print('refreshScrollOffset ${widget.pickerModel.currentRightIndex()}'); - leftScrollCtrl = FixedExtentScrollController( - initialItem: widget.pickerModel.currentLeftIndex()); - middleScrollCtrl = FixedExtentScrollController( - initialItem: widget.pickerModel.currentMiddleIndex()); - rightScrollCtrl = FixedExtentScrollController( - initialItem: widget.pickerModel.currentRightIndex()); + leftScrollCtrl = FixedExtentScrollController(initialItem: widget.pickerModel.currentLeftIndex()); + middleScrollCtrl = FixedExtentScrollController(initialItem: widget.pickerModel.currentMiddleIndex()); + rightScrollCtrl = FixedExtentScrollController(initialItem: widget.pickerModel.currentRightIndex()); } @override Widget build(BuildContext context) { - DatePickerTheme theme = widget.route.theme; + MyDatePickerTheme theme = widget.route.theme; return GestureDetector( child: AnimatedBuilder( animation: widget.route.animation!, @@ -309,7 +371,7 @@ class _DatePickerState extends State<_DatePickerComponent> { ), child: GestureDetector( child: Material( - color: theme.backgroundColor, + color: Colors.transparent, child: _renderPickerView(theme), ), ), @@ -326,22 +388,45 @@ class _DatePickerState extends State<_DatePickerComponent> { } } - Widget _renderPickerView(DatePickerTheme theme) { + Widget _renderPickerView(MyDatePickerTheme theme) { Widget itemView = _renderItemView(theme); if (widget.route.showTitleActions == true) { return Column( children: [ _renderTitleActionsView(theme), itemView, + Expanded( + child: Container(color: theme.backgroundColor), + ) ], ); } return itemView; } + /// 上下分割线 + Widget _buildMagnifierScreen(double itemExtent) { + final Color resolvedBorderColor = CupertinoDynamicColor.resolve(Color(0xFFEBEDF5), context); + return IgnorePointer( + child: Center( + child: Container( + decoration: BoxDecoration( + border: Border( + top: BorderSide(width: 0.0, color: resolvedBorderColor), + bottom: BorderSide(width: 0.0, color: resolvedBorderColor), + ), + ), + constraints: BoxConstraints.expand( + height: itemExtent, + ), + ), + ), + ); + } + Widget _renderColumnView( ValueKey key, - DatePickerTheme theme, + MyDatePickerTheme theme, StringAtIndexCallBack stringAtIndexCB, ScrollController scrollController, int layoutProportion, @@ -351,16 +436,12 @@ class _DatePickerState extends State<_DatePickerComponent> { return Expanded( flex: layoutProportion, child: Container( - padding: EdgeInsets.all(8.0), height: theme.containerHeight, decoration: BoxDecoration(color: theme.backgroundColor), child: NotificationListener( onNotification: (ScrollNotification notification) { - if (notification.depth == 0 && - notification is ScrollEndNotification && - notification.metrics is FixedExtentMetrics) { - final FixedExtentMetrics metrics = - notification.metrics as FixedExtentMetrics; + if (notification.depth == 0 && notification is ScrollEndNotification && notification.metrics is FixedExtentMetrics) { + final FixedExtentMetrics metrics = notification.metrics as FixedExtentMetrics; final int currentItemIndex = metrics.itemIndex; selectedChangedWhenScrollEnd(currentItemIndex); } @@ -369,6 +450,7 @@ class _DatePickerState extends State<_DatePickerComponent> { child: CupertinoPicker.builder( key: key, backgroundColor: theme.backgroundColor, + selectionOverlay: _buildMagnifierScreen(theme.itemHeight), scrollController: scrollController as FixedExtentScrollController, itemExtent: theme.itemHeight, onSelectedItemChanged: (int index) { @@ -396,7 +478,7 @@ class _DatePickerState extends State<_DatePickerComponent> { ); } - Widget _renderItemView(DatePickerTheme theme) { + Widget _renderItemView(MyDatePickerTheme theme) { return Container( color: theme.backgroundColor, child: Directionality( @@ -406,11 +488,7 @@ class _DatePickerState extends State<_DatePickerComponent> { children: [ Container( child: widget.pickerModel.layoutProportions()[0] > 0 - ? _renderColumnView( - ValueKey(widget.pickerModel.currentLeftIndex()), - theme, - widget.pickerModel.leftStringAtIndex, - leftScrollCtrl, + ? _renderColumnView(ValueKey(widget.pickerModel.currentLeftIndex()), theme, widget.pickerModel.leftStringAtIndex, leftScrollCtrl, widget.pickerModel.layoutProportions()[0], (index) { widget.pickerModel.setLeftIndex(index); }, (index) { @@ -427,12 +505,8 @@ class _DatePickerState extends State<_DatePickerComponent> { ), Container( child: widget.pickerModel.layoutProportions()[1] > 0 - ? _renderColumnView( - ValueKey(widget.pickerModel.currentLeftIndex()), - theme, - widget.pickerModel.middleStringAtIndex, - middleScrollCtrl, - widget.pickerModel.layoutProportions()[1], (index) { + ? _renderColumnView(ValueKey(widget.pickerModel.currentLeftIndex()), theme, widget.pickerModel.middleStringAtIndex, + middleScrollCtrl, widget.pickerModel.layoutProportions()[1], (index) { widget.pickerModel.setMiddleIndex(index); }, (index) { setState(() { @@ -448,13 +522,8 @@ class _DatePickerState extends State<_DatePickerComponent> { ), Container( child: widget.pickerModel.layoutProportions()[2] > 0 - ? _renderColumnView( - ValueKey(widget.pickerModel.currentMiddleIndex() * 100 + - widget.pickerModel.currentLeftIndex()), - theme, - widget.pickerModel.rightStringAtIndex, - rightScrollCtrl, - widget.pickerModel.layoutProportions()[2], (index) { + ? _renderColumnView(ValueKey(widget.pickerModel.currentMiddleIndex() * 100 + widget.pickerModel.currentLeftIndex()), theme, + widget.pickerModel.rightStringAtIndex, rightScrollCtrl, widget.pickerModel.layoutProportions()[2], (index) { widget.pickerModel.setRightIndex(index); }, (index) { setState(() { @@ -471,52 +540,52 @@ class _DatePickerState extends State<_DatePickerComponent> { } // Title View - Widget _renderTitleActionsView(DatePickerTheme theme) { - final done = _localeDone(); + Widget _renderTitleActionsView(MyDatePickerTheme theme) { final cancel = _localeCancel(); - return Container( height: theme.titleHeight, decoration: BoxDecoration( - color: theme.headerColor ?? theme.backgroundColor, + color: theme.headerColor, + borderRadius: BorderRadius.only(topLeft: Radius.circular(12), topRight: Radius.circular(12)), ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Container( - height: theme.titleHeight, - child: CupertinoButton( - pressedOpacity: 0.3, - padding: EdgeInsetsDirectional.only(start: 16, top: 0), - child: Text( - '$cancel', - style: theme.cancelStyle, + child: Column( + children: [ + Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Container( + margin: const EdgeInsets.only(left: 66), + alignment: Alignment.center, + height: theme.titleHeight - 1, + child: Text( + theme.title, + style: theme.titleStyle, + ), + ), ), - onPressed: () { - Navigator.pop(context); - if (widget.route.onCancel != null) { - widget.route.onCancel!(); - } - }, - ), - ), - Container( - height: theme.titleHeight, - child: CupertinoButton( - pressedOpacity: 0.3, - padding: EdgeInsetsDirectional.only(end: 16, top: 0), - child: Text( - '$done', - style: theme.doneStyle, + Container( + margin: const EdgeInsets.only(right: 16), + alignment: Alignment.centerRight, + height: theme.titleHeight - 1, + child: CupertinoButton( + pressedOpacity: 0.3, + padding: EdgeInsetsDirectional.only(start: 16, top: 0), + child: Text( + '$cancel', + style: theme.cancelStyle, + ), + onPressed: () { + Navigator.pop(context); + if (widget.route.onCancel != null) { + widget.route.onCancel!(); + } + }, + ), ), - onPressed: () { - Navigator.pop(context, widget.pickerModel.finalTime()); - if (widget.route.onConfirm != null) { - widget.route.onConfirm!(widget.pickerModel.finalTime()!); - } - }, - ), + ], ), + Container(height: 1, color: Color(0xFFEBEDF5)), ], ), ); @@ -527,7 +596,8 @@ class _DatePickerState extends State<_DatePickerComponent> { } String _localeCancel() { - return i18nObjInLocale(widget.locale)['cancel'] as String; + return '关闭'; + // return i18nObjInLocale(widget.locale)['cancel'] as String; } } @@ -543,7 +613,7 @@ class _BottomPickerLayout extends SingleChildLayoutDelegate { final double progress; final int? itemCount; final bool? showTitleActions; - final DatePickerTheme theme; + final MyDatePickerTheme theme; final double bottomPadding; @override diff --git a/lib/src/GreeRouteDatePickerModel.dart b/lib/src/GreeRouteDatePickerModel.dart new file mode 100644 index 00000000..66d6394e --- /dev/null +++ b/lib/src/GreeRouteDatePickerModel.dart @@ -0,0 +1,61 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_datetime_picker/flutter_datetime_picker.dart'; +import 'package:flutter_datetime_picker/src/date_format.dart'; + +class GreeRouteDatePickerModel extends DateTimePickerModel { + + GreeRouteDatePickerModel({ + DateTime? currentTime, + DateTime? maxTime, + DateTime? minTime, + LocaleType? locale, + }) : super( + currentTime: currentTime, + maxTime: maxTime, + minTime: minTime, + locale: locale, + ); + + @override + String? middleStringAtIndex(int index) { + String? hour = super.middleStringAtIndex(index); + return hour == null ? null : '$hour 时'; + } + + @override + String? rightStringAtIndex(int index) { + String? min = super.rightStringAtIndex(index); + return min == null ? null : '$min 分'; + } + + @override + String? leftStringAtIndex(int index) { + DateTime time = currentTime.add(Duration(days: index)); + if (minTime != null && + time.isBefore(minTime!) && + !isAtSameDay(minTime!, time)) { + return null; + } else if (maxTime != null && + time.isAfter(maxTime!) && + !isAtSameDay(maxTime, time)) { + return null; + } + return '${time.year}年${time.month}月${time.day}日'; + } + + @override + List layoutProportions() { + return [2, 1, 1]; + } + + @override + String leftDivider() { + return ''; + } + + @override + String rightDivider() { + return ''; + } + +} diff --git a/lib/src/datetime_picker_theme.dart b/lib/src/datetime_picker_theme.dart deleted file mode 100644 index e3f616f4..00000000 --- a/lib/src/datetime_picker_theme.dart +++ /dev/null @@ -1,27 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; - -// Migrate DiagnosticableMixin to Diagnosticable until -// https://github.com/flutter/flutter/pull/51495 makes it into stable (v1.15.21) -class DatePickerTheme with DiagnosticableTreeMixin { - final TextStyle cancelStyle; - final TextStyle doneStyle; - final TextStyle itemStyle; - final Color backgroundColor; - final Color? headerColor; - - final double containerHeight; - final double titleHeight; - final double itemHeight; - - const DatePickerTheme({ - this.cancelStyle = const TextStyle(color: Colors.black54, fontSize: 16), - this.doneStyle = const TextStyle(color: Colors.blue, fontSize: 16), - this.itemStyle = const TextStyle(color: Color(0xFF000046), fontSize: 18), - this.backgroundColor = Colors.white, - this.headerColor, - this.containerHeight = 210.0, - this.titleHeight = 44.0, - this.itemHeight = 36.0, - }); -} diff --git a/lib/src/my_datetime_picker_theme.dart b/lib/src/my_datetime_picker_theme.dart new file mode 100644 index 00000000..a4af965d --- /dev/null +++ b/lib/src/my_datetime_picker_theme.dart @@ -0,0 +1,30 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +// Migrate DiagnosticableMixin to Diagnosticable until +// https://github.com/flutter/flutter/pull/51495 makes it into stable (v1.15.21) +class MyDatePickerTheme with DiagnosticableTreeMixin { + final TextStyle cancelStyle; + final TextStyle doneStyle; + final TextStyle itemStyle; + final TextStyle titleStyle; + final String title; + final Color backgroundColor; + final Color headerColor; + final double containerHeight; + final double titleHeight; + final double itemHeight; + + const MyDatePickerTheme({ + this.cancelStyle = const TextStyle(color: Color(0xFF409EFF), fontSize: 16), + this.doneStyle = const TextStyle(color: Colors.black, fontSize: 16), + this.itemStyle = const TextStyle(color: Color(0xFF333333), fontSize: 18), + this.titleStyle = const TextStyle(color: Color(0xFF333333), fontSize: 18, fontWeight: FontWeight.w600), + this.title = '', + this.backgroundColor = Colors.white, + this.headerColor = Colors.white, + this.containerHeight = 330.0, + this.titleHeight = 74.0, + this.itemHeight = 48.0, + }); +}