Init commit
This commit is contained in:
parent
46794ba817
commit
6157f9d618
7 changed files with 582 additions and 0 deletions
75
.gitignore
vendored
Normal file
75
.gitignore
vendored
Normal file
|
@ -0,0 +1,75 @@
|
|||
# Miscellaneous
|
||||
*.class
|
||||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/
|
||||
|
||||
# The .vscode folder contains launch configuration and tasks you configure in
|
||||
# VS Code which you may wish to be included in version control, so this line
|
||||
# is commented out by default.
|
||||
#.vscode/
|
||||
|
||||
# Flutter/Dart/Pub related
|
||||
**/doc/api/
|
||||
.dart_tool/
|
||||
.flutter-plugins
|
||||
.flutter-plugins-dependencies
|
||||
.packages
|
||||
.pub-cache/
|
||||
.pub/
|
||||
build/
|
||||
|
||||
# Android related
|
||||
**/android/**/gradle-wrapper.jar
|
||||
**/android/.gradle
|
||||
**/android/captures/
|
||||
**/android/gradlew
|
||||
**/android/gradlew.bat
|
||||
**/android/local.properties
|
||||
**/android/**/GeneratedPluginRegistrant.java
|
||||
|
||||
# iOS/XCode related
|
||||
**/ios/**/*.mode1v3
|
||||
**/ios/**/*.mode2v3
|
||||
**/ios/**/*.moved-aside
|
||||
**/ios/**/*.pbxuser
|
||||
**/ios/**/*.perspectivev3
|
||||
**/ios/**/*sync/
|
||||
**/ios/**/.sconsign.dblite
|
||||
**/ios/**/.tags*
|
||||
**/ios/**/.vagrant/
|
||||
**/ios/**/DerivedData/
|
||||
**/ios/**/Icon?
|
||||
**/ios/**/Pods/
|
||||
**/ios/**/.symlinks/
|
||||
**/ios/**/profile
|
||||
**/ios/**/xcuserdata
|
||||
**/ios/.generated/
|
||||
**/ios/Flutter/App.framework
|
||||
**/ios/Flutter/Flutter.framework
|
||||
**/ios/Flutter/Flutter.podspec
|
||||
**/ios/Flutter/Generated.xcconfig
|
||||
**/ios/Flutter/app.flx
|
||||
**/ios/Flutter/app.zip
|
||||
**/ios/Flutter/flutter_assets/
|
||||
**/ios/Flutter/flutter_export_environment.sh
|
||||
**/ios/ServiceDefinitions.json
|
||||
**/ios/Runner/GeneratedPluginRegistrant.*
|
||||
|
||||
# Exceptions to above rules.
|
||||
!**/ios/**/default.mode1v3
|
||||
!**/ios/**/default.mode2v3
|
||||
!**/ios/**/default.pbxuser
|
||||
!**/ios/**/default.perspectivev3
|
||||
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
|
10
.metadata
Normal file
10
.metadata
Normal file
|
@ -0,0 +1,10 @@
|
|||
# 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: 09126abb222d0f25b03318a1ab4a99d27d9aaa8d
|
||||
channel: unknown
|
||||
|
||||
project_type: package
|
3
CHANGELOG.md
Normal file
3
CHANGELOG.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
## [0.0.1] - TODO: Add release date.
|
||||
|
||||
* TODO: Describe initial release.
|
1
LICENSE
Normal file
1
LICENSE
Normal file
|
@ -0,0 +1 @@
|
|||
TODO: Add your license here.
|
245
lib/date_field.dart
Normal file
245
lib/date_field.dart
Normal file
|
@ -0,0 +1,245 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
class DateFormField extends StatelessWidget {
|
||||
|
||||
/// An optional method to call with the final value when the form is saved via
|
||||
/// [FormState.save].
|
||||
final FormFieldSetter<DateTime> onSaved;
|
||||
|
||||
/// An optional method that validates an input. Returns an error string to
|
||||
/// display if the input is invalid, or null otherwise.
|
||||
final FormFieldValidator<DateTime> validator;
|
||||
|
||||
|
||||
/// An optional value to initialize the form field to, or null otherwise.
|
||||
final DateTime initialValue;
|
||||
|
||||
/// If true, this form field will validate and update its error text
|
||||
/// immediately after every change. Otherwise, you must call
|
||||
/// [FormFieldState.validate] to validate. If part of a [Form] that
|
||||
/// auto-validates, this value will be ignored.
|
||||
final bool autovalidate;
|
||||
|
||||
/// Whether the form is able to receive user input.
|
||||
///
|
||||
/// Defaults to true. If [autovalidate] is true, the field will be validated.
|
||||
/// Likewise, if this field is false, the widget will not be validated
|
||||
/// regardless of [autovalidate].
|
||||
final bool enabled;
|
||||
|
||||
/// (optional) The first date that the user can select (default is 1900)
|
||||
final DateTime firstDate;
|
||||
|
||||
/// (optional) The last date that the user can select (default is 2100)
|
||||
final DateTime lastDate;
|
||||
|
||||
/// (optional) The label to display for the field (default is 'Select date')
|
||||
final String label;
|
||||
|
||||
/// (optional) Custom [InputDecoration] for the [InputDecorator] widget
|
||||
final InputDecoration decoration;
|
||||
|
||||
/// (optional) How to display the [DateTime] for the user (default is [DateFormat.yMMMD])
|
||||
final DateFormat dateFormat;
|
||||
|
||||
/// (optional) Let you choose the [DatePickerMode] for the date picker! (default is [DatePickerMode.day]
|
||||
final DatePickerMode initialDatePickerMode;
|
||||
|
||||
const DateFormField(
|
||||
{Key key, this.onSaved, this.validator, this.initialValue, this.autovalidate=false, this.enabled=true, this.firstDate, this.lastDate, this.label='Select date', this.dateFormat, this.decoration, this.initialDatePickerMode})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FormField<DateTime>(
|
||||
onSaved: onSaved,
|
||||
autovalidate: autovalidate,
|
||||
validator: validator,
|
||||
enabled: enabled,
|
||||
initialValue: initialValue,
|
||||
builder: (FormFieldState state) {
|
||||
return DateField(
|
||||
label: label,
|
||||
firstDate: firstDate,
|
||||
lastDate: lastDate,
|
||||
decoration: decoration,
|
||||
initialDatePickerMode: initialDatePickerMode,
|
||||
dateFormat: dateFormat,
|
||||
errorText: state.errorText,
|
||||
onDateSelected: (DateTime value) {
|
||||
state.didChange(value);
|
||||
},
|
||||
selectedDate: state.value,
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// [DateField]
|
||||
///
|
||||
/// Shows an [_InputDropdown] that'll trigger [DateField._selectDate] whenever the user
|
||||
/// clicks on it !
|
||||
class DateField extends StatelessWidget {
|
||||
/// Default constructor
|
||||
DateField({
|
||||
@required this.onDateSelected,
|
||||
@required this.selectedDate,
|
||||
this.firstDate,
|
||||
this.lastDate,
|
||||
this.initialDatePickerMode = DatePickerMode.day,
|
||||
this.decoration,
|
||||
this.label = 'Select date',
|
||||
this.errorText,
|
||||
this.dateFormat,
|
||||
});
|
||||
|
||||
/// Callback for whenever the user selects a [DateTime]
|
||||
final ValueChanged<DateTime> onDateSelected;
|
||||
|
||||
/// The current selected date to display inside the field
|
||||
final DateTime selectedDate;
|
||||
|
||||
/// (optional) The first date that the user can select (default is 1900)
|
||||
final DateTime firstDate;
|
||||
|
||||
/// (optional) The last date that the user can select (default is 2100)
|
||||
final DateTime lastDate;
|
||||
|
||||
/// Let you choose the [DatePickerMode] for the date picker! (default is [DatePickerMode.day]
|
||||
final DatePickerMode initialDatePickerMode;
|
||||
|
||||
/// The label to display for the field (default is 'Select date')
|
||||
final String label;
|
||||
|
||||
/// (optional) The error text that should be displayed under the field
|
||||
final String errorText;
|
||||
|
||||
/// (optional) Custom [InputDecoration] for the [InputDecorator] widget
|
||||
final InputDecoration decoration;
|
||||
|
||||
/// (optional) How to display the [DateTime] for the user (default is [DateFormat.yMMMD])
|
||||
final DateFormat dateFormat;
|
||||
|
||||
/// Shows a dialog asking the user to pick a date !
|
||||
Future<void> _selectDate(BuildContext context) async {
|
||||
if (!Platform.isIOS) {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
builder: (BuildContext builder) {
|
||||
return Container(
|
||||
height: MediaQuery.of(context).size.height / 4,
|
||||
child: CupertinoDatePicker(
|
||||
mode: CupertinoDatePickerMode.date,
|
||||
onDateTimeChanged:(DateTime dateTime) => onDateSelected(dateTime),
|
||||
initialDateTime: selectedDate ?? lastDate ?? DateTime.now(),
|
||||
minimumDate: firstDate,
|
||||
maximumDate: lastDate,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
else {
|
||||
DateTime _selectedDate = await showDatePicker(
|
||||
context: context,
|
||||
initialDatePickerMode: initialDatePickerMode,
|
||||
initialDate: selectedDate ?? lastDate ?? DateTime.now(),
|
||||
firstDate: firstDate ?? DateTime(1900),
|
||||
lastDate: lastDate ?? DateTime(2100));
|
||||
|
||||
|
||||
if (_selectedDate != null) {
|
||||
onDateSelected(_selectedDate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
String text;
|
||||
|
||||
if (selectedDate != null)
|
||||
text = (dateFormat ?? DateFormat.yMMMd()).format(selectedDate);
|
||||
|
||||
return _InputDropdown(
|
||||
text: text ?? label,
|
||||
label: text == null ? null : label,
|
||||
errorText: errorText,
|
||||
decoration: decoration,
|
||||
onPressed: () {
|
||||
_selectDate(context);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// [_InputDropdown]
|
||||
///
|
||||
/// Shows a field with a dropdown arrow !
|
||||
/// It does not show any popup menu, it'll just trigger onPressed whenever the
|
||||
/// user does click on it !
|
||||
class _InputDropdown extends StatelessWidget {
|
||||
const _InputDropdown(
|
||||
{Key key, this.label, this.text, this.decoration, this.textStyle, this.onPressed, this.errorText})
|
||||
: super(key: key);
|
||||
|
||||
/// The label to display for the field (default is 'Select date')
|
||||
final String label;
|
||||
|
||||
/// The text that should be displayed inside the field
|
||||
final String text;
|
||||
|
||||
/// (optional) The error text that should be displayed under the field
|
||||
final String errorText;
|
||||
|
||||
/// (optional) Custom [InputDecoration] for the [InputDecorator] widget
|
||||
final InputDecoration decoration;
|
||||
|
||||
/// TextStyle for the field
|
||||
final TextStyle textStyle;
|
||||
|
||||
/// Callbacks triggered whenever the user presses on the field!
|
||||
final VoidCallback onPressed;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
BorderRadius inkwellBorderRadius;
|
||||
|
||||
if (decoration?.border?.runtimeType == OutlineInputBorder) {
|
||||
inkwellBorderRadius = BorderRadius.circular(8);
|
||||
}
|
||||
|
||||
return Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
borderRadius: inkwellBorderRadius,
|
||||
onTap: onPressed,
|
||||
child: InputDecorator(
|
||||
decoration: decoration ?? InputDecoration(
|
||||
labelText: label,
|
||||
errorText: errorText,
|
||||
border: UnderlineInputBorder(borderSide: BorderSide()),
|
||||
contentPadding: EdgeInsets.only(bottom: 2.0)
|
||||
),
|
||||
baseStyle: textStyle,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
Text(text, style: textStyle),
|
||||
Icon(Icons.arrow_drop_down),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
195
pubspec.lock
Normal file
195
pubspec.lock
Normal file
|
@ -0,0 +1,195 @@
|
|||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
archive:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: archive
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.11"
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: args
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.5.2"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.4.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: boolean_selector
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.5"
|
||||
charcode:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: charcode
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.14.11"
|
||||
convert:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: convert
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: crypto
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.3"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
image:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
intl:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: intl
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.16.1"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.12.6"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.8"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.6.4"
|
||||
pedantic:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pedantic
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.0+1"
|
||||
petitparser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: petitparser
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.4.0"
|
||||
quiver:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: quiver
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.5"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.99"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_span
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.5.5"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.9.3"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: string_scanner
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.5"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: term_glyph
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.11"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: typed_data
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.6"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_math
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.8"
|
||||
xml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xml
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "3.5.0"
|
||||
sdks:
|
||||
dart: ">=2.5.0 <3.0.0"
|
53
pubspec.yaml
Normal file
53
pubspec.yaml
Normal file
|
@ -0,0 +1,53 @@
|
|||
name: date_field
|
||||
description: Contains DateField and DateFormField
|
||||
version: 0.0.1
|
||||
|
||||
|
||||
environment:
|
||||
sdk: ">=2.1.0 <3.0.0"
|
||||
|
||||
dependencies:
|
||||
intl: ^0.16.1
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://dart.dev/tools/pub/pubspec
|
||||
|
||||
# The following section is specific to Flutter.
|
||||
flutter:
|
||||
|
||||
# To add assets to your package, add an assets section, like this:
|
||||
# assets:
|
||||
# - images/a_dot_burr.jpeg
|
||||
# - images/a_dot_ham.jpeg
|
||||
#
|
||||
# For details regarding assets in packages, see
|
||||
# https://flutter.dev/assets-and-images/#from-packages
|
||||
#
|
||||
# An image asset can refer to one or more resolution-specific "variants", see
|
||||
# https://flutter.dev/assets-and-images/#resolution-aware.
|
||||
|
||||
# To add custom fonts to your package, 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 in packages, see
|
||||
# https://flutter.dev/custom-fonts/#from-packages
|
Loading…
Reference in a new issue