Commit 6dc64a08 by Rizal

first commit

parents
.DS_Store
.atom/
.idea/
.vscode/
.packages
.pub/
.dart_tool/
pubspec.lock
Podfile
Podfile.lock
Pods/
.symlinks/
**/Flutter/App.framework/
**/Flutter/Flutter.framework/
**/Flutter/Generated.xcconfig
**/Flutter/flutter_assets/
ServiceDefinitions.json
xcuserdata/
local.properties
.gradle/
gradlew
gradlew.bat
gradle-wrapper.jar
*.iml
GeneratedPluginRegistrant.h
GeneratedPluginRegistrant.m
GeneratedPluginRegistrant.java
build/
.flutter-plugins
/example/android/keystore.properties
/example/ios/Flutter/flutter_export_environment.sh
\ No newline at end of file
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: c7ea3ca377e909469c68f2ab878a5bc53d3cf66b
channel: beta
## 1.0.26+2
- Update pt_br language.
## 1.0.26+1
- Update pt_br language.
## 1.0.26
- Modify the button widget of the custom title bar to support hidden title and button widget:
```dart
DatePicker.showDatePicker(
pickerTheme: DateTimePickerTheme(
showTitle: true,
confirm: Text('custom Done', style: TextStyle(color: Colors.red)),
cancel: null, // If a custom title bar is set, the widget(title/confirm/cancel) will not be displayed when the value is null
),
);
```
## 1.0.25
- Fixed bug: [Issues #89](https://github.com/dylanwuzh/flutter-cupertino-date-picker/issues/89)
## 1.0.24
- Added language support: Dutch (NL).
## 1.0.23+1
- Remove `keystore.properties`.
## 1.0.23
- Added date format separator: `/`.
- `DatePicker.showDatePicker`: check pickerMode is legal or not by date format.
## 1.0.22
- Support `onMonthChangeStartWithFirstDate` for DatePicker: When the selected month changes, whether to set the selected date as the first day of the month.
## 1.0.21
- Added language support: Bosnian (BS) and Croatian (HR).
## 1.0.20
- Added language support: Ukraine (UK).
## 1.0.19+1
- Update LICENSE file.
## 1.0.19
- Added language support: Serbia Cyrillic(DateTimePickerLocale.sr_cyrl) and Latin(DateTimePickerLocale.sr_latn).
## 1.0.18
- Added language support: Turkish (DateTimePickerLocale.tr).
## 1.0.17
- Added language support: Vietnamese (DateTimePickerLocale.vi).
## 1.0.16
- Added language support: French (DateTimePickerLocale.fr).
## 1.0.15+1
- Modified Indonesia's subtag: DateTimePickerLocale.in_id -> DateTimePickerLocale.id
## 1.0.15
- Added language support: Bahasa Indonesia (DateTimePickerLocale.in_id).
## 1.0.14
- Added language support: Arabic Egypt (DateTimePickerLocale.ar_eg).
## 1.0.13+1
- Fixed bug: `DateTimePickerMode.datetime` mode display error. Issues: [#91](https://github.com/dylanwuzh/flutter-cupertino-date-picker/issues/91)
## 1.0.13
- Compatible with Flutter `dev` channel.
## 1.0.12
- Fixed bug: when `onClose` is null, catch exception `Unhandled Exception: NoSuchMethodError: The method 'call' was called on null. Receiver: null`. Issues: [#40](https://github.com/wuzhendev/flutter-cupertino-date-picker/issues/40) and [#43](https://github.com/wuzhendev/flutter-cupertino-date-picker/issues/43).
## 1.0.11
- Added `minuteDivider` parameter.
## 1.0.10
- Added `onClose` callback.
## 1.0.9
- Added language support: Hungarian (DateTimePickerLocale.hu).
## 1.0.8
- Refactor i18n codes.
## 1.0.7
- Added language support: Italian (DateTimePickerLocale.it).
## 1.0.6
- Added language support: Korea (DateTimePickerLocale.ko).
## 1.0.5
- Added language support: German (DateTimePickerLocale.de).
## 1.0.4
- Added language support: Russian (DateTimePickerLocale.ru).
## 1.0.3
- Added language support: Japanese (DateTimePickerLocale.jp).
## 1.0.2
- Added language support: Arabic (DateTimePickerLocale.ar).
## 1.0.1
- Added language support: Bengali (DateTimePickerLocale.bn).
## 1.0.0
- Refactor code.
- Support `DatePicker``TimePicker``DateTimePicker`.
- Support `DatePickerWidget``TimePickerWidget``DateTimePickerWidget`.
- Upgrade date format.
- Add `DateTimePickerTheme`.
- Add `DateTimePickerLocale` for locale.
## 0.8.0
- Support set the value of minimum DateTime and maximum DateTime.
## 0.7.0
- Change days in a month when moth changes.
## 0.6.0
- Add `DatePickerWidget` widget for display DatePicker in page.
## 0.5.0
- Add `onChanged2(DateTime dateTime, List<int> selectedIndex)` callback.
- Add `onConfirm2(DateTime dateTime, List<int> selectedIndex)` callback.
- Add `minDateTime`.
- Add `maxDateTime`.
- Add `initialDateTime`.
## 0.4.0
- Add `onCancel` callback.
## 0.3.0
- Support Flutter v1.0.
## 0.2.0
- Add custom cancel and confirm button.
## 0.1.0
- Refactor locale message.
## 0.0.7
- Support language support: Portuguese Brazil (DateTimePickerLocale.pt_br).
## 0.0.6
- Support English months.
## 0.0.5
- Fix month and day in zh locale.
## 0.0.4
- Support i18n.
## 0.0.2
- Complete README file.
## 0.0.1
- Initial Release.
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2017 Dylan Wu
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
# Flutter Cupertino Date Picker
[[pub packages]](https://pub.dartlang.org/packages/flutter_cupertino_date_picker)
| [中文说明](./README_zh-cn.md)
Flutter cupertino date picker.
![Example][1]
## Usage
#### 1\. Depend
Add this to you package's `pubspec.yaml` file:
```yaml
dependencies:
flutter_cupertino_date_picker: ^1.0.26+2
```
#### 2\. Install
Run command:
```bash
$ flutter packages get
```
#### 3\. Import
Import in Dart code:
```dart
import 'package:flutter_cupertino_date_picker/flutter_cupertino_date_picker.dart';
```
#### 4\. Display DatePicker
##### Bottom Sheet DatePicker
```dart
/// Display date picker in bottom sheet.
///
/// context: [BuildContext]
/// minDateTime: [DateTime] minimum date time
/// maxDateTime: [DateTime] maximum date time
/// initialDateTime: [DateTime] initial date time for selected
/// dateFormat: [String] date format pattern
/// locale: [DateTimePickerLocale] internationalization
/// pickerMode: [DateTimePickerMode] display mode: date(DatePicker)、time(TimePicker)、datetime(DateTimePicker)
/// pickerTheme: [DateTimePickerTheme] the theme of date time picker
/// onCancel: [DateVoidCallback] pressed title cancel widget event
/// onClose: [DateVoidCallback] date picker closed event
/// onChange: [DateValueCallback] selected date time changed event
/// onConfirm: [DateValueCallback] pressed title confirm widget event
DatePicker.showDatePicker(
BuildContext context,
DateTime minDateTime,
DateTime maxDateTime,
DateTime initialDateTime,
String dateFormat,
DateTimePickerLocale locale: DATETIME_PICKER_LOCALE_DEFAULT,
DateTimePickerMode pickerMode: DateTimePickerMode.date,
DateTimePickerTheme pickerTheme: DatePickerTheme.Default,
DateVoidCallback onCancel,
DateVoidCallback onClose,
DateValueCallback onChange,
DateValueCallback onConfirm,
});
```
##### DatePicker Widget
```dart
/// Display date picker widget.
///
/// minDateTime: [DateTime] minimum date time
/// maxDateTime: [DateTime] maximum date time
/// initialDateTime: [DateTime] initial date time for selected
/// dateFormat: [String] date format pattern
/// locale: [DateTimePickerLocale] internationalization
/// pickerTheme: [DateTimePickerTheme] the theme of date time picker
/// onCancel: [DateVoidCallback] pressed title cancel widget event
/// onChange: [DateValueCallback] selected date time changed event
/// onConfirm: [DateValueCallback] pressed title confirm widget event
DatePickerWidget({
DateTime minDateTime,
DateTime maxDateTime,
DateTime initialDateTime,
String dateFormat: DATETIME_PICKER_DATE_FORMAT,
DateTimePickerLocale locale: DATETIME_PICKER_LOCALE_DEFAULT,
DateTimePickerTheme pickerTheme: DatePickerTheme.Default,
DateVoidCallback onCancel,
DateValueCallback onChange,
DateValueCallback onConfirm,
})
```
##### TimePicker Widget
```dart
/// Display time picker widget.
///
/// minDateTime: [DateTime] minimum date time
/// maxDateTime: [DateTime] maximum date time
/// initialDateTime: [DateTime] initial date time for selected
/// dateFormat: [String] date format pattern
/// locale: [DateTimePickerLocale] internationalization
/// pickerTheme: [DateTimePickerTheme] the theme of date time picker
/// minuteDivider: [int] minute restriction, e.g. 5: every 5th minute will be shown (0, 5, 10, 15 ...)
/// onCancel: [DateVoidCallback] pressed title cancel widget event
/// onChange: [DateValueCallback] selected date time changed event
/// onConfirm: [DateValueCallback] pressed title confirm widget event
TimePickerWidget({
DateTime minDateTime,
DateTime maxDateTime,
DateTime initialDateTime,
String dateFormat: DATETIME_PICKER_DATE_FORMAT,
DateTimePickerLocale locale: DATETIME_PICKER_LOCALE_DEFAULT,
DateTimePickerTheme pickerTheme: DatePickerTheme.Default,
int minuteDivider: 1,
DateVoidCallback onCancel,
DateValueCallback onChange,
DateValueCallback onConfirm,
})
```
##### DateTimePicker Widget
```dart
/// Display date time picker widget.
///
/// minDateTime: [DateTime] minimum date time
/// maxDateTime: [DateTime] maximum date time
/// initialDateTime: [DateTime] initial date time for selected
/// dateFormat: [String] date format pattern
/// locale: [DateTimePickerLocale] internationalization
/// pickerTheme: [DateTimePickerTheme] the theme of date time picker
/// onCancel: [DateVoidCallback] pressed title cancel widget event
/// onChange: [DateValueCallback] selected date time changed event
/// onConfirm: [DateValueCallback] pressed title confirm widget event
DateTimePickerWidget({
DateTime minDateTime,
DateTime maxDateTime,
DateTime initialDateTime,
String dateFormat: DATETIME_PICKER_DATE_FORMAT,
DateTimePickerLocale locale: DATETIME_PICKER_LOCALE_DEFAULT,
DateTimePickerTheme pickerTheme: DatePickerTheme.Default,
DateVoidCallback onCancel,
DateValueCallback onChange,
DateValueCallback onConfirm,
})
```
#### 5\. DateTimePickerLocale
Support:
- en_us: English (EN) United States ***[Default locale]***
- ar: Arabic (ar)
- ar_eg: Arabic (ar) Egypt
- bn: Bengali (BN)
- bs: Bosnian (BS)
- de: German (DE)
- es: Spanish (ES)
- fr: French (FR)
- hr: Croatian (HR)
- hu: Hungarian (HU)
- in_id: Bahasa (IN) Indonesia
- it: Italian (IT)
- jp: Japanese (JP)
- ko: Korea (KO)
- nl: Dutch (NL)
- pt_br: Portuguese (PT) Brazil
- ro: Romanian (RO)
- ru: Russian (RU)
- sr_cyrl: Serbia (sr) Cyrillic
- sr_latn: Serbia (sr) Latin
- tr: Turkish (TR)
- uk: Ukraine (UK)
- vi: Vietnamese (VI) Vietnam
- zh_cn: Chinese (ZH) Simplified
##### Add more language
###### 1. Add language i18n file
Fork this project, add language file in `lib/src/i18n/` directory, e.g. `strings_en_us.dart`.
```dart
/// English (EN) United States
class _StringsEnUs extends _StringsI18n {
const _StringsEnUs();
@override
String getCancelText() {
// TODO return cancel widget's text
return null;
}
@override
String getDoneText() {
// TODO return done widget's text
return null;
}
@override
List<String> getMonths() {
// TODO return the array of month's full name [January, February ... December]
return null;
}
@override
List<String> getMonthsShort() {
// TODO return the array of month's short name [Jan, Feb ... Dec]. If return null, will substring the full name (max length is 3)
return null;
}
@override
List<String> getWeeksFull() {
// TODO return the array of week's full name [Monday, Tuesday ... Sunday]
return null;
}
@override
List<String> getWeeksShort() {
// TODO return the array of week's short name [Mon, Tue ... Sun]
return null;
}
}
```
###### 2. Add Locale
Add language locale in `lib/src/i18n/date_picker_i18n.dart` file.
```dart
enum DateTimePickerLocale {
/// English (EN) United States
en_us,
}
```
###### 3. Add Locale-Language relationship
Add language-locale relationship in `lib/src/i18n/date_picker_i18n.dart` file.
```dart
const Map<DateTimePickerLocale, _StringsI18n> datePickerI18n = {
DateTimePickerLocale.en_us: const _StringsEnUs(),
};
```
#### 6\. dateFormat
|Pattern|Meaning |e.g. |
|:----|:------------------------|:---------|
|yyyy |year |2019, 2020|
|yy |year, 2 digits |19, 20|
|MMMM |month |January(en_us), 01(zh_cn)|
|MMM |month, abbreviated |Jan(en_us), 01(zh_cn)|
|MM |month, 2 digits |01、11
|M |month |1, 11|
|dd |day in month, 2 digits |05, 25|
|d |day in month |5, 25|
|EEEE |day of week |Monday(en_us), 星期一(zh_cn)|
|EEE |day of week, abbreviated |Mon(en_us), 周一(zh_cn)|
|HH |hour (0~23), 2 digits |04, 12, 20|
|H |hour (0~23) |4, 12, 20|
|mm |minute, 2 digits |05, 40|
|m |minute |5, 40|
|ss |second, 2 digits |06, 55|
|s |second |6, 55|
|yyyy年|format |2019年, 2020年|
|H时 |format |5时, 21时|
##### Date Format Separator
Support separator: `|,-/\._: `.
#### 7\. DateTimePickerTheme
```dart
/// DateTimePicker theme.
///
/// [backgroundColor] DatePicker's background color.
/// [cancelTextStyle] Default cancel widget's [TextStyle].
/// [confirmTextStyle] Default confirm widget's [TextStyle].
/// [cancel] Custom cancel widget.
/// [confirm] Custom confirm widget.
/// [title] Custom title widget. If specify a title widget, the cancel and confirm widgets will not display. Must set [titleHeight] value for custom title widget.
/// [showTitle] Whether display title widget or not. If set false, the default cancel and confirm widgets will not display, but the custom title widget will display if had specified one custom title widget.
/// [pickerHeight] The value of DatePicker's height.
/// [titleHeight] The value of DatePicker's title height.
/// [itemHeight] The value of DatePicker's column height.
/// [itemTextStyle] The value of DatePicker's column [TextStyle].
const DateTimePickerTheme({
this.backgroundColor: DATETIME_PICKER_BACKGROUND_COLOR,
this.cancelTextStyle,
this.confirmTextStyle,
this.cancel,
this.confirm,
this.title,
this.showTitle: DATETIME_PICKER_SHOW_TITLE_DEFAULT,
this.pickerHeight: DATETIME_PICKER_HEIGHT,
this.titleHeight: DATETIME_PICKER_TITLE_HEIGHT,
this.itemHeight: DATETIME_PICKER_ITEM_HEIGHT,
this.itemTextStyle: DATETIME_PICKER_ITEM_TEXT_STYLE,
});
```
## Example
[Example sources](https://github.com/wuzhendev/flutter-cupertino-date-picker/tree/master/example)
[Example APK](https://raw.githubusercontent.com/wuzhendev/assets/master/flutter-datepicker/flutter_cupertino_date_picker_v1.0.8.apk)
![Example APK Download](https://github.com/wuzhendev/assets/blob/master/flutter-datepicker/date_picker_qrcode_v1.0.8.png?raw=true)
### DatePicker
![Example: DatePicker][1]
![Example: DatePickerWidget][2]
### TimePicker
![Example: TimePicker][3]
![Example: TimePickerWidget][4]
### DateTimePicker
![Example: DateTimePicker][5]
![Example: DateTimePickerWidget][6]
## License
```
Copyright 2018 wuzhen
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
```
[1]:https://github.com/wuzhendev/assets/blob/master/flutter-datepicker/flutter_date_picker_14.jpg?raw=true
[2]:https://github.com/wuzhendev/assets/blob/master/flutter-datepicker/flutter_date_picker_15.jpg?raw=true
[3]:https://github.com/wuzhendev/assets/blob/master/flutter-datepicker/flutter_date_picker_16.jpg?raw=true
[4]:https://github.com/wuzhendev/assets/blob/master/flutter-datepicker/flutter_date_picker_17.jpg?raw=true
[5]:https://github.com/wuzhendev/assets/blob/master/flutter-datepicker/flutter_date_picker_18.jpg?raw=true
[6]:https://github.com/wuzhendev/assets/blob/master/flutter-datepicker/flutter_date_picker_19.jpg?raw=true
# Flutter Cupertino Date Picker
[[Pub Packages]](https://pub.dartlang.org/packages/flutter_cupertino_date_picker)
Flutter 的日期选择器控件,iOS 样式。
![示例][1]
## 用法
#### 1\. 添加依赖
在项目的 `pubspec.yaml` 文件中添加依赖:
```yaml
dependencies:
flutter_cupertino_date_picker: ^1.0.26+2
```
#### 2\. 获取包
执行 Flutter 的命令获取包资源:
```bash
$ flutter packages get
```
#### 3\. 导入控件
在项目中导入该控件:
```dart
import 'package:flutter_cupertino_date_picker/flutter_cupertino_date_picker.dart';
```
#### 4\. 显示控件
##### BottomSheet形式
```dart
/// 显示BottomSheet形式的日期时间选择器。
///
/// context: [BuildContext]
/// minDateTime: [DateTime] 日期选择器的最小值
/// maxDateTime: [DateTime] 日期选择器的最大值
/// initialDateTime: [DateTime] 日期选择器的初始值
/// dateFormat: [String] 日期时间格式化
/// locale: [DateTimePickerLocale] 国际化,语言地区
/// pickerMode: [DateTimePickerMode] 显示的类型: date(日期选择器)、time(时间选择器)、datetime(日期时间选择器)
/// pickerTheme: [DateTimePickerTheme] 日期选择器的样式
/// onCancel: [DateVoidCallback] 点击标题取消按钮的回调事件
/// onClose: [DateVoidCallback] 关闭日期时间选择器的回调事件
/// onChange: [DateValueCallback] 选择的日期时间改变的事件
/// onConfirm: [DateValueCallback] 点击标题确定按钮的回调事件
DatePicker.showDatePicker(
BuildContext context,
DateTime minDateTime,
DateTime maxDateTime,
DateTime initialDateTime,
String dateFormat,
DateTimePickerLocale locale: DATETIME_PICKER_LOCALE_DEFAULT,
DateTimePickerMode pickerMode: DateTimePickerMode.date,
DateTimePickerTheme pickerTheme: DatePickerTheme.Default,
DateVoidCallback onCancel,
DateVoidCallback onClose,
DateValueCallback onChange,
DateValueCallback onConfirm,
});
```
##### 日期选择器控件,可以在页面上显示
```dart
/// 显示日期选择器
///
/// minDateTime: [DateTime] 日期选择器的最小值
/// maxDateTime: [DateTime] 日期选择器的最大值
/// initialDateTime: [DateTime] 日期选择器的初始值
/// dateFormat: [String] 日期时间格式化
/// locale: [DateTimePickerLocale] 国际化,语言地区
/// pickerTheme: [DateTimePickerTheme] 日期选择器的样式
/// onCancel: [DateVoidCallback] 点击标题取消按钮的回调事件
/// onChange: [DateValueCallback] 选择的日期时间改变的事件
/// onConfirm: [DateValueCallback] 点击标题确定按钮的回调事件
DatePickerWidget({
DateTime minDateTime,
DateTime maxDateTime,
DateTime initialDateTime,
String dateFormat: DATETIME_PICKER_DATE_FORMAT,
DateTimePickerLocale locale: DATETIME_PICKER_LOCALE_DEFAULT,
DateTimePickerTheme pickerTheme: DatePickerTheme.Default,
DateVoidCallback onCancel,
DateValueCallback onChange,
DateValueCallback onConfirm,
})
```
##### TimePicker Widget
```dart
/// 显示时间选择器
///
/// minDateTime: [DateTime] 日期选择器的最小值
/// maxDateTime: [DateTime] 日期选择器的最大值
/// initialDateTime: [DateTime] 日期选择器的初始值
/// dateFormat: [String] 日期时间格式化
/// locale: [DateTimePickerLocale] 国际化,语言地区
/// pickerTheme: [DateTimePickerTheme] 日期选择器的样式
/// minuteDivider: [int] minute restriction, e.g. 5: every 5th minute will be shown (0, 5, 10, 15 ...)
/// onCancel: [DateVoidCallback] 点击标题取消按钮的回调事件
/// onChange: [DateValueCallback] 选择的日期时间改变的事件
/// onConfirm: [DateValueCallback] 点击标题确定按钮的回调事件
TimePickerWidget({
DateTime minDateTime,
DateTime maxDateTime,
DateTime initialDateTime,
String dateFormat: DATETIME_PICKER_DATE_FORMAT,
DateTimePickerLocale locale: DATETIME_PICKER_LOCALE_DEFAULT,
DateTimePickerTheme pickerTheme: DatePickerTheme.Default,
int minuteDivider: 1,
DateVoidCallback onCancel,
DateValueCallback onChange,
DateValueCallback onConfirm,
})
```
##### DateTimePicker Widget
```dart
/// 显示日期时间选择器
///
/// minDateTime: [DateTime] 日期选择器的最小值
/// maxDateTime: [DateTime] 日期选择器的最大值
/// initialDateTime: [DateTime] 日期选择器的初始值
/// dateFormat: [String] 日期时间格式化
/// locale: [DateTimePickerLocale] 国际化,语言地区
/// pickerTheme: [DateTimePickerTheme] 日期选择器的样式
/// onCancel: [DateVoidCallback] 点击标题取消按钮的回调事件
/// onChange: [DateValueCallback] 选择的日期时间改变的事件
/// onConfirm: [DateValueCallback] 点击标题确定按钮的回调事件
DateTimePickerWidget({
DateTime minDateTime,
DateTime maxDateTime,
DateTime initialDateTime,
String dateFormat: DATETIME_PICKER_DATE_FORMAT,
DateTimePickerLocale locale: DATETIME_PICKER_LOCALE_DEFAULT,
DateTimePickerTheme pickerTheme: DatePickerTheme.Default,
DateVoidCallback onCancel,
DateValueCallback onChange,
DateValueCallback onConfirm,
})
```
#### 5\. DateTimePickerLocale
多语言支持:
- en_us: 美式英语 ***[Default locale]***
- ar: 阿拉伯语
- ar_eg: 阿拉伯语(埃及)
- bn: 孟加拉语
- bs: 波斯尼亚语
- de: 德语
- es: 西班牙语
- fr: 法语
- hr: 克罗地亚语
- hu: 匈牙利语
- in_id: 印尼语
- it: 意大利语
- jp: 日语
- ko: 韩语
- nl: 荷兰语
- pt_br: 葡萄牙语(巴西)
- ro: 罗马尼亚语
- ru: 俄语
- sr_cyrl: 塞尔维亚(西里尔)
- sr_latn: 塞尔维亚(拉丁文)
- tr: 土耳其语
- uk: 乌克兰语
- vi: 越南语
- zh_cn: 简体中文
##### 添加更多的语言
###### 1. 添加语言文件
Fork 该项目, 在 `lib/src/i18n/` 文件夹中添加语言文件。参考 `strings_en_us.dart` 文件。
```dart
/// English (EN) United States
class _StringsEnUs extends _StringsI18n {
const _StringsEnUs();
@override
String getCancelText() {
// TODO 返回标题栏取消按钮的显示文字
return null;
}
@override
String getDoneText() {
// TODO 返回标题栏确定按钮的显示文字
return null;
}
@override
List<String> getMonths() {
// TODO 返回月份的全称 [1月, 2月 ... 12月]
return null;
}
@override
List<String> getMonthsShort() {
// TODO 返回月份的简称 [Jan, Feb ... Dec],返回null默认对全程进行截取,最多截取3位
return null;
}
@override
List<String> getWeeksFull() {
// TODO 返回星期几的全称 [周一, 周二 ... 周日]
return null;
}
@override
List<String> getWeeksShort() {
// TODO 返回星期几的缩写 [周一, 周二 ... 周日]
return null;
}
}
```
###### 2. 添加 DateTimePickerLocale
`lib/src/i18n/date_picker_i18n.dart` 文件中添加新语言对应的 `DateTimePickerLocale`
```dart
enum DateTimePickerLocale {
/// English (EN) United States
en_us,
}
```
###### 3. 添加 DateTimePickerLocale 和语言的对应关系
`lib/src/i18n/date_picker_i18n.dart` 文件中添加 DateTimePickerLocale 和语言的对应关系。
```dart
const Map<DateTimePickerLocale, _StringsI18n> datePickerI18n = {
DateTimePickerLocale.en_us: const _StringsEnUs(),
};
```
#### 6\. dateFormat
|Pattern|Meaning |e.g. |
|:----|:----------------|:----------|
|yyyy |年份 |2019, 2020|
|yy |年份, 2位数字 |19, 20|
|MMMM |月份 |January(en_us), 01(zh_cn)|
|MMM |月份, 缩写 |Jan(en_us), 01(zh_cn)|
|MM |月份, 2位数字 |01、11
|M |月份 |1, 11|
|dd |日期, 2位数字 |05, 25|
|d |日期 |5, 25|
|EEEE |星期 |Monday(en_us), 星期一(zh_cn)|
|EEE |星期, 缩写 |Mon(en_us), 周一(zh_cn)|
|HH |时 (0~23), 2位数字 |04, 12, 20|
|H |时 (0~23) |4, 12, 20|
|mm |分, 2位数字 |05, 40|
|m |分 |5, 40|
|ss |秒, 2位数字 |06, 55|
|s |秒 |6, 55|
|yyyy年|格式化 |2019年, 2020年|
|H时 |格式化 |5时, 21时|
##### Date Format Separator
支持的分隔符: `|,-/\._: `.
#### 7\. DateTimePickerTheme
```dart
/// 日期时间选择器的样式
///
/// [backgroundColor] 背景色
/// [cancelTextStyle] 默认标题栏取消按钮的样式 [TextStyle]
/// [confirmTextStyle] 默认标题栏确定按钮的样式 [TextStyle]
/// [cancel] 自定义标题栏取消按钮
/// [confirm] 自定义标题栏确定按钮
/// [title] 自定义标题栏。如果指定了自定义标题栏,不显示默认的标题栏。指定自定义的标题栏时必须指定 [titleHeight] 的值
/// [showTitle] 是否显示默认的标题栏。如果设置为false,默认的取消、确定按钮都不会显示,自定义的标题栏不受影响
/// [pickerHeight] 日期选择器的高度
/// [titleHeight] 标题栏的高度
/// [itemHeight] 选择器每一行的高度
/// [itemTextStyle] 选择器每一行的样式 [TextStyle]
const DateTimePickerTheme({
this.backgroundColor: DATETIME_PICKER_BACKGROUND_COLOR,
this.cancelTextStyle,
this.confirmTextStyle,
this.cancel,
this.confirm,
this.title,
this.showTitle: DATETIME_PICKER_SHOW_TITLE_DEFAULT,
this.pickerHeight: DATETIME_PICKER_HEIGHT,
this.titleHeight: DATETIME_PICKER_TITLE_HEIGHT,
this.itemHeight: DATETIME_PICKER_ITEM_HEIGHT,
this.itemTextStyle: DATETIME_PICKER_ITEM_TEXT_STYLE,
});
```
## Example
[Example sources](https://github.com/wuzhendev/flutter-cupertino-date-picker/tree/master/example)
[Example APK](https://raw.githubusercontent.com/wuzhendev/assets/master/flutter-datepicker/flutter_cupertino_date_picker_v1.0.8.apk)
![Example APK Download](https://github.com/wuzhendev/assets/blob/master/flutter-datepicker/date_picker_qrcode_v1.0.8.png?raw=true)
### DatePicker
![Example: DatePicker][1]
![Example: DatePickerWidget][2]
### TimePicker
![Example: TimePicker][3]
![Example: TimePickerWidget][4]
### DateTimePicker
![Example: DateTimePicker][5]
![Example: DateTimePickerWidget][6]
## License
```
Copyright 2018 wuzhen
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
```
[1]:https://github.com/wuzhendev/assets/blob/master/flutter-datepicker/flutter_date_picker_14.jpg?raw=true
[2]:https://github.com/wuzhendev/assets/blob/master/flutter-datepicker/flutter_date_picker_15.jpg?raw=true
[3]:https://github.com/wuzhendev/assets/blob/master/flutter-datepicker/flutter_date_picker_16.jpg?raw=true
[4]:https://github.com/wuzhendev/assets/blob/master/flutter-datepicker/flutter_date_picker_17.jpg?raw=true
[5]:https://github.com/wuzhendev/assets/blob/master/flutter-datepicker/flutter_date_picker_18.jpg?raw=true
[6]:https://github.com/wuzhendev/assets/blob/master/flutter-datepicker/flutter_date_picker_19.jpg?raw=true
*.iml
*.class
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
GeneratedPluginRegistrant.java
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
apply plugin: 'com.android.application'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion 27
lintOptions {
disable 'InvalidPackage'
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.flutter.flutterdatepicker"
minSdkVersion 16
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
}
}
}
flutter {
source '../..'
}
dependencies {
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.flutter.flutterdatepicker">
<!-- The INTERNET permission is required for development. Specifically,
flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<application
android:name="io.flutter.app.FlutterApplication"
android:label="flutter_date_picker"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- This keeps the window background of the activity showing
until Flutter renders its first frame. It can be removed if
there is no splash screen (such as the default splash screen
defined in @style/LaunchTheme). -->
<meta-data
android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
android:value="true" />
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
package com.flutter.flutterdatepicker;
import android.os.Bundle;
import io.flutter.app.FlutterActivity;
import io.flutter.plugins.GeneratedPluginRegistrant;
public class MainActivity extends FlutterActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
}
}
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
Flutter draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
</resources>
buildscript {
repositories {
google()
jcenter()
maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
}
}
allprojects {
repositories {
google()
jcenter()
maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
delete rootProject.buildDir
}
org.gradle.jvmargs=-Xmx1536M
#Fri Jun 23 08:50:38 CEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
include ':app'
def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
if (pluginsFile.exists()) {
pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
}
plugins.each { name, path ->
def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
include ":$name"
project(":$name").projectDir = pluginDirectory
}
.DS_Store
.dart_tool/
.packages
.pub/
build/
.flutter-plugins
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: c7ea3ca377e909469c68f2ab878a5bc53d3cf66b
channel: beta
# Date Picker Example
A Flutter application example of DatePicker.
## Getting Started
For help getting started with Flutter, view our online
[documentation](https://flutter.io/).
*.iml
*.class
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
GeneratedPluginRegistrant.java
/keystore.properties
/key.properties
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
apply plugin: 'com.android.application'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion 28
lintOptions {
disable 'InvalidPackage'
}
defaultConfig {
applicationId "com.flutter.datepicker.example"
minSdkVersion 16
targetSdkVersion 28
versionCode 2
versionName "1.0.8"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
signingConfigs {
release {
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
}
flutter {
source '../..'
}
dependencies {
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.flutter.datepicker.example">
<!-- The INTERNET permission is required for development. Specifically,
flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<application
android:name="io.flutter.app.FlutterApplication"
android:label="DatePicker"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- This keeps the window background of the activity showing
until Flutter renders its first frame. It can be removed if
there is no splash screen (such as the default splash screen
defined in @style/LaunchTheme). -->
<meta-data
android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
android:value="true" />
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
package com.flutter.datepicker.example;
import android.os.Bundle;
import io.flutter.app.FlutterActivity;
import io.flutter.plugins.GeneratedPluginRegistrant;
public class MainActivity extends FlutterActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
}
}
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
Flutter draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
</resources>
buildscript {
repositories {
mavenLocal()
maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.4.2'
}
}
allprojects {
repositories {
mavenLocal()
maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
google()
jcenter()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
delete rootProject.buildDir
}
org.gradle.jvmargs=-Xmx1536M
android.enableR8=true
#Fri Jun 23 08:50:38 CEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
include ':app'
def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
if (pluginsFile.exists()) {
pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
}
plugins.each { name, path ->
def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
include ":$name"
project(":$name").projectDir = pluginDirectory
}
.idea/
.vagrant/
.sconsign.dblite
.svn/
.DS_Store
*.swp
profile
DerivedData/
build/
GeneratedPluginRegistrant.h
GeneratedPluginRegistrant.m
.generated/
*.pbxuser
*.mode1v3
*.mode2v3
*.perspectivev3
!default.pbxuser
!default.mode1v3
!default.mode2v3
!default.perspectivev3
xcuserdata
*.moved-aside
*.pyc
*sync/
Icon?
.tags*
/Flutter/app.flx
/Flutter/app.zip
/Flutter/flutter_assets/
/Flutter/App.framework
/Flutter/Flutter.framework
/Flutter/Generated.xcconfig
/ServiceDefinitions.json
Pods/
.symlinks/
flutter_export_environment.sh
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>App</string>
<key>CFBundleIdentifier</key>
<string>io.flutter.flutter.app</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>App</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>8.0</string>
</dict>
</plist>
#include "Generated.xcconfig"
#include "Generated.xcconfig"
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */ = {isa = PBXBuildFile; fileRef = 2D5378251FAA1A9400D5DBA9 /* flutter_assets */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };
3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; };
9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; };
9740EEB51CF90195004384FC /* Generated.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB31CF90195004384FC /* Generated.xcconfig */; };
978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; };
97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */,
9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
2D5378251FAA1A9400D5DBA9 /* flutter_assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = flutter_assets; path = Flutter/flutter_assets; sourceTree = SOURCE_ROOT; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
97C146EB1CF9000F007C117D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */,
3B80C3941E831B6300D905FE /* App.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
2D5378251FAA1A9400D5DBA9 /* flutter_assets */,
3B80C3931E831B6300D905FE /* App.framework */,
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEBA1CF902C7004384FC /* Flutter.framework */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
9740EEB31CF90195004384FC /* Generated.xcconfig */,
);
name = Flutter;
sourceTree = "<group>";
};
97C146E51CF9000F007C117D = {
isa = PBXGroup;
children = (
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
);
sourceTree = "<group>";
};
97C146EF1CF9000F007C117D /* Products */ = {
isa = PBXGroup;
children = (
97C146EE1CF9000F007C117D /* Runner.app */,
);
name = Products;
sourceTree = "<group>";
};
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */,
7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */,
97C146FA1CF9000F007C117D /* Main.storyboard */,
97C146FD1CF9000F007C117D /* Assets.xcassets */,
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
97C147021CF9000F007C117D /* Info.plist */,
97C146F11CF9000F007C117D /* Supporting Files */,
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
);
path = Runner;
sourceTree = "<group>";
};
97C146F11CF9000F007C117D /* Supporting Files */ = {
isa = PBXGroup;
children = (
97C146F21CF9000F007C117D /* main.m */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
97C146ED1CF9000F007C117D /* Runner */ = {
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
);
buildRules = (
);
dependencies = (
);
name = Runner;
productName = Runner;
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0910;
ORGANIZATIONNAME = "The Chromium Authors";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
CreatedOnToolsVersion = 7.3.1;
DevelopmentTeam = PWRV2ZB7PD;
};
};
};
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 97C146E51CF9000F007C117D;
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
97C146ED1CF9000F007C117D /* Runner */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
97C146EC1CF9000F007C117D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
9740EEB51CF90195004384FC /* Generated.xcconfig in Resources */,
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Thin Binary";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin";
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Run Script";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
97C146EA1CF9000F007C117D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */,
97C146F31CF9000F007C117D /* main.m in Sources */,
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C146FB1CF9000F007C117D /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C147001CF9000F007C117D /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
97C147031CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
97C147041CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
97C147061CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = PWRV2ZB7PD;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = com.flutter.datepicker.example;
PRODUCT_NAME = "$(TARGET_NAME)";
VERSIONING_SYSTEM = "apple-generic";
};
name = Debug;
};
97C147071CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = PWRV2ZB7PD;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = com.flutter.datepicker.example;
PRODUCT_NAME = "$(TARGET_NAME)";
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147031CF9000F007C117D /* Debug */,
97C147041CF9000F007C117D /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147061CF9000F007C117D /* Debug */,
97C147071CF9000F007C117D /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 97C146E61CF9000F007C117D /* Project object */;
}
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
</Workspace>
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0910"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
</Workspace>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BuildSystemType</key>
<string>Original</string>
</dict>
</plist>
#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>
@interface AppDelegate : FlutterAppDelegate
@end
#include "AppDelegate.h"
#include "GeneratedPluginRegistrant.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[GeneratedPluginRegistrant registerWithRegistry:self];
// Override point for customization after application launch.
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
@end
{
"images" : [
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@3x.png",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@3x.png",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@3x.png",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@2x.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@3x.png",
"scale" : "3x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@1x.png",
"scale" : "1x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@1x.png",
"scale" : "1x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@1x.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@2x.png",
"scale" : "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "Icon-App-83.5x83.5@2x.png",
"scale" : "2x"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "Icon-App-1024x1024@1x.png",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
{
"images" : [
{
"idiom" : "universal",
"filename" : "LaunchImage.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
# Launch Screen Assets
You can customize the launch screen with your own desired assets by replacing the image files in this directory.
You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
</imageView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
<resources>
<image name="LaunchImage" width="168" height="185"/>
</resources>
</document>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<scenes>
<!--Flutter View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>datepickerexample</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>example</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
</dict>
</plist>
#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char* argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
import 'package:flutter/material.dart';
import 'package:flutter_cupertino_date_picker/flutter_cupertino_date_picker.dart';
class DatePickerBottomSheet extends StatefulWidget {
DatePickerBottomSheet({Key key}) : super(key: key);
@override
State<StatefulWidget> createState() => _DatePickerBottomSheetState();
}
const String MIN_DATETIME = '2010-05-12';
const String MAX_DATETIME = '2021-11-25';
const String INIT_DATETIME = '2019-05-17';
class _DatePickerBottomSheetState extends State<DatePickerBottomSheet> {
bool _showTitle = true;
DateTimePickerLocale _locale = DateTimePickerLocale.en_us;
List<DateTimePickerLocale> _locales = DateTimePickerLocale.values;
String _format = 'yyyy-MMMM-dd';
TextEditingController _formatCtrl = TextEditingController();
DateTime _dateTime;
@override
void initState() {
super.initState();
_formatCtrl.text = _format;
_dateTime = DateTime.parse(INIT_DATETIME);
}
@override
Widget build(BuildContext context) {
// create locale radio list
List<Widget> radios = List<Widget>();
_locales.forEach((locale) {
radios.add(Container(
margin: EdgeInsets.only(right: 8.0),
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Radio(
value: locale,
groupValue: _locale,
onChanged: (value) {
setState(() {
_locale = value;
});
},
),
Text(locale
.toString()
.substring(locale.toString().indexOf('.') + 1)),
],
),
));
});
TextStyle hintTextStyle =
Theme.of(context).textTheme.subhead.apply(color: Color(0xFF999999));
return Scaffold(
appBar: AppBar(title: Text('DatePicker Bottom Sheet')),
body: Container(
padding: EdgeInsets.all(16.0),
child: Column(
children: <Widget>[
// min datetime hint
Padding(
padding: EdgeInsets.only(bottom: 8.0),
child: Row(
children: <Widget>[
Container(
width: 115.0,
child: Text('min DateTime:', style: hintTextStyle),
),
Text(MIN_DATETIME,
style: Theme.of(context).textTheme.subhead),
],
),
),
// max datetime hint
Padding(
padding: EdgeInsets.only(bottom: 8.0),
child: Row(
children: <Widget>[
Container(
width: 115.0,
child: Text('max DateTime:', style: hintTextStyle)),
Text(MAX_DATETIME,
style: Theme.of(context).textTheme.subhead),
],
),
),
// init datetime hint
Padding(
padding: EdgeInsets.only(bottom: 8.0),
child: Row(
children: <Widget>[
Container(
width: 115.0,
child: Text('init DateTime:', style: hintTextStyle)),
Text(INIT_DATETIME,
style: Theme.of(context).textTheme.subhead),
],
),
),
// show title widget checkbox
Row(
children: <Widget>[
Text('show title'),
Checkbox(
value: _showTitle,
onChanged: (value) {
setState(() {
_showTitle = value;
});
},
)
],
),
// date format input field
TextField(
controller: _formatCtrl,
keyboardType: TextInputType.url,
decoration: InputDecoration(
labelText: 'Date Format',
hintText: 'yyyy-MM-dd',
hintStyle: TextStyle(color: Colors.black26),
),
onChanged: (value) {
_format = value;
},
),
// locale check radio group
Container(
width: double.infinity,
margin: EdgeInsets.only(top: 16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Locale: '),
Wrap(direction: Axis.horizontal, children: radios)
],
),
),
// selected date
Container(
margin: EdgeInsets.only(top: 40.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text('Selected Date:',
style: Theme.of(context).textTheme.subhead),
Container(
padding: EdgeInsets.only(left: 12.0),
child: Text(
'${_dateTime.year}-${_dateTime.month.toString().padLeft(2, '0')}-${_dateTime.day.toString().padLeft(2, '0')}',
style: Theme.of(context).textTheme.title,
),
),
],
),
),
],
),
),
// display DatePicker floating action button
floatingActionButton: FloatingActionButton(
onPressed: _showDatePicker,
tooltip: 'Show DatePicker',
child: Icon(Icons.date_range),
),
);
}
/// Display date picker.
void _showDatePicker() {
DatePicker.showDatePicker(
context,
onMonthChangeStartWithFirstDate: true,
pickerTheme: DateTimePickerTheme(
showTitle: _showTitle,
confirm: Text('custom Done', style: TextStyle(color: Colors.red)),
),
minDateTime: DateTime.parse(MIN_DATETIME),
maxDateTime: DateTime.parse(MAX_DATETIME),
initialDateTime: _dateTime,
dateFormat: _format,
locale: _locale,
onClose: () => print("----- onClose -----"),
onCancel: () => print('onCancel'),
onChange: (dateTime, List<int> index) {
setState(() {
_dateTime = dateTime;
});
},
onConfirm: (dateTime, List<int> index) {
setState(() {
_dateTime = dateTime;
});
},
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter_cupertino_date_picker/flutter_cupertino_date_picker.dart';
///
/// @author dylan wu
/// @since 2019-05-10
class DatePickerInPage extends StatefulWidget {
DatePickerInPage({Key key}) : super(key: key);
@override
State<StatefulWidget> createState() => _DatePickerInPageState();
}
const String MIN_DATETIME = '2010-05-12';
const String MAX_DATETIME = '2021-11-25';
const String INIT_DATETIME = '2019-05-17';
const String DATE_FORMAT = 'MM月|d日,yyyy年';
class _DatePickerInPageState extends State<DatePickerInPage> {
DateTime _dateTime;
@override
void initState() {
super.initState();
_dateTime = DateTime.parse(INIT_DATETIME);
}
@override
Widget build(BuildContext context) {
TextStyle hintTextStyle =
Theme.of(context).textTheme.subhead.apply(color: Color(0xFF999999));
return Scaffold(
appBar: AppBar(title: Text("DatePicker In Page")),
body: Container(
decoration: BoxDecoration(color: Colors.white),
padding: EdgeInsets.all(16.0),
child: Column(
children: <Widget>[
// min datetime hint
Padding(
padding: EdgeInsets.only(bottom: 8.0),
child: Row(
children: <Widget>[
Container(
width: 115.0,
child: Text('min DateTime:', style: hintTextStyle),
),
Text(MIN_DATETIME,
style: Theme.of(context).textTheme.subhead),
],
),
),
// max datetime hint
Padding(
padding: EdgeInsets.only(bottom: 8.0),
child: Row(
children: <Widget>[
Container(
width: 115.0,
child: Text('max DateTime:', style: hintTextStyle)),
Text(MAX_DATETIME,
style: Theme.of(context).textTheme.subhead),
],
),
),
// init datetime hint
Padding(
padding: EdgeInsets.only(bottom: 8.0),
child: Row(
children: <Widget>[
Container(
width: 115.0,
child: Text('init DateTime:', style: hintTextStyle),
),
Text(INIT_DATETIME,
style: Theme.of(context).textTheme.subhead),
],
),
),
// date format
Padding(
padding: EdgeInsets.only(bottom: 8.0),
child: Row(
children: <Widget>[
Container(
width: 115.0,
child: Text('Date Format:', style: hintTextStyle),
),
Text(DATE_FORMAT, style: Theme.of(context).textTheme.subhead),
],
),
),
// date picker theme
GestureDetector(
onTap: () {
showDialog(
context: context,
builder: (_) => new AlertDialog(
titlePadding: EdgeInsets.only(left: 16.0, top: 16.0),
title: new Text("DateTimePickerTheme"),
contentPadding: EdgeInsets.all(16.0),
content: new Text(
'''
DateTimePickerTheme(
backgroundColor: Color(0xFF80cbc4),
cancelTextStyle: TextStyle(color: Colors.white),
confirmTextStyle: TextStyle(color: Colors.black),
itemTextStyle: TextStyle(color: Colors.deepOrange),
pickerHeight: 300.0,
titleHeight: 24.0,
itemHeight: 30.0,
)
''',
style: TextStyle(fontSize: 14.0),
),
actions: <Widget>[
new FlatButton(
child: new Text("OK"),
onPressed: () {
Navigator.of(context).pop();
},
)
],
),
);
},
child: Padding(
padding: EdgeInsets.only(bottom: 8.0),
child: Row(
children: <Widget>[
Container(
child:
Text('DateTimePickerTheme ', style: hintTextStyle),
),
Icon(Icons.remove_red_eye, color: Color(0xFF03a9f4)),
],
),
),
),
// date picker widget
Container(
margin: EdgeInsets.only(top: 24.0, bottom: 40.0),
child: DatePickerWidget(
minDateTime: DateTime.parse(MIN_DATETIME),
maxDateTime: DateTime.parse(MAX_DATETIME),
initialDateTime: DateTime.parse(INIT_DATETIME),
dateFormat: DATE_FORMAT,
pickerTheme: DateTimePickerTheme(
backgroundColor: Color(0xFFb2dfdb),
cancelTextStyle: TextStyle(color: Colors.white),
confirmTextStyle: TextStyle(color: Colors.black),
itemTextStyle: TextStyle(color: Colors.deepOrange),
pickerHeight: 300.0,
titleHeight: 24.0,
itemHeight: 30.0,
),
onChange: (dateTime, selectedIndex) {
setState(() {
_dateTime = dateTime;
});
},
),
),
// selected date
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text('Selected Date:',
style: Theme.of(context).textTheme.subhead),
Container(
padding: EdgeInsets.only(left: 12.0),
child: Text(
_dateTime != null
? '${_dateTime.year}-${_dateTime.month.toString().padLeft(2, '0')}-${_dateTime.day.toString().padLeft(2, '0')}'
: '',
style: Theme.of(context).textTheme.title,
),
),
],
),
],
),
),
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter_cupertino_date_picker/flutter_cupertino_date_picker.dart';
class DateTimePickerBottomSheet extends StatefulWidget {
DateTimePickerBottomSheet({Key key}) : super(key: key);
@override
State<StatefulWidget> createState() => _DateTimePickerBottomSheetState();
}
const String MIN_DATETIME = '2019-05-15 09:23:10';
const String MAX_DATETIME = '2019-06-03 21:11:00';
const String INIT_DATETIME = '2019-05-16 09:00:00';
class _DateTimePickerBottomSheetState extends State<DateTimePickerBottomSheet> {
bool _showTitle = true;
String _format = 'yy年M月d日 EEE,H时:m分';
TextEditingController _formatCtrl = TextEditingController();
DateTimePickerLocale _locale = DateTimePickerLocale.zh_cn;
List<DateTimePickerLocale> _locales = DateTimePickerLocale.values;
DateTime _dateTime;
@override
void initState() {
super.initState();
_formatCtrl.text = _format;
_dateTime = DateTime.parse(INIT_DATETIME);
}
/// Display time picker.
void _showDateTimePicker() {
DatePicker.showDatePicker(
context,
minDateTime: DateTime.parse(MIN_DATETIME),
maxDateTime: DateTime.parse(MAX_DATETIME),
initialDateTime: DateTime.parse(INIT_DATETIME),
dateFormat: _format,
locale: _locale,
pickerTheme: DateTimePickerTheme(
showTitle: _showTitle,
),
pickerMode: DateTimePickerMode.datetime, // show TimePicker
onCancel: () {
debugPrint('onCancel');
},
onChange: (dateTime, List<int> index) {
setState(() {
_dateTime = dateTime;
});
},
onConfirm: (dateTime, List<int> index) {
setState(() {
_dateTime = dateTime;
});
},
);
}
@override
Widget build(BuildContext context) {
List<Widget> radios = List<Widget>();
_locales.forEach((locale) {
radios.add(Container(
margin: EdgeInsets.only(right: 8.0),
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Radio(
value: locale,
groupValue: _locale,
onChanged: (value) {
setState(() {
_locale = value;
});
}),
Text(locale
.toString()
.substring(locale.toString().indexOf('.') + 1)),
],
),
));
});
TextStyle hintTextStyle =
Theme.of(context).textTheme.subhead.apply(color: Color(0xFF999999));
return Scaffold(
appBar: AppBar(title: Text('DateTimePicker Bottom Sheet')),
body: Container(
padding: EdgeInsets.all(16.0),
child: Column(
children: <Widget>[
// min datetime hint
Padding(
padding: EdgeInsets.only(bottom: 8.0),
child: Row(
children: <Widget>[
Container(
width: 115.0,
child: Text('min DateTime:', style: hintTextStyle),
),
Text(MIN_DATETIME,
style: Theme.of(context).textTheme.subhead),
],
),
),
// max datetime hint
Padding(
padding: EdgeInsets.only(bottom: 8.0),
child: Row(
children: <Widget>[
Container(
width: 115.0,
child: Text('max DateTime:', style: hintTextStyle),
),
Text(MAX_DATETIME,
style: Theme.of(context).textTheme.subhead),
],
),
),
// init datetime hint
Padding(
padding: EdgeInsets.only(bottom: 8.0),
child: Row(
children: <Widget>[
Container(
width: 115.0,
child: Text('init DateTime:', style: hintTextStyle),
),
Text(INIT_DATETIME,
style: Theme.of(context).textTheme.subhead),
],
),
),
// show title widget checkbox
Container(
height: 30.0,
margin: EdgeInsets.only(top: 16.0),
child: Row(
children: <Widget>[
Text('show title actions', style: TextStyle(fontSize: 16.0)),
Checkbox(
value: _showTitle,
onChanged: (value) {
setState(() {
_showTitle = value;
});
})
],
),
),
// date format input field
TextField(
controller: _formatCtrl,
keyboardType: TextInputType.url,
decoration: InputDecoration(
labelText: 'Date Format: ',
hintText: 'yyyyMMdd HH:mm:ss / H:m / H时:m分',
hintStyle: TextStyle(color: Colors.black26),
),
onChanged: (value) => _format = value,
),
// locale check radio group
Container(
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Locale: '),
Wrap(direction: Axis.horizontal, children: radios)
],
),
),
// selected date time
Container(
width: double.infinity,
margin: EdgeInsets.only(top: 40.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Selected DateTime:',
style: Theme.of(context).textTheme.subhead),
Container(
padding: EdgeInsets.only(top: 4.0),
child: Text(
'${_dateTime.year}-${_dateTime.month.toString().padLeft(2, '0')}-${_dateTime.day.toString().padLeft(2, '0')} ${_dateTime.hour.toString().padLeft(2, '0')}:${_dateTime.minute.toString().padLeft(2, '0')}:${_dateTime.second.toString().padLeft(2, '0')}',
style: Theme.of(context).textTheme.title,
),
),
],
),
),
],
),
),
// display DateTimePicker floating action button
floatingActionButton: FloatingActionButton(
onPressed: _showDateTimePicker,
tooltip: 'Show DateTimePicker',
child: Icon(Icons.access_time),
),
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter_cupertino_date_picker/flutter_cupertino_date_picker.dart';
///
/// @author dylan wu
/// @since 2019-05-10
class DateTimePickerInPage extends StatefulWidget {
DateTimePickerInPage({Key key}) : super(key: key);
@override
State<StatefulWidget> createState() => _DateTimePickerInPageState();
}
const String MIN_DATETIME = '2019-05-15 20:10:55';
const String MAX_DATETIME = '2019-07-01 12:30:40';
const String INIT_DATETIME = '2019-05-16 09:00:58';
const String DATE_FORMAT = 'yyyy-MM-dd,H时:m分';
class _DateTimePickerInPageState extends State<DateTimePickerInPage> {
DateTime _dateTime;
@override
void initState() {
super.initState();
_dateTime = DateTime.parse(INIT_DATETIME);
}
@override
Widget build(BuildContext context) {
TextStyle hintTextStyle =
Theme.of(context).textTheme.subhead.apply(color: Color(0xFF999999));
return Scaffold(
appBar: AppBar(title: Text("DateTimePicker In Page")),
body: Container(
decoration: BoxDecoration(color: Colors.white),
padding: EdgeInsets.all(16.0),
child: Column(
children: <Widget>[
// min datetime hint
Padding(
padding: EdgeInsets.only(bottom: 8.0),
child: Row(
children: <Widget>[
Container(
width: 115.0,
child: Text('min DateTime:', style: hintTextStyle),
),
Text(MIN_DATETIME,
style: Theme.of(context).textTheme.subhead),
],
),
),
// max datetime hint
Padding(
padding: EdgeInsets.only(bottom: 8.0),
child: Row(
children: <Widget>[
Container(
width: 115.0,
child: Text('max DateTime:', style: hintTextStyle),
),
Text(MAX_DATETIME,
style: Theme.of(context).textTheme.subhead),
],
),
),
// init datetime hint
Padding(
padding: EdgeInsets.only(bottom: 8.0),
child: Row(
children: <Widget>[
Container(
width: 115.0,
child: Text('init DateTime:', style: hintTextStyle),
),
Text(INIT_DATETIME,
style: Theme.of(context).textTheme.subhead),
],
),
),
// date format
Padding(
padding: EdgeInsets.only(bottom: 8.0),
child: Row(
children: <Widget>[
Container(
width: 115.0,
child: Text('Date Format:', style: hintTextStyle),
),
Text(DATE_FORMAT, style: Theme.of(context).textTheme.subhead),
],
),
),
// show custom title widget
Row(
children: <Widget>[
Text('show custom title', style: hintTextStyle),
Checkbox(value: true, onChanged: (value) {}),
],
),
// custom title height
Padding(
padding: EdgeInsets.only(bottom: 8.0),
child: Row(
children: <Widget>[
Container(
margin: EdgeInsets.only(right: 8.0),
child: Text('custom title height:', style: hintTextStyle),
),
Text('40.0', style: Theme.of(context).textTheme.subhead),
],
),
),
// date time picker widget
Container(
margin: EdgeInsets.only(top: 8.0, bottom: 40.0),
child: DateTimePickerWidget(
minDateTime: DateTime.parse(MIN_DATETIME),
maxDateTime: DateTime.parse(MAX_DATETIME),
initDateTime: DateTime.parse(INIT_DATETIME),
dateFormat: DATE_FORMAT,
pickerTheme: DateTimePickerTheme(
showTitle: false,
title: Container(
width: double.infinity,
height: 40.0,
alignment: Alignment.center,
child: Text('Date Time Picker Title'),
decoration: BoxDecoration(color: Color(0xFFc0ca33)),
),
backgroundColor: Color(0xFFf0f4c3),
),
onChange: (dateTime, selectedIndex) {
setState(() {
_dateTime = dateTime;
});
},
),
),
// selected date time
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Selected DateTime:',
style: Theme.of(context).textTheme.subhead),
Container(
width: double.infinity,
padding: EdgeInsets.only(top: 4.0),
child: Text(
_dateTime != null
? '${_dateTime.year}-${_dateTime.month.toString().padLeft(2, '0')}-${_dateTime.day.toString().padLeft(2, '0')} ${_dateTime.hour.toString().padLeft(2, '0')}:${_dateTime.minute.toString().padLeft(2, '0')}:${_dateTime.second.toString().padLeft(2, '0')}'
: '',
style: Theme.of(context).textTheme.title,
),
),
],
),
],
),
),
);
}
}
import 'package:flutter/material.dart';
import './date_picker_bottom_sheet.dart';
import './date_picker_in_page.dart';
import './datetime_picker_bottom_sheet.dart';
import './datetime_picker_in_page.dart';
import './time_picker_bottom_sheet.dart';
import './time_picker_in_page.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Date Picker Demo',
theme: ThemeData(primarySwatch: Colors.blue),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
MyHomePage({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
TextStyle textStyle = TextStyle(color: Colors.white, fontSize: 16.0);
return Scaffold(
appBar: AppBar(title: Text('Date Picker Demo')),
body: Container(
width: double.infinity,
padding: EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
RaisedButton(
color: Colors.blue,
child: Text("DatePicker Bottom Sheet", style: textStyle),
onPressed: () {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) {
return DatePickerBottomSheet();
}));
},
),
RaisedButton(
color: Colors.blue,
child: Text("DatePicker In Page", style: textStyle),
onPressed: () {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) {
return DatePickerInPage();
}));
},
),
RaisedButton(
color: Colors.blue,
child: Text("TimePicker Bottom Sheet", style: textStyle),
onPressed: () {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) {
return TimePickerBottomSheet();
}));
},
),
RaisedButton(
color: Colors.blue,
child: Text("TimePicker In Page", style: textStyle),
onPressed: () {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) {
return TimePickerInPage();
}));
},
),
RaisedButton(
color: Colors.blue,
child: Text("DateTimePicker Bottom Sheet", style: textStyle),
onPressed: () {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) {
return DateTimePickerBottomSheet();
}));
},
),
RaisedButton(
color: Colors.blue,
child: Text("DateTimePicker In Page", style: textStyle),
onPressed: () {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) {
return DateTimePickerInPage();
}));
},
),
],
),
),
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter_cupertino_date_picker/flutter_cupertino_date_picker.dart';
class TimePickerBottomSheet extends StatefulWidget {
TimePickerBottomSheet({Key key}) : super(key: key);
@override
State<StatefulWidget> createState() => _TimePickerBottomSheetState();
}
const String MIN_DATETIME = '2010-05-12 10:47:00';
const String MAX_DATETIME = '2021-11-25 22:45:10';
const String INIT_DATETIME = '2019-05-17 18:13:15';
class _TimePickerBottomSheetState extends State<TimePickerBottomSheet> {
String _format = 'HH:mm';
TextEditingController _formatCtrl = TextEditingController();
DateTime _dateTime;
@override
void initState() {
super.initState();
_formatCtrl.text = _format;
_dateTime = DateTime.parse(INIT_DATETIME);
}
@override
Widget build(BuildContext context) {
TextStyle hintTextStyle =
Theme.of(context).textTheme.subhead.apply(color: Color(0xFF999999));
return Scaffold(
appBar: AppBar(title: Text('TimePicker Bottom Sheet')),
body: Container(
padding: EdgeInsets.all(16.0),
child: Column(
children: <Widget>[
// min datetime hint
Padding(
padding: EdgeInsets.only(bottom: 8.0),
child: Row(
children: <Widget>[
Container(
width: 115.0,
child: Text('min DateTime:', style: hintTextStyle),
),
Text(MIN_DATETIME.substring(11),
style: Theme.of(context).textTheme.subhead),
],
),
),
// max datetime hint
Padding(
padding: EdgeInsets.only(bottom: 8.0),
child: Row(
children: <Widget>[
Container(
width: 115.0,
child: Text('max DateTime:', style: hintTextStyle),
),
Text(MAX_DATETIME.substring(11),
style: Theme.of(context).textTheme.subhead),
],
),
),
// init datetime hint
Padding(
padding: EdgeInsets.only(bottom: 8.0),
child: Row(
children: <Widget>[
Container(
width: 115.0,
child: Text('init DateTime:', style: hintTextStyle),
),
Text(INIT_DATETIME.substring(11),
style: Theme.of(context).textTheme.subhead),
],
),
),
// show custom title widget
Row(
children: <Widget>[
Text('show custom title', style: hintTextStyle),
Checkbox(value: true, onChanged: (value) {}),
],
),
// custom title height
Padding(
padding: EdgeInsets.only(bottom: 8.0),
child: Row(
children: <Widget>[
Container(
margin: EdgeInsets.only(right: 8.0),
child: Text('custom title height:', style: hintTextStyle),
),
Text('56.0', style: Theme.of(context).textTheme.subhead),
],
),
),
// date format input field
TextField(
controller: _formatCtrl,
keyboardType: TextInputType.url,
decoration: InputDecoration(
labelText: 'Formatter',
hintText: 'HH:mm:ss / H-m / H时.m分',
hintStyle: TextStyle(color: Colors.black26),
),
onChanged: (value) => _format = value,
),
// selected time
Container(
margin: EdgeInsets.only(top: 40.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text('Selected Time:',
style: Theme.of(context).textTheme.subhead),
Container(
padding: EdgeInsets.only(left: 12.0),
child: Text(
'${_dateTime.hour.toString().padLeft(2, '0')}:${_dateTime.minute.toString().padLeft(2, '0')}:${_dateTime.second.toString().padLeft(2, '0')}',
style: Theme.of(context).textTheme.title),
),
],
),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _showTimePicker,
tooltip: 'Show TimePicker',
child: Icon(Icons.access_time),
),
);
}
/// Display time picker.
void _showTimePicker() {
DatePicker.showDatePicker(
context,
minDateTime: DateTime.parse(MIN_DATETIME),
maxDateTime: DateTime.parse(MAX_DATETIME),
initialDateTime: DateTime.parse(INIT_DATETIME),
dateFormat: _format,
pickerMode: DateTimePickerMode.time, // show TimePicker
pickerTheme: DateTimePickerTheme(
title: Container(
decoration: BoxDecoration(color: Color(0xFFEFEFEF)),
width: double.infinity,
height: 56.0,
alignment: Alignment.center,
child: Text(
'custom Title',
style: TextStyle(color: Colors.green, fontSize: 24.0),
),
),
titleHeight: 56.0,
),
onCancel: () {
debugPrint('onCancel');
},
onChange: (dateTime, List<int> index) {
setState(() {
_dateTime = dateTime;
});
},
onConfirm: (dateTime, List<int> index) {
setState(() {
_dateTime = dateTime;
});
},
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter_cupertino_date_picker/flutter_cupertino_date_picker.dart';
///
/// @author dylan wu
/// @since 2019-05-10
class TimePickerInPage extends StatefulWidget {
TimePickerInPage({Key key}) : super(key: key);
@override
State<StatefulWidget> createState() => _TimePickerInPageState();
}
const String MIN_DATETIME = '2010-05-12 05:15:20';
const String MAX_DATETIME = '2021-11-25 22:45:10';
const String INIT_DATETIME = '2019-05-17 18:13:15';
const String DATE_FORMAT = 'HH时:mm分:s';
class _TimePickerInPageState extends State<TimePickerInPage> {
DateTime _dateTime;
@override
void initState() {
super.initState();
_dateTime = DateTime.parse(INIT_DATETIME);
}
@override
Widget build(BuildContext context) {
TextStyle hintTextStyle =
Theme.of(context).textTheme.subhead.apply(color: Color(0xFF999999));
return Scaffold(
appBar: AppBar(title: Text("TimePicker In Page")),
body: Container(
decoration: BoxDecoration(color: Colors.white),
padding: EdgeInsets.all(16.0),
child: Column(
children: <Widget>[
// min datetime hint
Padding(
padding: EdgeInsets.only(bottom: 8.0),
child: Row(
children: <Widget>[
Container(
width: 115.0,
child: Text('min DateTime:', style: hintTextStyle),
),
Text(MIN_DATETIME.substring(11),
style: Theme.of(context).textTheme.subhead),
],
),
),
// max datetime hint
Padding(
padding: EdgeInsets.only(bottom: 8.0),
child: Row(
children: <Widget>[
Container(
width: 115.0,
child: Text('max DateTime:', style: hintTextStyle),
),
Text(MAX_DATETIME.substring(11),
style: Theme.of(context).textTheme.subhead),
],
),
),
// init datetime hint
Padding(
padding: EdgeInsets.only(bottom: 8.0),
child: Row(
children: <Widget>[
Container(
width: 115.0,
child: Text('init DateTime:', style: hintTextStyle),
),
Text(INIT_DATETIME.substring(11),
style: Theme.of(context).textTheme.subhead),
],
),
),
// date format
Padding(
padding: EdgeInsets.only(bottom: 8.0),
child: Row(
children: <Widget>[
Container(
width: 115.0,
child: Text('Date Format:', style: hintTextStyle),
),
Text(DATE_FORMAT, style: Theme.of(context).textTheme.subhead),
],
),
),
// date format input field
Container(
margin: EdgeInsets.only(top: 8.0, bottom: 40.0),
child: TimePickerWidget(
minDateTime: DateTime.parse(MIN_DATETIME),
maxDateTime: DateTime.parse(MAX_DATETIME),
initDateTime: DateTime.parse(INIT_DATETIME),
dateFormat: DATE_FORMAT,
minuteDivider: 15,
pickerTheme: DateTimePickerTheme(
showTitle: false, backgroundColor: Color(0xFFe1bee7)),
onChange: (dateTime, selectedIndex) {
setState(() {
_dateTime = dateTime;
});
},
),
),
// selected time
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text('Selected Time:',
style: Theme.of(context).textTheme.subhead),
Container(
padding: EdgeInsets.only(left: 12.0),
child: Text(
_dateTime != null
? '${_dateTime.hour.toString().padLeft(2, '0')}:${_dateTime.minute.toString().padLeft(2, '0')}:${_dateTime.second.toString().padLeft(2, '0')}'
: '',
style: Theme.of(context).textTheme.title,
),
),
],
),
],
),
),
);
}
}
name: example
description: A new Flutter application.
dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.2
flutter_cupertino_date_picker:
path: ../
dev_dependencies:
flutter_test:
sdk: flutter
# For information on the generic Dart part of this file, see the
# following page: https://www.dartlang.org/tools/pub/pubspec
# The following section is specific to Flutter.
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
# To add assets to your application, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.io/assets-and-images/#resolution-aware.
# For details regarding adding assets from package dependencies, see
# https://flutter.io/assets-and-images/#from-packages
# To add custom fonts to your application, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
# "family" key with the font family name, and a "fonts" key with a
# list giving the asset and other descriptors for the font. For
# example:
# fonts:
# - family: Schyler
# fonts:
# - asset: fonts/Schyler-Regular.ttf
# - asset: fonts/Schyler-Italic.ttf
# style: italic
# - family: Trajan Pro
# fonts:
# - asset: fonts/TrajanPro.ttf
# - asset: fonts/TrajanPro_Bold.ttf
# weight: 700
#
# For details regarding fonts from package dependencies,
# see https://flutter.io/custom-fonts/#from-packages
.idea/
.vagrant/
.sconsign.dblite
.svn/
.DS_Store
*.swp
profile
DerivedData/
build/
GeneratedPluginRegistrant.h
GeneratedPluginRegistrant.m
.generated/
*.pbxuser
*.mode1v3
*.mode2v3
*.perspectivev3
!default.pbxuser
!default.mode1v3
!default.mode2v3
!default.perspectivev3
xcuserdata
*.moved-aside
*.pyc
*sync/
Icon?
.tags*
/Flutter/app.flx
/Flutter/app.zip
/Flutter/flutter_assets/
/Flutter/App.framework
/Flutter/Flutter.framework
/Flutter/Generated.xcconfig
/ServiceDefinitions.json
Pods/
.symlinks/
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>App</string>
<key>CFBundleIdentifier</key>
<string>io.flutter.flutter.app</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>App</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>8.0</string>
</dict>
</plist>
#include "Generated.xcconfig"
#include "Generated.xcconfig"
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */ = {isa = PBXBuildFile; fileRef = 2D5378251FAA1A9400D5DBA9 /* flutter_assets */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };
3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; };
9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; };
9740EEB51CF90195004384FC /* Generated.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB31CF90195004384FC /* Generated.xcconfig */; };
978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; };
97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */,
9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
2D5378251FAA1A9400D5DBA9 /* flutter_assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = flutter_assets; path = Flutter/flutter_assets; sourceTree = SOURCE_ROOT; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
97C146EB1CF9000F007C117D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */,
3B80C3941E831B6300D905FE /* App.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
2D5378251FAA1A9400D5DBA9 /* flutter_assets */,
3B80C3931E831B6300D905FE /* App.framework */,
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEBA1CF902C7004384FC /* Flutter.framework */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
9740EEB31CF90195004384FC /* Generated.xcconfig */,
);
name = Flutter;
sourceTree = "<group>";
};
97C146E51CF9000F007C117D = {
isa = PBXGroup;
children = (
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
);
sourceTree = "<group>";
};
97C146EF1CF9000F007C117D /* Products */ = {
isa = PBXGroup;
children = (
97C146EE1CF9000F007C117D /* Runner.app */,
);
name = Products;
sourceTree = "<group>";
};
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */,
7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */,
97C146FA1CF9000F007C117D /* Main.storyboard */,
97C146FD1CF9000F007C117D /* Assets.xcassets */,
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
97C147021CF9000F007C117D /* Info.plist */,
97C146F11CF9000F007C117D /* Supporting Files */,
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
);
path = Runner;
sourceTree = "<group>";
};
97C146F11CF9000F007C117D /* Supporting Files */ = {
isa = PBXGroup;
children = (
97C146F21CF9000F007C117D /* main.m */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
97C146ED1CF9000F007C117D /* Runner */ = {
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
);
buildRules = (
);
dependencies = (
);
name = Runner;
productName = Runner;
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0910;
ORGANIZATIONNAME = "The Chromium Authors";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
CreatedOnToolsVersion = 7.3.1;
DevelopmentTeam = PWRV2ZB7PD;
};
};
};
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 97C146E51CF9000F007C117D;
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
97C146ED1CF9000F007C117D /* Runner */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
97C146EC1CF9000F007C117D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
9740EEB51CF90195004384FC /* Generated.xcconfig in Resources */,
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Thin Binary";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin";
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Run Script";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
97C146EA1CF9000F007C117D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */,
97C146F31CF9000F007C117D /* main.m in Sources */,
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C146FB1CF9000F007C117D /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C147001CF9000F007C117D /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
97C147031CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
97C147041CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
97C147061CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = PWRV2ZB7PD;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = com.flutter.flutterDatePicker;
PRODUCT_NAME = "$(TARGET_NAME)";
VERSIONING_SYSTEM = "apple-generic";
};
name = Debug;
};
97C147071CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = PWRV2ZB7PD;
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = com.flutter.flutterDatePicker;
PRODUCT_NAME = "$(TARGET_NAME)";
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147031CF9000F007C117D /* Debug */,
97C147041CF9000F007C117D /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147061CF9000F007C117D /* Debug */,
97C147071CF9000F007C117D /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 97C146E61CF9000F007C117D /* Project object */;
}
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
</Workspace>
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0910"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
</Workspace>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>
@interface AppDelegate : FlutterAppDelegate
@end
#include "AppDelegate.h"
#include "GeneratedPluginRegistrant.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[GeneratedPluginRegistrant registerWithRegistry:self];
// Override point for customization after application launch.
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
@end
{
"images" : [
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@3x.png",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@3x.png",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@3x.png",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@2x.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@3x.png",
"scale" : "3x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@1x.png",
"scale" : "1x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@1x.png",
"scale" : "1x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@1x.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@2x.png",
"scale" : "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "Icon-App-83.5x83.5@2x.png",
"scale" : "2x"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "Icon-App-1024x1024@1x.png",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
{
"images" : [
{
"idiom" : "universal",
"filename" : "LaunchImage.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
# Launch Screen Assets
You can customize the launch screen with your own desired assets by replacing the image files in this directory.
You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
</imageView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
<resources>
<image name="LaunchImage" width="168" height="185"/>
</resources>
</document>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<scenes>
<!--Flutter View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>flutter_date_picker</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
</dict>
</plist>
#import <Flutter/Flutter.h>
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char* argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
library flutter_cupertino_date_picker;
export 'src/date_picker.dart';
export 'src/i18n/date_picker_i18n.dart';
export 'src/date_picker_theme.dart' show DateTimePickerTheme;
export 'src/widget/date_picker_widget.dart';
export 'src/widget/time_picker_widget.dart';
export 'src/widget/datetime_picker_widget.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'date_picker_theme.dart';
import 'date_picker_constants.dart';
import 'date_time_formatter.dart';
import 'i18n/date_picker_i18n.dart';
import 'widget/date_picker_widget.dart';
import 'widget/datetime_picker_widget.dart';
import 'widget/time_picker_widget.dart';
enum DateTimePickerMode {
/// Display DatePicker
date,
/// Display TimePicker
time,
/// Display DateTimePicker
datetime,
}
///
/// author: Dylan Wu
/// since: 2018/06/21
class DatePicker {
/// Display date picker in bottom sheet.
///
/// context: [BuildContext]
/// minDateTime: [DateTime] minimum date time
/// maxDateTime: [DateTime] maximum date time
/// initialDateTime: [DateTime] initial date time for selected
/// dateFormat: [String] date format pattern
/// locale: [DateTimePickerLocale] internationalization
/// pickerMode: [DateTimePickerMode] display mode: date(DatePicker)、time(TimePicker)、datetime(DateTimePicker)
/// pickerTheme: [DateTimePickerTheme] the theme of date time picker
/// onCancel: [DateVoidCallback] pressed title cancel widget event
/// onClose: [DateVoidCallback] date picker closed event
/// onChange: [DateValueCallback] selected date time changed event
/// onConfirm: [DateValueCallback] pressed title confirm widget event
static void showDatePicker(
BuildContext context, {
DateTime minDateTime,
DateTime maxDateTime,
DateTime initialDateTime,
String dateFormat,
DateTimePickerLocale locale: DATETIME_PICKER_LOCALE_DEFAULT,
DateTimePickerMode pickerMode: DateTimePickerMode.date,
DateTimePickerTheme pickerTheme: DateTimePickerTheme.Default,
DateVoidCallback onCancel,
DateVoidCallback onClose,
DateValueCallback onChange,
DateValueCallback onConfirm,
int minuteDivider = 1,
bool onMonthChangeStartWithFirstDate = false,
}) {
// handle the range of datetime
if (minDateTime == null) {
minDateTime = DateTime.parse(DATE_PICKER_MIN_DATETIME);
}
if (maxDateTime == null) {
maxDateTime = DateTime.parse(DATE_PICKER_MAX_DATETIME);
}
// handle initial DateTime
if (initialDateTime == null) {
initialDateTime = DateTime.now();
}
// Set value of date format
if (dateFormat != null && dateFormat.length > 0) {
// Check whether date format is legal or not
if (DateTimeFormatter.isDayFormat(dateFormat)) {
if (pickerMode == DateTimePickerMode.time) {
pickerMode = DateTimeFormatter.isTimeFormat(dateFormat)
? DateTimePickerMode.datetime
: DateTimePickerMode.date;
}
} else {
if (pickerMode == DateTimePickerMode.date ||
pickerMode == DateTimePickerMode.datetime) {
pickerMode = DateTimePickerMode.time;
}
}
} else {
dateFormat = DateTimeFormatter.generateDateFormat(pickerMode);
}
Navigator.push(
context,
new _DatePickerRoute(
onMonthChangeStartWithFirstDate: onMonthChangeStartWithFirstDate,
minDateTime: minDateTime,
maxDateTime: maxDateTime,
initialDateTime: initialDateTime,
dateFormat: dateFormat,
locale: locale,
pickerMode: pickerMode,
pickerTheme: pickerTheme,
onCancel: onCancel,
onChange: onChange,
onConfirm: onConfirm,
theme: Theme.of(context, shadowThemeOnly: true),
barrierLabel:
MaterialLocalizations.of(context).modalBarrierDismissLabel,
minuteDivider: minuteDivider,
),
).whenComplete(onClose ?? () => {});
}
}
class _DatePickerRoute<T> extends PopupRoute<T> {
_DatePickerRoute({
this.onMonthChangeStartWithFirstDate,
this.minDateTime,
this.maxDateTime,
this.initialDateTime,
this.dateFormat,
this.locale,
this.pickerMode,
this.pickerTheme,
this.onCancel,
this.onChange,
this.onConfirm,
this.theme,
this.barrierLabel,
this.minuteDivider,
RouteSettings settings,
}) : super(settings: settings);
final DateTime minDateTime, maxDateTime, initialDateTime;
final String dateFormat;
final DateTimePickerLocale locale;
final DateTimePickerMode pickerMode;
final DateTimePickerTheme pickerTheme;
final VoidCallback onCancel;
final DateValueCallback onChange;
final DateValueCallback onConfirm;
final int minuteDivider;
final bool onMonthChangeStartWithFirstDate;
final ThemeData theme;
@override
Duration get transitionDuration => const Duration(milliseconds: 200);
@override
bool get barrierDismissible => true;
@override
final String barrierLabel;
@override
Color get barrierColor => Colors.black54;
AnimationController _animationController;
@override
AnimationController createAnimationController() {
assert(_animationController == null);
_animationController =
BottomSheet.createAnimationController(navigator.overlay);
return _animationController;
}
@override
Widget buildPage(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) {
double height = pickerTheme.pickerHeight;
if (pickerTheme.title != null || pickerTheme.showTitle) {
height += pickerTheme.titleHeight;
}
Widget bottomSheet = new MediaQuery.removePadding(
context: context,
removeTop: true,
child: _DatePickerComponent(route: this, pickerHeight: height),
);
if (theme != null) {
bottomSheet = new Theme(data: theme, child: bottomSheet);
}
return bottomSheet;
}
}
class _DatePickerComponent extends StatelessWidget {
final _DatePickerRoute route;
final double _pickerHeight;
_DatePickerComponent({Key key, @required this.route, @required pickerHeight})
: this._pickerHeight = pickerHeight;
@override
Widget build(BuildContext context) {
Widget pickerWidget;
switch (route.pickerMode) {
case DateTimePickerMode.date:
pickerWidget = DatePickerWidget(
onMonthChangeStartWithFirstDate:
route.onMonthChangeStartWithFirstDate,
minDateTime: route.minDateTime,
maxDateTime: route.maxDateTime,
initialDateTime: route.initialDateTime,
dateFormat: route.dateFormat,
locale: route.locale,
pickerTheme: route.pickerTheme,
onCancel: route.onCancel,
onChange: route.onChange,
onConfirm: route.onConfirm,
);
break;
case DateTimePickerMode.time:
pickerWidget = TimePickerWidget(
minDateTime: route.minDateTime,
maxDateTime: route.maxDateTime,
initDateTime: route.initialDateTime,
dateFormat: route.dateFormat,
locale: route.locale,
pickerTheme: route.pickerTheme,
onCancel: route.onCancel,
onChange: route.onChange,
onConfirm: route.onConfirm,
minuteDivider: route.minuteDivider,
);
break;
case DateTimePickerMode.datetime:
pickerWidget = DateTimePickerWidget(
minDateTime: route.minDateTime,
maxDateTime: route.maxDateTime,
initDateTime: route.initialDateTime,
dateFormat: route.dateFormat,
locale: route.locale,
pickerTheme: route.pickerTheme,
onCancel: route.onCancel,
onChange: route.onChange,
onConfirm: route.onConfirm,
minuteDivider: route.minuteDivider,
);
break;
}
return new GestureDetector(
child: new AnimatedBuilder(
animation: route.animation,
builder: (BuildContext context, Widget child) {
return new ClipRect(
child: new CustomSingleChildLayout(
delegate: new _BottomPickerLayout(route.animation.value,
contentHeight: _pickerHeight),
child: pickerWidget,
),
);
},
),
);
}
}
class _BottomPickerLayout extends SingleChildLayoutDelegate {
_BottomPickerLayout(this.progress, {this.contentHeight});
final double progress;
final double contentHeight;
@override
BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
return new BoxConstraints(
minWidth: constraints.maxWidth,
maxWidth: constraints.maxWidth,
minHeight: 0.0,
maxHeight: contentHeight,
);
}
@override
Offset getPositionForChild(Size size, Size childSize) {
double height = size.height - childSize.height * progress;
return new Offset(0.0, height);
}
@override
bool shouldRelayout(_BottomPickerLayout oldDelegate) {
return progress != oldDelegate.progress;
}
}
/// Selected value of DatePicker.
typedef DateValueCallback(DateTime dateTime, List<int> selectedIndex);
/// Pressed cancel callback.
typedef DateVoidCallback();
/// Default value of minimum datetime.
const String DATE_PICKER_MIN_DATETIME = "1900-01-01 00:00:00";
/// Default value of maximum datetime.
const String DATE_PICKER_MAX_DATETIME = "2100-12-31 23:59:59";
/// Default value of date format
const String DATETIME_PICKER_DATE_FORMAT = 'yyyy-MM-dd';
/// Default value of time format
const String DATETIME_PICKER_TIME_FORMAT = 'HH:mm:ss';
/// Default value of datetime format
const String DATETIME_PICKER_DATETIME_FORMAT = 'yyyyMMdd HH:mm:ss';
import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
/// Default value of DatePicker's background color.
const DATETIME_PICKER_BACKGROUND_COLOR = Colors.white;
/// Default value of whether show title widget or not.
const DATETIME_PICKER_SHOW_TITLE_DEFAULT = true;
/// Default value of DatePicker's height.
const double DATETIME_PICKER_HEIGHT = 210.0;
/// Default value of DatePicker's title height.
const double DATETIME_PICKER_TITLE_HEIGHT = 44.0;
/// Default value of DatePicker's column height.
const double DATETIME_PICKER_ITEM_HEIGHT = 36.0;
/// Default value of DatePicker's item [TextStyle].
const TextStyle DATETIME_PICKER_ITEM_TEXT_STYLE =
const TextStyle(color: Color(0xFF000046), fontSize: 16.0);
class DateTimePickerTheme with DiagnosticableMixin {
final cancelDefault = const Text('OK');
/// DateTimePicker theme.
///
/// [backgroundColor] DatePicker's background color.
/// [cancelTextStyle] Default cancel widget's [TextStyle].
/// [confirmTextStyle] Default confirm widget's [TextStyle].
/// [cancel] Custom cancel widget.
/// [confirm] Custom confirm widget.
/// [title] Custom title widget. If specify a title widget, the cancel and confirm widgets will not display. Must set [titleHeight] value for custom title widget.
/// [showTitle] Whether display title widget or not. If set false, the default cancel and confirm widgets will not display, but the custom title widget will display if had specified one custom title widget.
/// [pickerHeight] The value of DatePicker's height.
/// [titleHeight] The value of DatePicker's title height.
/// [itemHeight] The value of DatePicker's column height.
/// [itemTextStyle] The value of DatePicker's column [TextStyle].
const DateTimePickerTheme({
this.backgroundColor: DATETIME_PICKER_BACKGROUND_COLOR,
this.cancelTextStyle,
this.confirmTextStyle,
this.cancel,
this.confirm,
this.title,
this.showTitle: DATETIME_PICKER_SHOW_TITLE_DEFAULT,
this.pickerHeight: DATETIME_PICKER_HEIGHT,
this.titleHeight: DATETIME_PICKER_TITLE_HEIGHT,
this.itemHeight: DATETIME_PICKER_ITEM_HEIGHT,
this.itemTextStyle: DATETIME_PICKER_ITEM_TEXT_STYLE,
});
static const DateTimePickerTheme Default = const DateTimePickerTheme();
/// DatePicker's background color.
final Color backgroundColor;
/// Default cancel widget's [TextStyle].
final TextStyle cancelTextStyle;
/// Default confirm widget's [TextStyle].
final TextStyle confirmTextStyle;
/// Custom cancel [Widget].
final Widget cancel;
/// Custom confirm [Widget].
final Widget confirm;
/// Custom title [Widget]. If specify a title widget, the cancel and confirm widgets will not display.
final Widget title;
/// Whether display title widget or not. If set false, the default cancel and confirm widgets will not display, but the custom title widget will display if had specified one custom title widget.
final bool showTitle;
/// The value of DatePicker's height.
final double pickerHeight;
/// The value of DatePicker's title height.
final double titleHeight;
/// The value of DatePicker's column height.
final double itemHeight;
/// The value of DatePicker's column [TextStyle].
final TextStyle itemTextStyle;
}
import 'dart:math';
import 'date_picker.dart';
import 'date_picker_constants.dart';
import 'i18n/date_picker_i18n.dart';
const String DATE_FORMAT_SEPARATOR = r'[|,-/\._: ]+';
class DateTimeFormatter {
/// Get default value of date format.
static String generateDateFormat(DateTimePickerMode pickerMode) {
switch (pickerMode) {
case DateTimePickerMode.date:
return DATETIME_PICKER_DATE_FORMAT;
case DateTimePickerMode.time:
return DATETIME_PICKER_TIME_FORMAT;
case DateTimePickerMode.datetime:
return DATETIME_PICKER_DATETIME_FORMAT;
}
return '';
}
/// Check if the date format is for day(contain y、M、d、E) or not.
static bool isDayFormat(String format) {
return format.contains(RegExp(r'[yMdE]'));
}
/// Check if the date format is for time(contain H、m、s) or not.
static bool isTimeFormat(String format) {
return format.contains(RegExp(r'[Hms]'));
}
/// Split date format to array.
static List<String> splitDateFormat(String dateFormat,
{DateTimePickerMode mode}) {
if (dateFormat == null || dateFormat.length == 0) {
return [];
}
List<String> result = dateFormat.split(RegExp(DATE_FORMAT_SEPARATOR));
if (mode == DateTimePickerMode.datetime) {
// datetime mode need join day format
List<String> temp = List<String>();
StringBuffer dayFormat = StringBuffer();
for (int i = 0; i < result.length; i++) {
String format = result[i];
if (isDayFormat(format)) {
// find format pre-separator
int end = dateFormat.indexOf(format);
if (end > 0) {
int start = 0;
if (i > 0) {
start = dateFormat.indexOf(result[i - 1]) + result[i - 1].length;
}
dayFormat.write(dateFormat.substring(start, end));
}
dayFormat.write(format);
} else if (isTimeFormat(format)) {
temp.add(format);
}
}
if (dayFormat.length > 0) {
temp.insert(0, dayFormat.toString());
} else {
// add default date format
temp.insert(0, DATETIME_PICKER_DATE_FORMAT);
}
result = temp;
}
return result;
}
/// Format datetime string
static String formatDateTime(
int value, String format, DateTimePickerLocale locale) {
if (format == null || format.length == 0) {
return value.toString();
}
String result = format;
// format year text
if (format.contains('y')) {
result = _formatYear(value, result, locale);
}
// format month text
if (format.contains('M')) {
result = _formatMonth(value, result, locale);
}
// format day text
if (format.contains('d')) {
result = _formatDay(value, result, locale);
}
if (format.contains('E')) {
result = _formatWeek(value, result, locale);
}
// format hour text
if (format.contains('H')) {
result = _formatHour(value, result, locale);
}
// format minute text
if (format.contains('m')) {
result = _formatMinute(value, result, locale);
}
// format second text
if (format.contains('s')) {
result = _formatSecond(value, result, locale);
}
if (result == format) {
return value.toString();
}
return result;
}
/// Format day display
static String formatDate(
DateTime dateTime, String format, DateTimePickerLocale locale) {
if (format == null || format.length == 0) {
return dateTime.toString();
}
String result = format;
// format year text
if (format.contains('y')) {
result = _formatYear(dateTime.year, result, locale);
}
// format month text
if (format.contains('M')) {
result = _formatMonth(dateTime.month, result, locale);
}
// format day text
if (format.contains('d')) {
result = _formatDay(dateTime.day, result, locale);
}
if (format.contains('E')) {
result = _formatWeek(dateTime.weekday, result, locale);
}
if (result == format) {
return dateTime.toString();
}
return result;
}
/// format year text
static String _formatYear(
int value, String format, DateTimePickerLocale locale) {
if (format.contains('yyyy')) {
// yyyy: the digit count of year is 4, e.g. 2019
return format.replaceAll('yyyy', value.toString());
} else if (format.contains('yy')) {
// yy: the digit count of year is 2, e.g. 19
return format.replaceAll('yy',
value.toString().substring(max(0, value.toString().length - 2)));
}
return value.toString();
}
/// format month text
static String _formatMonth(
int value, String format, DateTimePickerLocale locale) {
List<String> months = DatePickerI18n.getLocaleMonths(locale);
if (format.contains('MMMM')) {
// MMMM: the full name of month, e.g. January
return format.replaceAll('MMMM', months[value - 1]);
} else if (format.contains('MMM')) {
// MMM: the short name of month, e.g. Jan
months = DatePickerI18n.getLocaleMonths(locale, false);
String month = months[value - 1];
return format.replaceAll('MMM', month);
}
return _formatNumber(value, format, 'M');
}
/// format day text
static String _formatDay(
int value, String format, DateTimePickerLocale locale) {
return _formatNumber(value, format, 'd');
}
/// format week text
static String _formatWeek(
int value, String format, DateTimePickerLocale locale) {
if (format.contains('EEEE')) {
// EEEE: the full name of week, e.g. Monday
List<String> weeks = DatePickerI18n.getLocaleWeeks(locale);
return format.replaceAll('EEEE', weeks[value - 1]);
}
// EEE: the short name of week, e.g. Mon
List<String> weeks = DatePickerI18n.getLocaleWeeks(locale, false);
return format.replaceAll(RegExp(r'E+'), weeks[value - 1]);
}
/// format hour text
static String _formatHour(
int value, String format, DateTimePickerLocale locale) {
return _formatNumber(value, format, 'H');
}
/// format minute text
static String _formatMinute(
int value, String format, DateTimePickerLocale locale) {
return _formatNumber(value, format, 'm');
}
/// format second text
static String _formatSecond(
int value, String format, DateTimePickerLocale locale) {
return _formatNumber(value, format, 's');
}
/// format number, if the digit count is 2, will pad zero on the left
static String _formatNumber(int value, String format, String unit) {
if (format.contains('$unit$unit')) {
return format.replaceAll('$unit$unit', value.toString().padLeft(2, '0'));
} else if (format.contains('$unit')) {
return format.replaceAll('$unit', value.toString());
}
return value.toString();
}
}
import 'dart:math';
part 'strings_en_us.dart';
part 'strings_zh_cn.dart';
part 'strings_pt_br.dart';
part 'strings_id.dart';
part 'strings_ar_eg.dart';
part 'strings_es.dart';
part 'strings_ro.dart';
part 'strings_bn.dart';
part 'strings_bs.dart';
part 'strings_ar.dart';
part 'strings_jp.dart';
part 'strings_ru.dart';
part 'strings_de.dart';
part 'strings_ko.dart';
part 'strings_it.dart';
part 'strings_hu.dart';
part 'strings_hr.dart';
part 'strings_uk.dart';
part 'strings_tr.dart';
part 'strings_vi.dart';
part 'strings_fr.dart';
part 'strings_sr_cyr.dart';
part 'strings_sr_lat.dart';
part 'strings_nl.dart';
abstract class _StringsI18n {
const _StringsI18n();
/// Get the done widget text
String getDoneText();
/// Get the cancel widget text
String getCancelText();
/// Get the name of month
List<String> getMonths();
/// Get the short name of month
List<String> getMonthsShort();
/// Get the full name of week
List<String> getWeeksFull();
/// Get the short name of week
List<String> getWeeksShort();
}
enum DateTimePickerLocale {
/// English (EN) United States
en_us,
/// Chinese (ZH) Simplified
zh_cn,
/// Portuguese (PT) Brazil
pt_br,
/// Indonesia (ID)
id,
/// Spanish (ES)
es,
/// Turkish (TR)
tr,
/// French (FR)
fr,
/// Romanian (RO)
ro,
/// Bengali (BN)
bn,
/// Bosnian (BS)
bs,
/// Arabic (ar)
ar,
/// Arabic (ar) Egypt
ar_eg,
/// Japanese (JP)
jp,
/// Russian (RU)
ru,
/// German (DE)
de,
/// Korea (KO)
ko,
/// Italian (IT)
it,
/// Hungarian (HU)
hu,
/// Croatian (HR)
hr,
/// Ukrainian (UK)
uk,
/// Vietnamese (VN)
vi,
/// Serbia (sr) Cyrillic
sr_cyrl,
/// Serbia (sr) Latin
sr_latn,
/// Dutch (NL)
nl,
}
/// Default value of date locale
const DateTimePickerLocale DATETIME_PICKER_LOCALE_DEFAULT =
DateTimePickerLocale.en_us;
const Map<DateTimePickerLocale, _StringsI18n> datePickerI18n = {
DateTimePickerLocale.en_us: const _StringsEnUs(),
DateTimePickerLocale.zh_cn: const _StringsZhCn(),
DateTimePickerLocale.pt_br: const _StringsPtBr(),
DateTimePickerLocale.id: const _StringsId(),
DateTimePickerLocale.ar_eg: const _StringsArEg(),
DateTimePickerLocale.es: const _StringsEs(),
DateTimePickerLocale.fr: const _StringsFr(),
DateTimePickerLocale.ro: const _StringsRo(),
DateTimePickerLocale.bn: const _StringsBn(),
DateTimePickerLocale.bs: const _StringsBs(),
DateTimePickerLocale.ar: const _StringsAr(),
DateTimePickerLocale.jp: const _StringsJp(),
DateTimePickerLocale.ru: const _StringsRu(),
DateTimePickerLocale.de: const _StringsDe(),
DateTimePickerLocale.ko: const _StringsKo(),
DateTimePickerLocale.it: const _StringsIt(),
DateTimePickerLocale.hu: const _StringsHu(),
DateTimePickerLocale.hr: const _StringsHr(),
DateTimePickerLocale.uk: const _StringsUk(),
DateTimePickerLocale.tr: const _StringsTr(),
DateTimePickerLocale.vi: const _StringsVn(),
DateTimePickerLocale.sr_cyrl: const _StringsSrCyrillic(),
DateTimePickerLocale.sr_latn: const _StringsSrLatin(),
DateTimePickerLocale.nl: const _StringsNl(),
};
class DatePickerI18n {
/// Get done button text
static String getLocaleDone(DateTimePickerLocale locale) {
_StringsI18n i18n = datePickerI18n[locale] ??
datePickerI18n[DATETIME_PICKER_LOCALE_DEFAULT];
return i18n.getDoneText() ??
datePickerI18n[DATETIME_PICKER_LOCALE_DEFAULT].getDoneText();
}
/// Get cancel button text
static String getLocaleCancel(DateTimePickerLocale locale) {
_StringsI18n i18n = datePickerI18n[locale] ??
datePickerI18n[DATETIME_PICKER_LOCALE_DEFAULT];
return i18n.getCancelText() ??
datePickerI18n[DATETIME_PICKER_LOCALE_DEFAULT].getCancelText();
}
/// Get locale month array
static List<String> getLocaleMonths(DateTimePickerLocale locale,
[bool isFull = true]) {
_StringsI18n i18n = datePickerI18n[locale] ??
datePickerI18n[DATETIME_PICKER_LOCALE_DEFAULT];
if (isFull) {
List<String> months = i18n.getMonths();
if (months != null && months.isNotEmpty) {
return months;
}
return datePickerI18n[DATETIME_PICKER_LOCALE_DEFAULT].getMonths();
}
List<String> months = i18n.getMonthsShort();
if (months != null && months.isNotEmpty && months.length == 12) {
return months;
}
return datePickerI18n[DATETIME_PICKER_LOCALE_DEFAULT].getMonthsShort();
}
/// Get locale week array
static List<String> getLocaleWeeks(DateTimePickerLocale locale,
[bool isFull = true]) {
_StringsI18n i18n = datePickerI18n[locale] ??
datePickerI18n[DATETIME_PICKER_LOCALE_DEFAULT];
if (isFull) {
List<String> weeks = i18n.getWeeksFull();
if (weeks != null && weeks.isNotEmpty) {
return weeks;
}
return datePickerI18n[DATETIME_PICKER_LOCALE_DEFAULT].getWeeksFull();
}
List<String> weeks = i18n.getWeeksShort();
if (weeks != null && weeks.isNotEmpty) {
return weeks;
}
List<String> fullWeeks = i18n.getWeeksFull();
if (fullWeeks != null && fullWeeks.isNotEmpty) {
return fullWeeks
.map((item) => item.substring(0, min(3, item.length)))
.toList();
}
return datePickerI18n[DATETIME_PICKER_LOCALE_DEFAULT].getWeeksShort();
}
}
part of 'date_picker_i18n.dart';
/// Arabic (ar)
class _StringsAr extends _StringsI18n {
const _StringsAr();
@override
String getCancelText() {
return 'ألغاء';
}
@override
String getDoneText() {
return 'تم';
}
@override
List<String> getMonths() {
return [
"كانون الثاني",
"شباط",
"آذار",
"نيسان",
"أيار",
"حزيران",
"تموز",
"آب",
"أيلول",
"تشرين الأول",
"تشرين الثاني",
"كانون الأول"
];
}
@override
List<String> getWeeksFull() {
return [
"الأثنين",
"الثلاثاء",
"الأربعاء",
"الخميس",
"الجمعه",
"السبت",
"الأحد",
];
}
@override
List<String> getWeeksShort() {
return null;
}
@override
List<String> getMonthsShort() {
// TODO: implement getMonthsShort
return null;
}
}
part of 'date_picker_i18n.dart';
/// Arabic (ar) Egypt
class _StringsArEg extends _StringsI18n {
const _StringsArEg();
@override
String getCancelText() {
return 'إلغاء';
}
@override
String getDoneText() {
return 'تم';
}
@override
List<String> getMonths() {
return [
"يناير",
"فبراير",
"مارس",
"أبريل",
"مايو",
"يونيو",
"يوليو",
"أغسطس",
"سبتمبر",
"أكتوبر",
"نوفمبر",
"ديسمبر"
];
}
@override
List<String> getMonthsShort() {
return null;
}
@override
List<String> getWeeksFull() {
return [
"الأثنين",
"الثلاثاء",
"الأربعاء",
"الخميس",
"الجمعه",
"السبت",
"الأحد",
];
}
@override
List<String> getWeeksShort() {
return [
"ن",
"ث",
"ر",
"خ",
"ج",
"س",
"ح",
];
}
}
part of 'date_picker_i18n.dart';
/// Bengali (BN)
class _StringsBn extends _StringsI18n {
const _StringsBn();
@override
String getCancelText() {
return 'বাতিল';
}
@override
String getDoneText() {
return 'সম্পন্ন';
}
@override
List<String> getMonths() {
return [
"জানুয়ারী",
"ফেব্রুয়ারি",
"মার্চ",
"এপ্রিল",
"মে",
"জুন",
"জুলাই",
"অগাস্ট",
"সেপ্টেম্বর",
"অক্টোবর",
"নভেম্বর",
"ডিসেম্বর"
];
}
@override
List<String> getWeeksFull() {
return [
"রবিবার",
"সোমবার",
"মঙ্গলবার",
"বুধবার",
"বৃহস্পতিবার",
"শুক্রবার",
"শনিবার",
];
}
@override
List<String> getWeeksShort() {
return [
"রবি",
"সোম",
"মঙ্গল",
"বুধ",
"বৃহস্পতি",
"শুক্র",
"শনি",
];
}
@override
List<String> getMonthsShort() {
// TODO: implement getMonthsShort
return null;
}
}
part of 'date_picker_i18n.dart';
/// Bosnian (BS)
class _StringsBs extends _StringsI18n {
const _StringsBs();
@override
String getCancelText() {
return 'Otkaži';
}
@override
String getDoneText() {
return 'Završi';
}
@override
List<String> getMonths() {
return [
"Januar",
"Februar",
"Mart",
"April",
"Maj",
"Juni",
"Juli",
"August",
"Septembar",
"Oktobar",
"Novembar",
"Decembar",
];
}
@override
List<String> getMonthsShort() {
return null;
}
@override
List<String> getWeeksFull() {
return [
"Ponedjeljak",
"Utorak",
"Srijeda",
"Četvrtak",
"Petak",
"Subota",
"Nedjelja",
];
}
@override
List<String> getWeeksShort() {
return [
"Pon",
"Uto",
"Sri",
"Čet",
"Pet",
"Sub",
"Ned",
];
}
}
part of 'date_picker_i18n.dart';
/// German (DE)
class _StringsDe extends _StringsI18n {
const _StringsDe();
@override
String getCancelText() {
return 'Abbrechen';
}
@override
String getDoneText() {
return 'Fertig';
}
@override
List<String> getMonths() {
return [
"Januar",
"Februar",
"März",
"April",
"Mai",
"Juni",
"Juli",
"August",
"September",
"Oktober",
"November",
"Dezember",
];
}
@override
List<String> getWeeksFull() {
return [
"Montag",
"Dienstag",
"Mittwoch",
"Donnerstag",
"Freitag",
"Samstag",
"Sonntag",
];
}
@override
List<String> getWeeksShort() {
return [
"Mo",
"Di",
"Mi",
"Do",
"Fr",
"Sa",
"So",
];
}
@override
List<String> getMonthsShort() {
// TODO: implement getMonthsShort
return null;
}
}
part of 'date_picker_i18n.dart';
/// English (EN) United States
class _StringsEnUs extends _StringsI18n {
const _StringsEnUs();
@override
String getCancelText() {
return 'Cancel';
}
@override
String getDoneText() {
return 'Done';
}
@override
List<String> getMonths() {
return [
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
];
}
@override
List<String> getMonthsShort() {
return [
"Jan.",
"Feb.",
"Mar.",
"Apr.",
"May",
"Jun",
"Jul.",
"Aug.",
"Sep.",
"Oct.",
"Nov.",
"Dec.",
];
}
@override
List<String> getWeeksFull() {
return [
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday",
];
}
@override
List<String> getWeeksShort() {
return [
"Mon",
"Tue",
"Wed",
"Thur",
"Fri",
"Sat",
"Sun",
];
}
}
part of 'date_picker_i18n.dart';
/// Spanish (ES)
class _StringsEs extends _StringsI18n {
const _StringsEs();
@override
String getCancelText() {
return "Cancelar";
}
@override
String getDoneText() {
return "Aceptar";
}
@override
List<String> getMonths() {
return [
"Enero",
"Febrero",
"Marzo",
"Abril",
"Mayo",
"Junio",
"Julio",
"Agosto",
"Septiembre",
"Octubre",
"Noviembre",
"Diciembre"
];
}
@override
List<String> getWeeksFull() {
return [
"Lunes",
"Martes",
"Miercoles",
"Jueves",
"Viernes",
"Sabado",
"Domingo",
];
}
@override
List<String> getWeeksShort() {
return null;
}
@override
List<String> getMonthsShort() {
// TODO: implement getMonthsShort
return null;
}
}
part of 'date_picker_i18n.dart';
/// French (FR)
class _StringsFr extends _StringsI18n {
const _StringsFr();
@override
String getCancelText() {
return 'Annuler';
}
@override
String getDoneText() {
return 'Accepter';
}
@override
List<String> getMonths() {
return [
"Janvier",
"Février",
"Mars",
"Avril",
"Mai",
"Juin",
"Juillet",
"Août",
"Septembre",
"Octobre",
"Novembre",
"Décembre",
];
}
@override
List<String> getMonthsShort() {
return [
"Janv.",
"Févr.",
"Mars",
"Avr.",
"Mai",
"Juin",
"Juil.",
"Août",
"Sept.",
"Oct.",
"Nov.",
"Déc."
];
}
@override
List<String> getWeeksFull() {
return [
"Lundi",
"Mardi",
"Mercredi",
"Jeudi",
"Vendredi",
"Samedi",
"Dimanche",
];
}
@override
List<String> getWeeksShort() {
return [
"Lun.",
"Mar.",
"Mer.",
"Jeu.",
"Ven.",
"Sam.",
"Dim.",
];
}
}
part of 'date_picker_i18n.dart';
/// Croatian (HR)
class _StringsHr extends _StringsI18n {
const _StringsHr();
@override
String getCancelText() {
return 'Otkaži';
}
@override
String getDoneText() {
return 'Završi';
}
@override
List<String> getMonths() {
return [
"Siječanj",
"Veljača",
"Ožujak",
"Travanj",
"Svibanj",
"Lipanj",
"Srpanj",
"Kolovoz",
"Rujan",
"Listopad",
"Studeni",
"Prosinac",
];
}
@override
List<String> getMonthsShort() {
return null;
}
@override
List<String> getWeeksFull() {
return [
"Ponedjeljak",
"Utorak",
"Srijeda",
"Četvrtak",
"Petak",
"Subota",
"Nedjelja",
];
}
@override
List<String> getWeeksShort() {
return [
"Pon",
"Uto",
"Sri",
"Čet",
"Pet",
"Sub",
"Ned",
];
}
}
part of 'date_picker_i18n.dart';
/// Hungarian
class _StringsHu extends _StringsI18n {
const _StringsHu();
@override
String getCancelText() {
return 'Mégsem';
}
@override
String getDoneText() {
return 'Mentés';
}
@override
List<String> getMonths() {
return [
"Január",
"Február",
"Március",
"Április",
"Május",
"Június",
"Július",
"Augusztus",
"Szeptember",
"Október",
"November",
"December"
];
}
@override
List<String> getWeeksFull() {
return [
"Hétfő",
"Kedd",
"Szerda",
"Csütörtök",
"Péntek",
"Szombat",
"Vasárnap",
];
}
@override
List<String> getWeeksShort() {
return [
"H",
"K",
"Sze",
"Cs",
"P",
"Szo",
"V",
];
}
@override
List<String> getMonthsShort() {
// TODO: implement getMonthsShort
return null;
}
}
part of 'date_picker_i18n.dart';
/// Indonesia (ID)
class _StringsId extends _StringsI18n {
const _StringsId();
@override
String getCancelText() {
return 'Batalkan';
}
@override
String getDoneText() {
return 'Simpan';
}
@override
List<String> getMonths() {
return [
'Januari',
'Februari',
'Maret',
'April',
'Mei',
'Juni',
'Juli',
'Agustus',
'September',
'Oktober',
'November',
'Desember'
];
}
@override
List<String> getMonthsShort() {
return null;
}
@override
List<String> getWeeksFull() {
return ['Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat', 'Sabtu', 'Minggu'];
}
@override
List<String> getWeeksShort() {
return ['Sen', 'Sel', 'Rab', 'Kam', 'Jum', 'Sab', 'Min'];
}
}
part of 'date_picker_i18n.dart';
/// Italian (IT)
class _StringsIt extends _StringsI18n {
const _StringsIt();
@override
String getCancelText() {
return 'Annulla';
}
@override
String getDoneText() {
return 'Salva';
}
@override
List<String> getMonths() {
return [
"Gennaio",
"Febbraio",
"Marzo",
"Aprile",
"Maggio",
"Giugno",
"Luglio",
"Agosto",
"Settembre",
"Ottobre",
"Novembre",
"Dicembre"
];
}
@override
List<String> getWeeksFull() {
return [
"Lunedì",
"Martedì",
"Mercoledì",
"Giovedì",
"Venerdì",
"Sabato",
"Domenica",
];
}
@override
List<String> getWeeksShort() {
return [
"Lu",
"Ma",
"Me",
"Gi",
"Ve",
"Sa",
"Do",
];
}
@override
List<String> getMonthsShort() {
// TODO: implement getMonthsShort
return null;
}
}
part of 'date_picker_i18n.dart';
/// Japanese (JP)
class _StringsJp extends _StringsI18n {
const _StringsJp();
@override
String getCancelText() {
return 'キャンセル';
}
@override
String getDoneText() {
return '完了';
}
@override
List<String> getMonths() {
return [
"1月",
"2月",
"3月",
"4月",
"5月",
"6月",
"7月",
"8月",
"9月",
"10月",
"11月",
"12月"
];
}
@override
List<String> getWeeksFull() {
return [
"月曜日",
"火曜日",
"水曜日",
"木曜日",
"金曜日",
"土曜日",
"日曜日",
];
}
@override
List<String> getWeeksShort() {
return [
"月",
"火",
"水",
"木",
"金",
"土",
"日",
];
}
@override
List<String> getMonthsShort() {
// TODO: implement getMonthsShort
return null;
}
}
part of 'date_picker_i18n.dart';
/// Korea (KO)
class _StringsKo extends _StringsI18n {
const _StringsKo();
@override
String getCancelText() {
return '취소';
}
@override
String getDoneText() {
return '완료';
}
@override
List<String> getMonths() {
return [
"1월",
"2월",
"3월",
"4월",
"5월",
"6월",
"7월",
"8월",
"9월",
"10월",
"11월",
"12월"
];
}
@override
List<String> getWeeksFull() {
return [
"월요일",
"화요일",
"수요일",
"목요일",
"금요일",
"토요일",
"일요일",
];
}
@override
List<String> getWeeksShort() {
return [
"월",
"화",
"수",
"목",
"금",
"토",
"일",
];
}
@override
List<String> getMonthsShort() {
// TODO: implement getMonthsShort
return null;
}
}
part of 'date_picker_i18n.dart';
/// Dutch (NL)
class _StringsNl extends _StringsI18n {
const _StringsNl();
@override
String getCancelText() {
return 'Annuleer';
}
@override
String getDoneText() {
return 'Bewaar';
}
@override
List<String> getMonths() {
return [
"Januari",
"Februari",
"Maart",
"April",
"Mei",
"Juni",
"Juli",
"Augustus",
"September",
"Oktober",
"November",
"December",
];
}
@override
List<String> getMonthsShort() {
return [
"Jan.",
"Febr.",
"Maart",
"Apr.",
"Mei",
"Juni",
"Juli",
"Aug.",
"Sept.",
"Okt.",
"Nov.",
"Dec.",
];
}
@override
List<String> getWeeksFull() {
return [
"Maandag",
"Dinsdag",
"Woensdag",
"Donderdag",
"Vrijdag",
"Zaterdag",
"Zondag",
];
}
@override
List<String> getWeeksShort() {
return [
"Ma.",
"Di.",
"Wo.",
"Do.",
"Vr.",
"Za.",
"Zo.",
];
}
}
part of 'date_picker_i18n.dart';
/// Portuguese (PT) Brazil
class _StringsPtBr extends _StringsI18n {
const _StringsPtBr();
@override
String getCancelText() {
return 'Cancelar';
}
@override
String getDoneText() {
return 'Confirmar';
}
@override
List<String> getMonths() {
return [
"Janeiro",
"Fevereiro",
"Março",
"Abril",
"Maio",
"Junho",
"Julho",
"Agosto",
"Setembro",
"Outubro",
"Novembro",
"Dezembro"
];
}
@override
List<String> getMonthsShort() {
return [
"Jan.",
"Fev.",
"Mar.",
"Abr.",
"Mai.",
"Jun.",
"Jul.",
"Ago.",
"Set.",
"Out.",
"Nov.",
"Dez.",
];
}
@override
List<String> getWeeksFull() {
return [
"Segunda",
"Terca",
"Quarta",
"Quinta",
"Sexta",
"Sabado",
"Domingo",
];
}
@override
List<String> getWeeksShort() {
return [
"Seg",
"Ter",
"Qua",
"Qui",
"Sex",
"Sab",
"Dom",
];
}
}
part of 'date_picker_i18n.dart';
/// Romanian (RO)
class _StringsRo extends _StringsI18n {
const _StringsRo();
@override
String getCancelText() {
return "Anulare";
}
@override
String getDoneText() {
return "Ok";
}
@override
List<String> getMonths() {
return [
"Ianuarie",
"Februarie",
"Martie",
"Aprilie",
"Mai",
"Iunie",
"Iulie",
"August",
"Septembrie",
"Octombrie",
"Noiembrie",
"Decembrie"
];
}
@override
List<String> getWeeksFull() {
return [
"Luni",
"Marti",
"Miercuri",
"Joi",
"Vineri",
"Sambata",
"Duminica"
];
}
@override
List<String> getWeeksShort() {
return null;
}
@override
List<String> getMonthsShort() {
// TODO: implement getMonthsShort
return null;
}
}
part of 'date_picker_i18n.dart';
/// Russian (RU)
class _StringsRu extends _StringsI18n {
const _StringsRu();
@override
String getCancelText() {
return 'Отмена';
}
@override
String getDoneText() {
return 'Готово';
}
@override
List<String> getMonths() {
return [
"Январь",
"Февраль",
"Март",
"Апрель",
"Май",
"Июнь",
"Июль",
"Август",
"Сентябрь",
"Октябрь",
"Ноябрь",
"Декабрь",
];
}
@override
List<String> getWeeksFull() {
return [
"Понедельник",
"Вторник",
"Среда",
"Четверг",
"Пятница",
"Суббота",
"Воскресенье",
];
}
@override
List<String> getWeeksShort() {
return [
"пн",
"вт",
"ср",
"чт",
"пт",
"сб",
"вс",
];
}
@override
List<String> getMonthsShort() {
// TODO: implement getMonthsShort
return null;
}
}
part of 'date_picker_i18n.dart';
/// Serbia (sr) Cyrillic
class _StringsSrCyrillic extends _StringsI18n {
const _StringsSrCyrillic();
@override
String getCancelText() {
return 'Откажи';
}
@override
String getDoneText() {
return 'Изабери';
}
@override
List<String> getMonths() {
return [
"Јануар",
"Фебруар",
"Март",
"Април",
"Мај",
"Јун",
"Јул",
"Август",
"Септембар",
"Октобар",
"Новембар",
"Децембар"
];
}
@override
List<String> getMonthsShort() {
return null;
}
@override
List<String> getWeeksFull() {
return [
"Понедељак",
"Уторак",
"Среда",
"Четвртак",
"Петак",
"Субота",
"Недеља",
];
}
@override
List<String> getWeeksShort() {
return [
"Пон",
"Уто",
"Сре",
"Чет",
"Пет",
"Суб",
"Нед",
];
}
}
part of 'date_picker_i18n.dart';
/// Serbia (sr) Latin
class _StringsSrLatin extends _StringsI18n {
const _StringsSrLatin();
@override
String getCancelText() {
return 'Otkaži';
}
@override
String getDoneText() {
return 'Izaberi';
}
@override
List<String> getMonths() {
return [
"Januar",
"Februar",
"Mart",
"April",
"Maj",
"Jun",
"Jul",
"Avgust",
"Septembar",
"Octobar",
"Novembar",
"Decembar"
];
}
@override
List<String> getMonthsShort() {
return null;
}
@override
List<String> getWeeksFull() {
return [
"Ponedeljak",
"Utorak",
"Sreda",
"Četvrtak",
"Petak",
"Subota",
"Nedelja",
];
}
@override
List<String> getWeeksShort() {
return [
"Pon",
"Uto",
"Sre",
"Čet",
"Pet",
"Sub",
"Ned",
];
}
}
part of 'date_picker_i18n.dart';
/// Turkish (TR)
class _StringsTr extends _StringsI18n {
const _StringsTr();
@override
String getCancelText() {
return 'Vazgeç';
}
@override
String getDoneText() {
return 'Tamam';
}
@override
List<String> getMonths() {
return [
"Ocak",
"Şubat",
"Mart",
"Nisan",
"Mayıs",
"Haziran",
"Temmuz",
"Ağustos",
"Eylül",
"Ekim",
"Kasım",
"Aralık"
];
}
@override
List<String> getMonthsShort() {
return null;
}
@override
List<String> getWeeksFull() {
return [
"Pazartesi",
"Salı",
"Çarşamba",
"Perşembe",
"Cuma",
"Cumartesi",
"Pazar",
];
}
@override
List<String> getWeeksShort() {
return [
"Pzt",
"Sal",
"Çrs",
"Per",
"Cum",
"Cmt",
"Pzr",
];
}
}
part of 'date_picker_i18n.dart';
/// Ukraine (UK)
class _StringsUk extends _StringsI18n {
const _StringsUk();
@override
String getCancelText() {
return 'Скасувати';
}
@override
String getDoneText() {
return 'Готово';
}
@override
List<String> getMonths() {
return [
"Cічень",
"Лютий",
"Березень",
"Квітень",
"Травень",
"Червень",
"Липень",
"Серпень",
"Вересень",
"Жовтень",
"Листопад",
"Грудень",
];
}
@override
List<String> getMonthsShort() {
return null;
}
@override
List<String> getWeeksFull() {
return [
"Понеділок",
"Вівторок",
"Середа",
"Четвер",
\'ятниця",
"Субота",
"Неділя",
];
}
@override
List<String> getWeeksShort() {
return [
"пн",
"вт",
"ср",
"чт",
"пт",
"сб",
"нд",
];
}
}
part of 'date_picker_i18n.dart';
/// Vietnamese (VI) Vietnam
class _StringsVn extends _StringsI18n {
const _StringsVn();
@override
String getCancelText() {
return 'Hủy';
}
@override
String getDoneText() {
return 'Xong';
}
@override
List<String> getMonths() {
return [
"Tháng 1",
"Tháng 2",
"Tháng 3",
"Tháng 4",
"Tháng 5",
"Tháng 6",
"Tháng 7",
"Tháng 8",
"Tháng 9",
"Tháng 10",
"Tháng 11",
"Tháng 12"
];
}
@override
List<String> getMonthsShort() {
return null;
}
@override
List<String> getWeeksFull() {
return [
"Thứ 2",
"Thứ 3",
"Thứ 4",
"Thứ 5",
"Thứ 6",
"Thứ 7",
"Chủ nhật",
];
}
@override
List<String> getWeeksShort() {
return ['T2', 'T3', 'T4', 'T5', 'T6', 'T7', 'CN'];
}
}
part of 'date_picker_i18n.dart';
/// Chinese (ZH) Simplified
class _StringsZhCn extends _StringsI18n {
const _StringsZhCn();
@override
String getCancelText() {
return '取消';
}
@override
String getDoneText() {
return '确定';
}
@override
List<String> getMonths() {
return [
"01",
"02",
"03",
"04",
"05",
"06",
"07",
"08",
"09",
"10",
"11",
"12"
];
}
@override
List<String> getWeeksFull() {
return [
"星期一",
"星期二",
"星期三",
"星期四",
"星期五",
"星期六",
"星期日",
];
}
@override
List<String> getWeeksShort() {
return [
"周一",
"周二",
"周三",
"周四",
"周五",
"周六",
"周日",
];
}
@override
List<String> getMonthsShort() {
// TODO: implement getMonthsShort
return null;
}
}
import 'package:flutter/material.dart';
import '../date_picker_constants.dart';
import '../date_picker_theme.dart';
import '../i18n/date_picker_i18n.dart';
/// DatePicker's title widget.
///
/// @author dylan wu
/// @since 2019-05-16
class DatePickerTitleWidget extends StatelessWidget {
DatePickerTitleWidget({
Key key,
this.pickerTheme,
this.locale,
@required this.onCancel,
@required this.onConfirm,
}) : super(key: key);
final DateTimePickerTheme pickerTheme;
final DateTimePickerLocale locale;
final DateVoidCallback onCancel, onConfirm;
@override
Widget build(BuildContext context) {
if (pickerTheme.title != null) {
return pickerTheme.title;
}
return Container(
height: pickerTheme.titleHeight,
decoration: BoxDecoration(color: pickerTheme.backgroundColor),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
_renderCancelWidget(context),
_renderConfirmWidget(context),
],
),
);
}
/// render cancel button widget
Widget _renderCancelWidget(BuildContext context) {
if (isCustomTitleWidget()) {
// has custom title button widget
if (pickerTheme.cancel == null) {
return Offstage();
}
}
Widget cancelWidget = pickerTheme.cancel;
if (cancelWidget == null) {
TextStyle textStyle = pickerTheme.cancelTextStyle ??
TextStyle(
color: Theme.of(context).unselectedWidgetColor,
fontSize: 16.0,
);
cancelWidget = Text(
DatePickerI18n.getLocaleCancel(locale),
style: textStyle,
);
}
return Container(
height: pickerTheme.titleHeight,
child: FlatButton(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.zero),
child: cancelWidget,
onPressed: () => this.onCancel(),
),
);
}
/// render confirm button widget
Widget _renderConfirmWidget(BuildContext context) {
if (isCustomTitleWidget()) {
// has custom title button widget
if (pickerTheme.confirm == null) {
return Offstage();
}
}
Widget confirmWidget = pickerTheme.confirm;
if (confirmWidget == null) {
TextStyle textStyle = pickerTheme.confirmTextStyle ??
TextStyle(
color: Theme.of(context).primaryColor,
fontSize: 16.0,
);
confirmWidget = Text(
DatePickerI18n.getLocaleDone(locale),
style: textStyle,
);
}
return Container(
height: pickerTheme.titleHeight,
child: FlatButton(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.zero),
child: confirmWidget,
onPressed: () => this.onConfirm(),
),
);
}
bool isCustomTitleWidget() {
return pickerTheme.cancel != null ||
pickerTheme.confirm != null ||
pickerTheme.title != null;
}
}
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import '../date_time_formatter.dart';
import '../date_picker_theme.dart';
import '../date_picker_constants.dart';
import '../i18n/date_picker_i18n.dart';
import 'date_picker_title_widget.dart';
/// Solar months of 31 days.
const List<int> _solarMonthsOf31Days = const <int>[1, 3, 5, 7, 8, 10, 12];
/// DatePicker widget.
///
/// @author dylan wu
/// @since 2019-05-10
class DatePickerWidget extends StatefulWidget {
DatePickerWidget({
Key key,
this.onMonthChangeStartWithFirstDate,
this.minDateTime,
this.maxDateTime,
this.initialDateTime,
this.dateFormat: DATETIME_PICKER_DATE_FORMAT,
this.locale: DATETIME_PICKER_LOCALE_DEFAULT,
this.pickerTheme: DateTimePickerTheme.Default,
this.onCancel,
this.onChange,
this.onConfirm,
}) : super(key: key) {
DateTime minTime = minDateTime ?? DateTime.parse(DATE_PICKER_MIN_DATETIME);
DateTime maxTime = maxDateTime ?? DateTime.parse(DATE_PICKER_MAX_DATETIME);
assert(minTime.compareTo(maxTime) < 0);
}
final DateTime minDateTime, maxDateTime, initialDateTime;
final String dateFormat;
final DateTimePickerLocale locale;
final DateTimePickerTheme pickerTheme;
final DateVoidCallback onCancel;
final DateValueCallback onChange, onConfirm;
final onMonthChangeStartWithFirstDate;
@override
State<StatefulWidget> createState() => _DatePickerWidgetState(
this.minDateTime, this.maxDateTime, this.initialDateTime);
}
class _DatePickerWidgetState extends State<DatePickerWidget> {
DateTime _minDateTime, _maxDateTime;
int _currYear, _currMonth, _currDay;
List<int> _yearRange, _monthRange, _dayRange;
FixedExtentScrollController _yearScrollCtrl, _monthScrollCtrl, _dayScrollCtrl;
Map<String, FixedExtentScrollController> _scrollCtrlMap;
Map<String, List<int>> _valueRangeMap;
bool _isChangeDateRange = false;
_DatePickerWidgetState(
DateTime minDateTime, DateTime maxDateTime, DateTime initialDateTime) {
// handle current selected year、month、day
DateTime initDateTime = initialDateTime ?? DateTime.now();
this._currYear = initDateTime.year;
this._currMonth = initDateTime.month;
this._currDay = initDateTime.day;
// handle DateTime range
this._minDateTime = minDateTime ?? DateTime.parse(DATE_PICKER_MIN_DATETIME);
this._maxDateTime = maxDateTime ?? DateTime.parse(DATE_PICKER_MAX_DATETIME);
// limit the range of year
this._yearRange = _calcYearRange();
this._currYear = min(max(_minDateTime.year, _currYear), _maxDateTime.year);
// limit the range of month
this._monthRange = _calcMonthRange();
this._currMonth = min(max(_monthRange.first, _currMonth), _monthRange.last);
// limit the range of day
this._dayRange = _calcDayRange();
this._currDay = min(max(_dayRange.first, _currDay), _dayRange.last);
// create scroll controller
_yearScrollCtrl =
FixedExtentScrollController(initialItem: _currYear - _yearRange.first);
_monthScrollCtrl = FixedExtentScrollController(
initialItem: _currMonth - _monthRange.first);
_dayScrollCtrl =
FixedExtentScrollController(initialItem: _currDay - _dayRange.first);
_scrollCtrlMap = {
'y': _yearScrollCtrl,
'M': _monthScrollCtrl,
'd': _dayScrollCtrl
};
_valueRangeMap = {'y': _yearRange, 'M': _monthRange, 'd': _dayRange};
}
@override
Widget build(BuildContext context) {
return GestureDetector(
child: Material(
color: Colors.transparent, child: _renderPickerView(context)),
);
}
/// render date picker widgets
Widget _renderPickerView(BuildContext context) {
Widget datePickerWidget = _renderDatePickerWidget();
// display the title widget
if (widget.pickerTheme.title != null || widget.pickerTheme.showTitle) {
Widget titleWidget = DatePickerTitleWidget(
pickerTheme: widget.pickerTheme,
locale: widget.locale,
onCancel: () => _onPressedCancel(),
onConfirm: () => _onPressedConfirm(),
);
return Column(children: <Widget>[titleWidget, datePickerWidget]);
}
return datePickerWidget;
}
/// pressed cancel widget
void _onPressedCancel() {
if (widget.onCancel != null) {
widget.onCancel();
}
Navigator.pop(context);
}
/// pressed confirm widget
void _onPressedConfirm() {
if (widget.onConfirm != null) {
DateTime dateTime = DateTime(_currYear, _currMonth, _currDay);
widget.onConfirm(dateTime, _calcSelectIndexList());
}
Navigator.pop(context);
}
/// notify selected date changed
void _onSelectedChange() {
if (widget.onChange != null) {
DateTime dateTime = DateTime(_currYear, _currMonth, _currDay);
widget.onChange(dateTime, _calcSelectIndexList());
}
}
/// find scroll controller by specified format
FixedExtentScrollController _findScrollCtrl(String format) {
FixedExtentScrollController scrollCtrl;
_scrollCtrlMap.forEach((key, value) {
if (format.contains(key)) {
scrollCtrl = value;
}
});
return scrollCtrl;
}
/// find item value range by specified format
List<int> _findPickerItemRange(String format) {
List<int> valueRange;
_valueRangeMap.forEach((key, value) {
if (format.contains(key)) {
valueRange = value;
}
});
return valueRange;
}
/// render the picker widget of year、month and day
Widget _renderDatePickerWidget() {
List<Widget> pickers = List<Widget>();
List<String> formatArr =
DateTimeFormatter.splitDateFormat(widget.dateFormat);
formatArr.forEach((format) {
List<int> valueRange = _findPickerItemRange(format);
Widget pickerColumn = _renderDatePickerColumnComponent(
scrollCtrl: _findScrollCtrl(format),
valueRange: valueRange,
format: format,
valueChanged: (value) {
if (format.contains('y')) {
_changeYearSelection(value);
} else if (format.contains('M')) {
_changeMonthSelection(value);
} else if (format.contains('d')) {
_changeDaySelection(value);
}
},
);
pickers.add(pickerColumn);
});
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, children: pickers);
}
Widget _renderDatePickerColumnComponent({
@required FixedExtentScrollController scrollCtrl,
@required List<int> valueRange,
@required String format,
@required ValueChanged<int> valueChanged,
}) {
return Expanded(
flex: 1,
child: Container(
padding: EdgeInsets.all(8.0),
height: widget.pickerTheme.pickerHeight,
decoration: BoxDecoration(color: widget.pickerTheme.backgroundColor),
child: CupertinoPicker.builder(
backgroundColor: widget.pickerTheme.backgroundColor,
scrollController: scrollCtrl,
itemExtent: widget.pickerTheme.itemHeight,
onSelectedItemChanged: valueChanged,
childCount: valueRange.last - valueRange.first + 1,
itemBuilder: (context, index) =>
_renderDatePickerItemComponent(valueRange.first + index, format),
),
),
);
}
Widget _renderDatePickerItemComponent(int value, String format) {
return Container(
height: widget.pickerTheme.itemHeight,
alignment: Alignment.center,
child: Text(
DateTimeFormatter.formatDateTime(value, format, widget.locale),
style:
widget.pickerTheme.itemTextStyle ?? DATETIME_PICKER_ITEM_TEXT_STYLE,
),
);
}
/// change the selection of year picker
void _changeYearSelection(int index) {
int year = _yearRange.first + index;
if (_currYear != year) {
_currYear = year;
_changeDateRange();
_onSelectedChange();
}
}
/// change the selection of month picker
void _changeMonthSelection(int index) {
int month = _monthRange.first + index;
if (_currMonth != month) {
_currMonth = month;
_changeDateRange();
_onSelectedChange();
}
}
/// change the selection of day picker
void _changeDaySelection(int index) {
int dayOfMonth = _dayRange.first + index;
if (_currDay != dayOfMonth) {
_currDay = dayOfMonth;
_onSelectedChange();
}
}
/// change range of month and day
void _changeDateRange() {
if (_isChangeDateRange) {
return;
}
_isChangeDateRange = true;
List<int> monthRange = _calcMonthRange();
bool monthRangeChanged = _monthRange.first != monthRange.first ||
_monthRange.last != monthRange.last;
if (monthRangeChanged) {
// selected year changed
_currMonth = max(min(_currMonth, monthRange.last), monthRange.first);
}
List<int> dayRange = _calcDayRange();
bool dayRangeChanged =
_dayRange.first != dayRange.first || _dayRange.last != dayRange.last;
if (dayRangeChanged) {
// day range changed, need limit the value of selected day
if (!widget.onMonthChangeStartWithFirstDate) {
max(min(_currDay, dayRange.last), dayRange.first);
} else {
_currDay = dayRange.first;
}
}
setState(() {
_monthRange = monthRange;
_dayRange = dayRange;
_valueRangeMap['M'] = monthRange;
_valueRangeMap['d'] = dayRange;
});
if (monthRangeChanged) {
// CupertinoPicker refresh data not working (https://github.com/flutter/flutter/issues/22999)
int currMonth = _currMonth;
_monthScrollCtrl.jumpToItem(monthRange.last - monthRange.first);
if (currMonth < monthRange.last) {
_monthScrollCtrl.jumpToItem(currMonth - monthRange.first);
}
}
if (dayRangeChanged) {
// CupertinoPicker refresh data not working (https://github.com/flutter/flutter/issues/22999)
int currDay = _currDay;
_dayScrollCtrl.jumpToItem(dayRange.last - dayRange.first);
if (currDay < dayRange.last) {
_dayScrollCtrl.jumpToItem(currDay - dayRange.first);
}
}
_isChangeDateRange = false;
}
/// calculate the count of day in current month
int _calcDayCountOfMonth() {
if (_currMonth == 2) {
return isLeapYear(_currYear) ? 29 : 28;
} else if (_solarMonthsOf31Days.contains(_currMonth)) {
return 31;
}
return 30;
}
/// whether or not is leap year
bool isLeapYear(int year) {
return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
}
/// calculate selected index list
List<int> _calcSelectIndexList() {
int yearIndex = _currYear - _minDateTime.year;
int monthIndex = _currMonth - _monthRange.first;
int dayIndex = _currDay - _dayRange.first;
return [yearIndex, monthIndex, dayIndex];
}
/// calculate the range of year
List<int> _calcYearRange() {
print(_minDateTime.year.toString() + ", " + _maxDateTime.year.toString());
return [_minDateTime.year, _maxDateTime.year];
}
/// calculate the range of month
List<int> _calcMonthRange() {
int minMonth = 1, maxMonth = 12;
int minYear = _minDateTime.year;
int maxYear = _maxDateTime.year;
if (minYear == _currYear) {
// selected minimum year, limit month range
minMonth = _minDateTime.month;
}
if (maxYear == _currYear) {
// selected maximum year, limit month range
maxMonth = _maxDateTime.month;
}
return [minMonth, maxMonth];
}
/// calculate the range of day
List<int> _calcDayRange({currMonth}) {
int minDay = 1, maxDay = _calcDayCountOfMonth();
int minYear = _minDateTime.year;
int maxYear = _maxDateTime.year;
int minMonth = _minDateTime.month;
int maxMonth = _maxDateTime.month;
if (currMonth == null) {
currMonth = _currMonth;
}
if (minYear == _currYear && minMonth == currMonth) {
// selected minimum year and month, limit day range
minDay = _minDateTime.day;
}
if (maxYear == _currYear && maxMonth == currMonth) {
// selected maximum year and month, limit day range
maxDay = _maxDateTime.day;
}
return [minDay, maxDay];
}
}
import 'dart:math';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import '../date_picker.dart';
import '../date_picker_constants.dart';
import '../date_picker_theme.dart';
import '../date_time_formatter.dart';
import '../i18n/date_picker_i18n.dart';
import 'date_picker_title_widget.dart';
/// DateTimePicker widget. Can display date and time picker.
///
/// @author dylan wu
/// @since 2019-05-10
class DateTimePickerWidget extends StatefulWidget {
DateTimePickerWidget({
Key key,
this.minDateTime,
this.maxDateTime,
this.initDateTime,
this.dateFormat: DATETIME_PICKER_TIME_FORMAT,
this.locale: DATETIME_PICKER_LOCALE_DEFAULT,
this.pickerTheme: DateTimePickerTheme.Default,
this.minuteDivider = 1,
this.onCancel,
this.onChange,
this.onConfirm,
}) : super(key: key) {
DateTime minTime = minDateTime ?? DateTime.parse(DATE_PICKER_MIN_DATETIME);
DateTime maxTime = maxDateTime ?? DateTime.parse(DATE_PICKER_MAX_DATETIME);
assert(minTime.compareTo(maxTime) < 0);
}
final DateTime minDateTime, maxDateTime, initDateTime;
final String dateFormat;
final DateTimePickerLocale locale;
final DateTimePickerTheme pickerTheme;
final DateVoidCallback onCancel;
final DateValueCallback onChange, onConfirm;
final int minuteDivider;
@override
State<StatefulWidget> createState() => _DateTimePickerWidgetState(
this.minDateTime,
this.maxDateTime,
this.initDateTime,
this.minuteDivider);
}
class _DateTimePickerWidgetState extends State<DateTimePickerWidget> {
DateTime _minTime, _maxTime;
int _currDay, _currHour, _currMinute, _currSecond;
int _minuteDivider;
List<int> _dayRange, _hourRange, _minuteRange, _secondRange;
FixedExtentScrollController _dayScrollCtrl,
_hourScrollCtrl,
_minuteScrollCtrl,
_secondScrollCtrl;
Map<String, FixedExtentScrollController> _scrollCtrlMap;
Map<String, List<int>> _valueRangeMap;
bool _isChangeTimeRange = false;
final DateTime _baselineDate = DateTime(1900, 1, 1);
_DateTimePickerWidgetState(DateTime minTime, DateTime maxTime,
DateTime initTime, int minuteDivider) {
// check minTime value
if (minTime == null) {
minTime = DateTime.parse(DATE_PICKER_MIN_DATETIME);
}
// check maxTime value
if (maxTime == null) {
maxTime = DateTime.parse(DATE_PICKER_MAX_DATETIME);
}
// check initTime value
if (initTime == null) {
initTime = DateTime.now();
}
// limit initTime value
if (initTime.compareTo(minTime) < 0) {
initTime = minTime;
}
if (initTime.compareTo(maxTime) > 0) {
initTime = maxTime;
}
this._minTime = minTime;
this._maxTime = maxTime;
this._currHour = initTime.hour;
this._currMinute = initTime.minute;
this._currSecond = initTime.second;
this._minuteDivider = minuteDivider;
// limit the range of date
this._dayRange = _calcDayRange();
int currDate = initTime.difference(_baselineDate).inDays;
this._currDay = min(max(_dayRange.first, currDate), _dayRange.last);
// limit the range of hour
this._hourRange = _calcHourRange();
this._currHour = min(max(_hourRange.first, _currHour), _hourRange.last);
// limit the range of minute
this._minuteRange = _calcMinuteRange();
this._currMinute =
min(max(_minuteRange.first, _currMinute), _minuteRange.last);
// limit the range of second
this._secondRange = _calcSecondRange();
this._currSecond =
min(max(_secondRange.first, _currSecond), _secondRange.last);
// create scroll controller
_dayScrollCtrl =
FixedExtentScrollController(initialItem: _currDay - _dayRange.first);
_hourScrollCtrl =
FixedExtentScrollController(initialItem: _currHour - _hourRange.first);
_minuteScrollCtrl = FixedExtentScrollController(
initialItem: (_currMinute - _minuteRange.first) ~/ _minuteDivider);
_secondScrollCtrl = FixedExtentScrollController(
initialItem: _currSecond - _secondRange.first);
_scrollCtrlMap = {
'H': _hourScrollCtrl,
'm': _minuteScrollCtrl,
's': _secondScrollCtrl
};
_valueRangeMap = {'H': _hourRange, 'm': _minuteRange, 's': _secondRange};
}
@override
Widget build(BuildContext context) {
return GestureDetector(
child: Material(
color: Colors.transparent, child: _renderPickerView(context)),
);
}
/// render time picker widgets
Widget _renderPickerView(BuildContext context) {
Widget pickerWidget = _renderDatePickerWidget();
// display the title widget
if (widget.pickerTheme.title != null || widget.pickerTheme.showTitle) {
Widget titleWidget = DatePickerTitleWidget(
pickerTheme: widget.pickerTheme,
locale: widget.locale,
onCancel: () => _onPressedCancel(),
onConfirm: () => _onPressedConfirm(),
);
return Column(children: <Widget>[titleWidget, pickerWidget]);
}
return pickerWidget;
}
/// pressed cancel widget
void _onPressedCancel() {
if (widget.onCancel != null) {
widget.onCancel();
}
Navigator.pop(context);
}
/// pressed confirm widget
void _onPressedConfirm() {
if (widget.onConfirm != null) {
DateTime day = _baselineDate.add(Duration(days: _currDay));
DateTime dateTime = DateTime(
day.year, day.month, day.day, _currHour, _currMinute, _currSecond);
widget.onConfirm(dateTime, _calcSelectIndexList());
}
Navigator.pop(context);
}
/// notify selected datetime changed
void _onSelectedChange() {
if (widget.onChange != null) {
DateTime day = _baselineDate.add(Duration(days: _currDay));
DateTime dateTime = DateTime(
day.year, day.month, day.day, _currHour, _currMinute, _currSecond);
widget.onChange(dateTime, _calcSelectIndexList());
}
}
/// find scroll controller by specified format
FixedExtentScrollController _findScrollCtrl(String format) {
FixedExtentScrollController scrollCtrl;
_scrollCtrlMap.forEach((key, value) {
if (format.contains(key)) {
scrollCtrl = value;
}
});
return scrollCtrl;
}
/// find item value range by specified format
List<int> _findPickerItemRange(String format) {
List<int> valueRange;
_valueRangeMap.forEach((key, value) {
if (format.contains(key)) {
valueRange = value;
}
});
return valueRange;
}
/// render the picker widget of year、month and day
Widget _renderDatePickerWidget() {
List<Widget> pickers = List<Widget>();
List<String> formatArr = DateTimeFormatter.splitDateFormat(
widget.dateFormat,
mode: DateTimePickerMode.datetime);
int count = formatArr.length;
int dayFlex = count > 3 ? count - 1 : count;
// render day picker column
String dayFormat = formatArr.removeAt(0);
Widget dayPickerColumn = _renderDatePickerColumnComponent(
scrollCtrl: _dayScrollCtrl,
valueRange: _dayRange,
format: dayFormat,
valueChanged: (value) {
_changeDaySelection(value);
},
flex: dayFlex,
itemBuilder: (BuildContext context, int index) =>
_renderDayPickerItemComponent(_dayRange.first + index, dayFormat),
);
pickers.add(dayPickerColumn);
// render time picker column
formatArr.forEach((format) {
List<int> valueRange = _findPickerItemRange(format);
Widget pickerColumn = _renderDatePickerColumnComponent(
scrollCtrl: _findScrollCtrl(format),
valueRange: valueRange,
format: format,
flex: 1,
minuteDivider: widget.minuteDivider,
valueChanged: (value) {
if (format.contains('H')) {
_changeHourSelection(value);
} else if (format.contains('m')) {
_changeMinuteSelection(value);
} else if (format.contains('s')) {
_changeSecondSelection(value);
}
},
);
pickers.add(pickerColumn);
});
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, children: pickers);
}
Widget _renderDatePickerColumnComponent({
@required FixedExtentScrollController scrollCtrl,
@required List<int> valueRange,
@required String format,
@required ValueChanged<int> valueChanged,
int minuteDivider,
int flex,
IndexedWidgetBuilder itemBuilder,
}) {
IndexedWidgetBuilder builder = itemBuilder != null
? itemBuilder
: (context, index) {
int value = valueRange.first + index;
if (format.contains('m')) {
value = minuteDivider * index;
}
return _renderDatePickerItemComponent(value, format);
};
Widget columnWidget = Container(
padding: EdgeInsets.all(8.0),
width: double.infinity,
height: widget.pickerTheme.pickerHeight,
decoration: BoxDecoration(color: widget.pickerTheme.backgroundColor),
child: CupertinoPicker.builder(
backgroundColor: widget.pickerTheme.backgroundColor,
scrollController: scrollCtrl,
itemExtent: widget.pickerTheme.itemHeight,
onSelectedItemChanged: valueChanged,
childCount: format.contains('m')
? _calculateMinuteChildCount(valueRange, minuteDivider)
: valueRange.last - valueRange.first + 1,
itemBuilder: builder,
),
);
return Expanded(
flex: flex,
child: columnWidget,
);
}
_calculateMinuteChildCount(List<int> valueRange, int divider) {
if (divider == 0) {
debugPrint("Cant devide by 0");
return (valueRange.last - valueRange.first + 1);
}
return (valueRange.last - valueRange.first + 1) ~/ divider;
}
/// render day picker item
Widget _renderDayPickerItemComponent(int value, String format) {
DateTime dateTime = _baselineDate.add(Duration(days: value));
return Container(
height: widget.pickerTheme.itemHeight,
alignment: Alignment.center,
child: Text(
DateTimeFormatter.formatDate(dateTime, format, widget.locale),
style:
widget.pickerTheme.itemTextStyle ?? DATETIME_PICKER_ITEM_TEXT_STYLE,
),
);
}
/// render hour、minute、second picker item
Widget _renderDatePickerItemComponent(int value, String format) {
return Container(
height: widget.pickerTheme.itemHeight,
alignment: Alignment.center,
child: Text(
DateTimeFormatter.formatDateTime(value, format, widget.locale),
style:
widget.pickerTheme.itemTextStyle ?? DATETIME_PICKER_ITEM_TEXT_STYLE,
),
);
}
/// change the selection of day picker
void _changeDaySelection(int days) {
int value = _dayRange.first + days;
if (_currDay != value) {
_currDay = value;
_changeTimeRange();
_onSelectedChange();
}
}
/// change the selection of hour picker
void _changeHourSelection(int index) {
int value = _hourRange.first + index;
if (_currHour != value) {
_currHour = value;
_changeTimeRange();
_onSelectedChange();
}
}
/// change the selection of minute picker
void _changeMinuteSelection(int index) {
// TODO: copied from time_picker_widget - this looks like it would break date ranges but not taking into account _minuteRange.first
int value = index * _minuteDivider;
// int value = _minuteRange.first + index;
if (_currMinute != value) {
_currMinute = value;
_changeTimeRange();
_onSelectedChange();
}
}
/// change the selection of second picker
void _changeSecondSelection(int index) {
int value = _secondRange.first + index;
if (_currSecond != value) {
_currSecond = value;
_onSelectedChange();
}
}
/// change range of minute and second
void _changeTimeRange() {
if (_isChangeTimeRange) {
return;
}
_isChangeTimeRange = true;
List<int> hourRange = _calcHourRange();
bool hourRangeChanged = _hourRange.first != hourRange.first ||
_hourRange.last != hourRange.last;
if (hourRangeChanged) {
// selected day changed
_currHour = max(min(_currHour, hourRange.last), hourRange.first);
}
List<int> minuteRange = _calcMinuteRange();
bool minuteRangeChanged = _minuteRange.first != minuteRange.first ||
_minuteRange.last != minuteRange.last;
if (minuteRangeChanged) {
// selected hour changed
_currMinute = max(min(_currMinute, minuteRange.last), minuteRange.first);
}
List<int> secondRange = _calcSecondRange();
bool secondRangeChanged = _secondRange.first != secondRange.first ||
_secondRange.last != secondRange.last;
if (secondRangeChanged) {
// second range changed, need limit the value of selected second
_currSecond = max(min(_currSecond, secondRange.last), secondRange.first);
}
setState(() {
_hourRange = hourRange;
_minuteRange = minuteRange;
_secondRange = secondRange;
_valueRangeMap['H'] = hourRange;
_valueRangeMap['m'] = minuteRange;
_valueRangeMap['s'] = secondRange;
});
if (hourRangeChanged) {
// CupertinoPicker refresh data not working (https://github.com/flutter/flutter/issues/22999)
int currHour = _currHour;
_hourScrollCtrl.jumpToItem(hourRange.last - hourRange.first);
if (currHour < hourRange.last) {
_hourScrollCtrl.jumpToItem(currHour - hourRange.first);
}
}
if (minuteRangeChanged) {
// CupertinoPicker refresh data not working (https://github.com/flutter/flutter/issues/22999)
int currMinute = _currMinute;
_minuteScrollCtrl
.jumpToItem((minuteRange.last - minuteRange.first) ~/ _minuteDivider);
if (currMinute < minuteRange.last) {
_minuteScrollCtrl.jumpToItem(currMinute - minuteRange.first);
}
}
if (secondRangeChanged) {
// CupertinoPicker refresh data not working (https://github.com/flutter/flutter/issues/22999)
int currSecond = _currSecond;
_secondScrollCtrl.jumpToItem(secondRange.last - secondRange.first);
if (currSecond < secondRange.last) {
_secondScrollCtrl.jumpToItem(currSecond - secondRange.first);
}
}
_isChangeTimeRange = false;
}
/// calculate selected index list
List<int> _calcSelectIndexList() {
int hourIndex = _currHour - _hourRange.first;
int minuteIndex = _currMinute - _minuteRange.first;
int secondIndex = _currSecond - _secondRange.first;
return [hourIndex, minuteIndex, secondIndex];
}
/// calculate the range of day
List<int> _calcDayRange() {
int minDays = _minTime.difference(_baselineDate).inDays;
int maxDays = _maxTime.difference(_baselineDate).inDays;
return [minDays, maxDays];
}
/// calculate the range of hour
List<int> _calcHourRange() {
int minHour = 0, maxHour = 23;
if (_currDay == _dayRange.first) {
minHour = _minTime.hour;
}
if (_currDay == _dayRange.last) {
maxHour = _maxTime.hour;
}
return [minHour, maxHour];
}
/// calculate the range of minute
List<int> _calcMinuteRange({currHour}) {
int minMinute = 0, maxMinute = 59;
if (currHour == null) {
currHour = _currHour;
}
if (_currDay == _dayRange.first && currHour == _minTime.hour) {
// selected minimum day、hour, limit minute range
minMinute = _minTime.minute;
}
if (_currDay == _dayRange.last && currHour == _maxTime.hour) {
// selected maximum day、hour, limit minute range
maxMinute = _maxTime.minute;
}
return [minMinute, maxMinute];
}
/// calculate the range of second
List<int> _calcSecondRange({currHour, currMinute}) {
int minSecond = 0, maxSecond = 59;
if (currHour == null) {
currHour = _currHour;
}
if (currMinute == null) {
currMinute = _currMinute;
}
if (_currDay == _dayRange.first &&
currHour == _minTime.hour &&
currMinute == _minTime.minute) {
// selected minimum hour and minute, limit second range
minSecond = _minTime.second;
}
if (_currDay == _dayRange.last &&
currHour == _maxTime.hour &&
currMinute == _maxTime.minute) {
// selected maximum hour and minute, limit second range
maxSecond = _maxTime.second;
}
return [minSecond, maxSecond];
}
}
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import '../date_time_formatter.dart';
import '../date_picker_theme.dart';
import '../date_picker_constants.dart';
import '../i18n/date_picker_i18n.dart';
import 'date_picker_title_widget.dart';
/// TimePicker widget.
///
/// @author dylan wu
/// @since 2019-05-10
class TimePickerWidget extends StatefulWidget {
TimePickerWidget({
Key key,
this.minDateTime,
this.maxDateTime,
this.initDateTime,
this.dateFormat: DATETIME_PICKER_TIME_FORMAT,
this.locale: DATETIME_PICKER_LOCALE_DEFAULT,
this.pickerTheme: DateTimePickerTheme.Default,
this.minuteDivider = 1,
this.onCancel,
this.onChange,
this.onConfirm,
}) : super(key: key) {
DateTime minTime = minDateTime ?? DateTime.parse(DATE_PICKER_MIN_DATETIME);
DateTime maxTime = maxDateTime ?? DateTime.parse(DATE_PICKER_MAX_DATETIME);
assert(minTime.compareTo(maxTime) < 0);
}
final DateTime minDateTime, maxDateTime, initDateTime;
final String dateFormat;
final DateTimePickerLocale locale;
final DateTimePickerTheme pickerTheme;
final DateVoidCallback onCancel;
final DateValueCallback onChange, onConfirm;
final int minuteDivider;
@override
State<StatefulWidget> createState() => _TimePickerWidgetState(
this.minDateTime,
this.maxDateTime,
this.initDateTime,
this.minuteDivider);
}
class _TimePickerWidgetState extends State<TimePickerWidget> {
DateTime _minTime, _maxTime;
int _currHour, _currMinute, _currSecond;
int _minuteDivider;
List<int> _hourRange, _minuteRange, _secondRange;
FixedExtentScrollController _hourScrollCtrl,
_minuteScrollCtrl,
_secondScrollCtrl;
Map<String, FixedExtentScrollController> _scrollCtrlMap;
Map<String, List<int>> _valueRangeMap;
bool _isChangeTimeRange = false;
_TimePickerWidgetState(DateTime minTime, DateTime maxTime, DateTime initTime,
int minuteDivider) {
if (minTime == null) {
minTime = DateTime.parse(DATE_PICKER_MIN_DATETIME);
}
if (maxTime == null) {
maxTime = DateTime.parse(DATE_PICKER_MAX_DATETIME);
}
if (initTime == null) {
// init time is now
initTime = DateTime.now();
}
this._minTime = minTime;
this._maxTime = maxTime;
this._currHour = initTime.hour;
this._currMinute = initTime.minute;
this._currSecond = initTime.second;
this._minuteDivider = minuteDivider;
// limit the range of hour
this._hourRange = _calcHourRange();
this._currHour = min(max(_hourRange.first, _currHour), _hourRange.last);
// limit the range of minute
this._minuteRange = _calcMinuteRange();
this._currMinute =
min(max(_minuteRange.first, _currMinute), _minuteRange.last);
// limit the range of second
this._secondRange = _calcSecondRange();
this._currSecond =
min(max(_secondRange.first, _currSecond), _secondRange.last);
// create scroll controller
_hourScrollCtrl =
FixedExtentScrollController(initialItem: _currHour - _hourRange.first);
_minuteScrollCtrl = FixedExtentScrollController(
initialItem: (_currMinute - _minuteRange.first) ~/ _minuteDivider);
_secondScrollCtrl = FixedExtentScrollController(
initialItem: _currSecond - _secondRange.first);
_scrollCtrlMap = {
'H': _hourScrollCtrl,
'm': _minuteScrollCtrl,
's': _secondScrollCtrl
};
_valueRangeMap = {'H': _hourRange, 'm': _minuteRange, 's': _secondRange};
}
@override
Widget build(BuildContext context) {
return GestureDetector(
child: Material(
color: Colors.transparent, child: _renderPickerView(context)),
);
}
/// render time picker widgets
Widget _renderPickerView(BuildContext context) {
Widget pickerWidget = _renderDatePickerWidget();
// display the title widget
if (widget.pickerTheme.title != null || widget.pickerTheme.showTitle) {
Widget titleWidget = DatePickerTitleWidget(
pickerTheme: widget.pickerTheme,
locale: widget.locale,
onCancel: () => _onPressedCancel(),
onConfirm: () => _onPressedConfirm(),
);
return Column(children: <Widget>[titleWidget, pickerWidget]);
}
return pickerWidget;
}
/// pressed cancel widget
void _onPressedCancel() {
if (widget.onCancel != null) {
widget.onCancel();
}
Navigator.pop(context);
}
/// pressed confirm widget
void _onPressedConfirm() {
if (widget.onConfirm != null) {
DateTime now = DateTime.now();
DateTime dateTime = DateTime(
now.year, now.month, now.day, _currHour, _currMinute, _currSecond);
widget.onConfirm(dateTime, _calcSelectIndexList());
}
Navigator.pop(context);
}
/// notify selected time changed
void _onSelectedChange() {
if (widget.onChange != null) {
DateTime now = DateTime.now();
DateTime dateTime = DateTime(
now.year, now.month, now.day, _currHour, _currMinute, _currSecond);
widget.onChange(dateTime, _calcSelectIndexList());
}
}
/// find scroll controller by specified format
FixedExtentScrollController _findScrollCtrl(String format) {
FixedExtentScrollController scrollCtrl;
_scrollCtrlMap.forEach((key, value) {
if (format.contains(key)) {
scrollCtrl = value;
}
});
return scrollCtrl;
}
/// find item value range by specified format
List<int> _findPickerItemRange(String format) {
List<int> valueRange;
_valueRangeMap.forEach((key, value) {
if (format.contains(key)) {
valueRange = value;
}
});
return valueRange;
}
/// render the picker widget of year、month and day
Widget _renderDatePickerWidget() {
List<Widget> pickers = List<Widget>();
List<String> formatArr =
DateTimeFormatter.splitDateFormat(widget.dateFormat);
formatArr.forEach((format) {
List<int> valueRange = _findPickerItemRange(format);
Widget pickerColumn = _renderDatePickerColumnComponent(
scrollCtrl: _findScrollCtrl(format),
valueRange: valueRange,
format: format,
minuteDivider: widget.minuteDivider,
valueChanged: (value) {
if (format.contains('H')) {
_changeHourSelection(value);
} else if (format.contains('m')) {
_changeMinuteSelection(value);
} else if (format.contains('s')) {
_changeSecondSelection(value);
}
},
);
pickers.add(pickerColumn);
});
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, children: pickers);
}
Widget _renderDatePickerColumnComponent({
@required FixedExtentScrollController scrollCtrl,
@required List<int> valueRange,
@required String format,
@required ValueChanged<int> valueChanged,
int minuteDivider,
}) {
return Expanded(
flex: 1,
child: Container(
padding: EdgeInsets.all(8.0),
height: widget.pickerTheme.pickerHeight,
decoration: BoxDecoration(color: widget.pickerTheme.backgroundColor),
child: CupertinoPicker.builder(
backgroundColor: widget.pickerTheme.backgroundColor,
scrollController: scrollCtrl,
itemExtent: widget.pickerTheme.itemHeight,
onSelectedItemChanged: valueChanged,
childCount: format.contains('m')
? _calculateMinuteChildCount(valueRange, minuteDivider)
: valueRange.last - valueRange.first + 1,
itemBuilder: (context, index) {
int value = valueRange.first + index;
if (format.contains('m')) {
value = minuteDivider * index + valueRange.first;
}
return _renderDatePickerItemComponent(value, format);
},
),
),
);
}
_calculateMinuteChildCount(List<int> valueRange, int divider) {
if (divider == 0) {
print("Cant devide by 0");
return (valueRange.last - valueRange.first + 1);
}
return (valueRange.last - valueRange.first + 1) ~/ divider;
}
Widget _renderDatePickerItemComponent(int value, String format) {
return Container(
height: widget.pickerTheme.itemHeight,
alignment: Alignment.center,
child: Text(
DateTimeFormatter.formatDateTime(value, format, widget.locale),
style:
widget.pickerTheme.itemTextStyle ?? DATETIME_PICKER_ITEM_TEXT_STYLE,
),
);
}
/// change the selection of hour picker
void _changeHourSelection(int index) {
int value = _hourRange.first + index;
if (_currHour != value) {
_currHour = value;
_changeTimeRange();
_onSelectedChange();
}
}
/// change the selection of minute picker
void _changeMinuteSelection(int index) {
int value = index * _minuteDivider + _minuteRange.first;
if (_currMinute != value) {
_currMinute = value;
_changeTimeRange();
_onSelectedChange();
}
}
/// change the selection of second picker
void _changeSecondSelection(int index) {
int value = _secondRange.first + index;
if (_currSecond != value) {
_currSecond = value;
_onSelectedChange();
}
}
/// change range of minute and second
void _changeTimeRange() {
if (_isChangeTimeRange) {
return;
}
_isChangeTimeRange = true;
List<int> minuteRange = _calcMinuteRange();
bool minuteRangeChanged = _minuteRange.first != minuteRange.first ||
_minuteRange.last != minuteRange.last;
if (minuteRangeChanged) {
// selected hour changed
_currMinute = max(min(_currMinute, minuteRange.last), minuteRange.first);
}
List<int> secondRange = _calcSecondRange();
bool secondRangeChanged = _secondRange.first != secondRange.first ||
_secondRange.last != secondRange.last;
if (secondRangeChanged) {
// second range changed, need limit the value of selected second
_currSecond = max(min(_currSecond, secondRange.last), secondRange.first);
}
setState(() {
_minuteRange = minuteRange;
_secondRange = secondRange;
_valueRangeMap['m'] = minuteRange;
_valueRangeMap['s'] = secondRange;
});
if (minuteRangeChanged) {
// CupertinoPicker refresh data not working (https://github.com/flutter/flutter/issues/22999)
int currMinute = _currMinute;
_minuteScrollCtrl
.jumpToItem((minuteRange.last - minuteRange.first) ~/ _minuteDivider);
if (currMinute < minuteRange.last) {
_minuteScrollCtrl.jumpToItem(currMinute - minuteRange.first);
}
}
if (secondRangeChanged) {
// CupertinoPicker refresh data not working (https://github.com/flutter/flutter/issues/22999)
int currSecond = _currSecond;
_secondScrollCtrl.jumpToItem(secondRange.last - secondRange.first);
if (currSecond < secondRange.last) {
_secondScrollCtrl.jumpToItem(currSecond - secondRange.first);
}
}
_isChangeTimeRange = false;
}
/// calculate selected index list
List<int> _calcSelectIndexList() {
int hourIndex = _currHour - _hourRange.first;
int minuteIndex = _currMinute - _minuteRange.first;
int secondIndex = _currSecond - _secondRange.first;
return [hourIndex, minuteIndex, secondIndex];
}
/// calculate the range of hour
List<int> _calcHourRange() {
return [_minTime.hour, _maxTime.hour];
}
/// calculate the range of minute
List<int> _calcMinuteRange({currHour}) {
int minMinute = 0, maxMinute = 59;
int minHour = _minTime.hour;
int maxHour = _maxTime.hour;
if (currHour == null) {
currHour = _currHour;
}
if (minHour == currHour) {
// selected minimum hour, limit minute range
minMinute = _minTime.minute;
}
if (maxHour == currHour) {
// selected maximum hour, limit minute range
maxMinute = _maxTime.minute;
}
return [minMinute, maxMinute];
}
/// calculate the range of second
List<int> _calcSecondRange({currHour, currMinute}) {
int minSecond = 0, maxSecond = 59;
int minHour = _minTime.hour;
int maxHour = _maxTime.hour;
int minMinute = _minTime.minute;
int maxMinute = _maxTime.minute;
if (currHour == null) {
currHour = _currHour;
}
if (currMinute == null) {
currMinute = _currMinute;
}
if (minHour == currHour && minMinute == currMinute) {
// selected minimum hour and minute, limit second range
minSecond = _minTime.second;
}
if (maxHour == currHour && maxMinute == currMinute) {
// selected maximum hour and minute, limit second range
maxSecond = _maxTime.second;
}
return [minSecond, maxSecond];
}
}
#!/usr/bin/env bash
flutter format .
flutter packages pub publish --dry-run
flutter packages pub publish -v
\ No newline at end of file
name: flutter_cupertino_date_picker
description: Flutter cupertino date picker. Display DatePicker in iOS style. Support both Android and iOS platform.
version: 1.0.26+2
author: Dylan Wu <dylanwuzh@gmail.com>
homepage: https://github.com/wuzhendev/flutter-cupertino-date-picker
dependencies:
flutter:
sdk: flutter
flutter:
environment:
sdk: ">=1.19.0 <3.0.0"
flutter: ">=0.4.1 <2.0.0"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment