|
@ -4,7 +4,7 @@
|
|||
# This file should be version controlled.
|
||||
|
||||
version:
|
||||
revision: f1875d570e39de09040c8f79aa13cc56baab8db1
|
||||
revision: ffccd96b62ee8cec7740dab303538c5fc26ac543
|
||||
channel: stable
|
||||
|
||||
project_type: app
|
||||
|
@ -13,26 +13,26 @@ project_type: app
|
|||
migration:
|
||||
platforms:
|
||||
- platform: root
|
||||
create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
|
||||
base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
|
||||
create_revision: ffccd96b62ee8cec7740dab303538c5fc26ac543
|
||||
base_revision: ffccd96b62ee8cec7740dab303538c5fc26ac543
|
||||
- platform: android
|
||||
create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
|
||||
base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
|
||||
create_revision: ffccd96b62ee8cec7740dab303538c5fc26ac543
|
||||
base_revision: ffccd96b62ee8cec7740dab303538c5fc26ac543
|
||||
- platform: ios
|
||||
create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
|
||||
base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
|
||||
create_revision: ffccd96b62ee8cec7740dab303538c5fc26ac543
|
||||
base_revision: ffccd96b62ee8cec7740dab303538c5fc26ac543
|
||||
- platform: linux
|
||||
create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
|
||||
base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
|
||||
create_revision: ffccd96b62ee8cec7740dab303538c5fc26ac543
|
||||
base_revision: ffccd96b62ee8cec7740dab303538c5fc26ac543
|
||||
- platform: macos
|
||||
create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
|
||||
base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
|
||||
create_revision: ffccd96b62ee8cec7740dab303538c5fc26ac543
|
||||
base_revision: ffccd96b62ee8cec7740dab303538c5fc26ac543
|
||||
- platform: web
|
||||
create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
|
||||
base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
|
||||
create_revision: ffccd96b62ee8cec7740dab303538c5fc26ac543
|
||||
base_revision: ffccd96b62ee8cec7740dab303538c5fc26ac543
|
||||
- platform: windows
|
||||
create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
|
||||
base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1
|
||||
create_revision: ffccd96b62ee8cec7740dab303538c5fc26ac543
|
||||
base_revision: ffccd96b62ee8cec7740dab303538c5fc26ac543
|
||||
|
||||
# User provided section
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ android {
|
|||
|
||||
defaultConfig {
|
||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||
applicationId "com.example.example"
|
||||
applicationId "com.iconica.example"
|
||||
// You can update the following values to match your application needs.
|
||||
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
|
||||
minSdkVersion flutter.minSdkVersion
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.example.example">
|
||||
package="com.iconica.example">
|
||||
<!-- The INTERNET permission is required for development. Specifically,
|
||||
the Flutter tool needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.example.example">
|
||||
package="com.iconica.example">
|
||||
<application
|
||||
android:label="example"
|
||||
android:name="${applicationName}"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package com.example.example
|
||||
package com.iconica.example
|
||||
|
||||
import io.flutter.embedding.android.FlutterActivity
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.example.example">
|
||||
package="com.iconica.example">
|
||||
<!-- The INTERNET permission is required for development. Specifically,
|
||||
the Flutter tool needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#Fri Jun 23 08:50:38 CEST 2017
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
|
|
@ -21,6 +21,6 @@
|
|||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>9.0</string>
|
||||
<string>11.0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
@ -272,7 +272,7 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
|
@ -295,7 +295,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.example;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.iconica.example;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
|
@ -350,7 +350,7 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
|
@ -399,7 +399,7 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
|
@ -424,7 +424,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.example;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.iconica.example;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
|
@ -447,7 +447,7 @@
|
|||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.example;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.iconica.example;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
|
|
|
@ -45,5 +45,7 @@
|
|||
<false/>
|
||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||
<true/>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
@ -6,7 +6,7 @@ void main() {
|
|||
}
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
const MyApp({Key? key}) : super(key: key);
|
||||
const MyApp({super.key});
|
||||
|
||||
// This widget is the root of your application.
|
||||
@override
|
||||
|
@ -14,90 +14,38 @@ class MyApp extends StatelessWidget {
|
|||
return MaterialApp(
|
||||
title: 'Flutter Demo',
|
||||
theme: ThemeData(
|
||||
// This is the theme of your application.
|
||||
//
|
||||
// Try running your application with "flutter run". You'll see the
|
||||
// application has a blue toolbar. Then, without quitting the app, try
|
||||
// changing the primarySwatch below to Colors.green and then invoke
|
||||
// "hot reload" (press "r" in the console where you ran "flutter run",
|
||||
// or simply save your changes to "hot reload" in a Flutter IDE).
|
||||
// Notice that the counter didn't reset back to zero; the application
|
||||
// is not restarted.
|
||||
primarySwatch: Colors.blue,
|
||||
),
|
||||
home: MyHomePage(),
|
||||
home: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Roster'),
|
||||
),
|
||||
body: const DatePickerDemo(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class MyHomePage extends StatelessWidget {
|
||||
class DatePickerDemo extends StatelessWidget {
|
||||
const DatePickerDemo({Key? key}) : super(key: key);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text('Rooster')),
|
||||
body: DateTimePicker(
|
||||
// header: Container(
|
||||
// height: 100,
|
||||
// width: MediaQuery.of(context).size.width,
|
||||
// padding: const EdgeInsets.only(bottom: 10),
|
||||
// child: Row(
|
||||
// crossAxisAlignment: CrossAxisAlignment.end,
|
||||
// mainAxisAlignment: MainAxisAlignment.center,
|
||||
// children: [
|
||||
// const SizedBox(
|
||||
// width: 160,
|
||||
// height: 34,
|
||||
// child: Center(
|
||||
// child: Text(
|
||||
// 'Persoonlijk',
|
||||
// style: TextStyle(
|
||||
// fontSize: 16,
|
||||
// fontWeight: FontWeight.w900,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// const SizedBox(
|
||||
// width: 4,
|
||||
// ),
|
||||
// Container(
|
||||
// width: 160,
|
||||
// height: 34,
|
||||
// decoration: BoxDecoration(
|
||||
// color: const Color(0xFF00273D),
|
||||
// borderRadius: const BorderRadius.all(
|
||||
// Radius.circular(10),
|
||||
// ),
|
||||
// boxShadow: [
|
||||
// BoxShadow(
|
||||
// color: const Color(0xFF000000).withOpacity(0.50),
|
||||
// offset: const Offset(0, 6),
|
||||
// blurRadius: 9,
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// child: const Center(
|
||||
// child: Text(
|
||||
// 'Teamplanning',
|
||||
// style: TextStyle(
|
||||
// color: Colors.white,
|
||||
// fontSize: 16,
|
||||
// fontWeight: FontWeight.w900,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
markedDates: [DateTime(2022, 8, 26)],
|
||||
child: Container(
|
||||
margin: const EdgeInsets.only(
|
||||
top: 195,
|
||||
return DateTimePicker(
|
||||
dateTimePickerTheme: const DateTimePickerTheme(
|
||||
markedIndicatorColor: Colors.red,
|
||||
selectedTheme: DateBoxSelectedTheme(
|
||||
Color(0x4BF44336),
|
||||
TextStyle(
|
||||
color: Colors.red,
|
||||
),
|
||||
),
|
||||
child: Container(),
|
||||
),
|
||||
),
|
||||
highlightTheme: DateBoxHighlightTheme(
|
||||
Colors.red,
|
||||
TextStyle(
|
||||
color: Colors.white,
|
||||
),
|
||||
)),
|
||||
markedDates: [DateTime(2022, 9, 6)],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ project(runner LANGUAGES CXX)
|
|||
set(BINARY_NAME "example")
|
||||
# The unique GTK application identifier for this application. See:
|
||||
# https://wiki.gnome.org/HowDoI/ChooseApplicationID
|
||||
set(APPLICATION_ID "com.example.example")
|
||||
set(APPLICATION_ID "com.iconica.example")
|
||||
|
||||
# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
|
||||
# versions of CMake.
|
||||
|
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 101 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 520 B |
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 2.2 KiB |
|
@ -8,7 +8,7 @@
|
|||
PRODUCT_NAME = example
|
||||
|
||||
// The application's bundle identifier
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.example.example
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.iconica.example
|
||||
|
||||
// The copyright displayed in application information
|
||||
PRODUCT_COPYRIGHT = Copyright © 2022 com.example. All rights reserved.
|
||||
PRODUCT_COPYRIGHT = Copyright © 2022 com.iconica. All rights reserved.
|
||||
|
|
|
@ -7,7 +7,7 @@ packages:
|
|||
name: async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.8.2"
|
||||
version: "2.9.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -21,21 +21,14 @@ packages:
|
|||
name: characters
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
charcode:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: charcode
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
version: "1.2.1"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: clock
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
version: "1.1.1"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -56,7 +49,7 @@ packages:
|
|||
name: fake_async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
version: "1.3.1"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
|
@ -101,28 +94,28 @@ packages:
|
|||
name: matcher
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.12.11"
|
||||
version: "0.12.12"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: material_color_utilities
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.4"
|
||||
version: "0.1.5"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.7.0"
|
||||
version: "1.8.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.1"
|
||||
version: "1.8.2"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
|
@ -134,7 +127,7 @@ packages:
|
|||
name: source_span
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.2"
|
||||
version: "1.9.0"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -155,21 +148,21 @@ packages:
|
|||
name: string_scanner
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
version: "1.1.1"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: term_glyph
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
version: "1.2.1"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.4.9"
|
||||
version: "0.4.12"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -1,91 +1,24 @@
|
|||
name: example
|
||||
description: A new Flutter project.
|
||||
name: datetime_picker_example
|
||||
description: DateTimePicker Widget
|
||||
|
||||
# The following line prevents the package from being accidentally published to
|
||||
# pub.dev using `flutter pub publish`. This is preferred for private packages.
|
||||
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
publish_to: 'none'
|
||||
|
||||
# The following defines the version and build number for your application.
|
||||
# A version number is three numbers separated by dots, like 1.2.43
|
||||
# followed by an optional build number separated by a +.
|
||||
# Both the version and the builder number may be overridden in flutter
|
||||
# build by specifying --build-name and --build-number, respectively.
|
||||
# In Android, build-name is used as versionName while build-number used as versionCode.
|
||||
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
|
||||
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||
# Read more about iOS versioning at
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
version: 1.0.0+1
|
||||
|
||||
environment:
|
||||
sdk: ">=2.17.6 <3.0.0"
|
||||
|
||||
# Dependencies specify other packages that your package needs in order to work.
|
||||
# To automatically upgrade your package dependencies to the latest versions
|
||||
# consider running `flutter pub upgrade --major-versions`. Alternatively,
|
||||
# dependencies can be manually updated by changing the version numbers below to
|
||||
# the latest version available on pub.dev. To see which dependencies have newer
|
||||
# versions available, run `flutter pub outdated`.
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
cupertino_icons: ^1.0.2
|
||||
flutter_date_time_picker:
|
||||
path: ../
|
||||
|
||||
|
||||
# The following adds the Cupertino Icons font to your application.
|
||||
# Use with the CupertinoIcons class for iOS style icons.
|
||||
cupertino_icons: ^1.0.2
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
||||
# The "flutter_lints" package below contains a set of recommended lints to
|
||||
# encourage good coding practices. The lint set provided by the package is
|
||||
# activated in the `analysis_options.yaml` file located at the root of your
|
||||
# package. See that file for information about deactivating specific lint
|
||||
# rules and activating additional ones.
|
||||
flutter_lints: ^2.0.0
|
||||
|
||||
# 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 packages.
|
||||
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.dev/assets-and-images/#resolution-aware
|
||||
|
||||
# For details regarding adding assets from package dependencies, see
|
||||
# https://flutter.dev/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.dev/custom-fonts/#from-packages
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
// This is a basic Flutter widget test.
|
||||
//
|
||||
// To perform an interaction with a widget in your test, use the WidgetTester
|
||||
// utility in the flutter_test package. For example, you can send tap and scroll
|
||||
// gestures. You can also use WidgetTester to find child widgets in the widget
|
||||
// tree, read text, and verify that the values of widget properties are correct.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'package:example/main.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
||||
// Build our app and trigger a frame.
|
||||
await tester.pumpWidget(const MyApp());
|
||||
|
||||
// Verify that our counter starts at 0.
|
||||
expect(find.text('0'), findsOneWidget);
|
||||
expect(find.text('1'), findsNothing);
|
||||
|
||||
// Tap the '+' icon and trigger a frame.
|
||||
await tester.tap(find.byIcon(Icons.add));
|
||||
await tester.pump();
|
||||
|
||||
// Verify that our counter has incremented.
|
||||
expect(find.text('0'), findsNothing);
|
||||
expect(find.text('1'), findsOneWidget);
|
||||
});
|
||||
}
|
|
@ -20,6 +20,13 @@ add_executable(${BINARY_NAME} WIN32
|
|||
# that need different build settings.
|
||||
apply_standard_settings(${BINARY_NAME})
|
||||
|
||||
# Add preprocessor definitions for the build version.
|
||||
target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"")
|
||||
target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}")
|
||||
target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}")
|
||||
target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}")
|
||||
target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}")
|
||||
|
||||
# Disable Windows macros that collide with C++ standard library functions.
|
||||
target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX")
|
||||
|
||||
|
|
|
@ -60,14 +60,14 @@ IDI_APP_ICON ICON "resources\\app_icon.ico"
|
|||
// Version
|
||||
//
|
||||
|
||||
#ifdef FLUTTER_BUILD_NUMBER
|
||||
#define VERSION_AS_NUMBER FLUTTER_BUILD_NUMBER
|
||||
#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD)
|
||||
#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD
|
||||
#else
|
||||
#define VERSION_AS_NUMBER 1,0,0
|
||||
#define VERSION_AS_NUMBER 1,0,0,0
|
||||
#endif
|
||||
|
||||
#ifdef FLUTTER_BUILD_NAME
|
||||
#define VERSION_AS_STRING #FLUTTER_BUILD_NAME
|
||||
#if defined(FLUTTER_VERSION)
|
||||
#define VERSION_AS_STRING FLUTTER_VERSION
|
||||
#else
|
||||
#define VERSION_AS_STRING "1.0.0"
|
||||
#endif
|
||||
|
@ -89,11 +89,11 @@ BEGIN
|
|||
BEGIN
|
||||
BLOCK "040904e4"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "com.example" "\0"
|
||||
VALUE "CompanyName", "com.iconica" "\0"
|
||||
VALUE "FileDescription", "example" "\0"
|
||||
VALUE "FileVersion", VERSION_AS_STRING "\0"
|
||||
VALUE "InternalName", "example" "\0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2022 com.example. All rights reserved." "\0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2022 com.iconica. All rights reserved." "\0"
|
||||
VALUE "OriginalFilename", "example.exe" "\0"
|
||||
VALUE "ProductName", "example" "\0"
|
||||
VALUE "ProductVersion", VERSION_AS_STRING "\0"
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
</application>
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
<application>
|
||||
<!-- Windows 10 -->
|
||||
<!-- Windows 10 and Windows 11 -->
|
||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
|
||||
<!-- Windows 8.1 -->
|
||||
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
library flutter_date_time_picker;
|
||||
|
||||
export 'src/date_time_picker.dart';
|
||||
export 'src/date_time_picker.dart' show DateTimePicker;
|
||||
export 'src/enums/date_box_shape.dart';
|
||||
export 'src/models/date_box_base_theme.dart';
|
||||
export 'src/models/date_box_disabled_theme.dart';
|
||||
export 'src/models/date_box_highlight_theme.dart';
|
||||
export 'src/models/date_box_selected_theme.dart';
|
||||
export 'src/models/date_time_picker_theme.dart';
|
|
@ -1,130 +1,168 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_date_time_picker/src/models/date_time_picker_theme.dart';
|
||||
import 'package:flutter_date_time_picker/src/utils/date_time_picker_controller.dart';
|
||||
import 'package:flutter_date_time_picker/src/widgets/month_date_time_picker.dart/month_date_time_picker_sheet.dart';
|
||||
import 'package:flutter_date_time_picker/src/widgets/week_date_time_picker/week_date_time_picker_sheet.dart';
|
||||
import 'package:intl/date_symbol_data_local.dart';
|
||||
|
||||
/// A widget that displays a date picker from a sheet form the top of the screen.
|
||||
/// This sheet displays initialy displays a week of days but can be dragged down to show full months.
|
||||
/// Both views can be dragged sideways to show the next or previous wweek/month.
|
||||
///
|
||||
/// The child will be the [Widget] that is displayed underneath the date picker in the stack.
|
||||
///
|
||||
/// The header [Widget] will be displayed above the date picker in the modal sheet in a column.
|
||||
///
|
||||
/// onTapDay is a callback that provides the taped date as a [DateTime] object.
|
||||
///
|
||||
/// highlightToday is a [bool] that determines which day shall we highlighted.
|
||||
/// true will always highlight the current date. This is standard.
|
||||
/// false will highlight the currently selected date by either the initial date or the one chosen by the user.
|
||||
/// [highlighColor] is used as background for the highlighted day.
|
||||
/// [toggleableActiveColor] is used for the text color when highlighted.
|
||||
/// [disabledColor] is used for the text color when not highlighted.
|
||||
///
|
||||
/// markedDates contain the dates [DateTime] that will be marked in the picker by a small dot.
|
||||
/// [indicatorColor] is used for the color of the dot.
|
||||
///
|
||||
/// Example:
|
||||
/// ```dart
|
||||
/// ShellDatePicker(
|
||||
/// initialDate: selectedDate,
|
||||
/// highlightToday: false,
|
||||
/// onTapDay: (date) {
|
||||
/// setState(() {
|
||||
/// selectedDate = date;
|
||||
/// });
|
||||
/// },
|
||||
/// markedDates: [
|
||||
/// DateTime(2022, 7, 22),
|
||||
/// ],
|
||||
/// header: Container(
|
||||
/// height: 100,
|
||||
/// width: MediaQuery.of(context).size.width,
|
||||
/// padding: const EdgeInsets.only(bottom: 10),
|
||||
/// child: Row(
|
||||
/// crossAxisAlignment: CrossAxisAlignment.end,
|
||||
/// mainAxisAlignment: MainAxisAlignment.center,
|
||||
/// children: [
|
||||
/// const SizedBox(
|
||||
/// width: 160,
|
||||
/// height: 34,
|
||||
/// child: Center(
|
||||
/// child: Text(
|
||||
/// 'Persoonlijk',
|
||||
/// style: TextStyle(
|
||||
/// fontSize: 16,
|
||||
/// fontWeight: FontWeight.w900,
|
||||
/// ),
|
||||
/// ),
|
||||
/// ),
|
||||
/// ),
|
||||
/// const SizedBox(
|
||||
/// width: 4,
|
||||
/// ),
|
||||
/// Container(
|
||||
/// width: 160,
|
||||
/// height: 34,
|
||||
/// decoration: BoxDecoration(
|
||||
/// color: const Color(0xFF00273D),
|
||||
/// borderRadius: const BorderRadius.all(
|
||||
/// Radius.circular(10),
|
||||
/// ),
|
||||
/// boxShadow: [
|
||||
/// BoxShadow(
|
||||
/// color: const Color(0xFF000000).withOpacity(0.50),
|
||||
/// offset: const Offset(0, 6),
|
||||
/// blurRadius: 9,
|
||||
/// ),
|
||||
/// ],
|
||||
/// ),
|
||||
/// child: const Center(
|
||||
/// child: Text(
|
||||
/// 'Teamplanning',
|
||||
/// style: TextStyle(
|
||||
/// color: Colors.white,
|
||||
/// fontSize: 16,
|
||||
/// fontWeight: FontWeight.w900,
|
||||
/// ),
|
||||
/// ),
|
||||
/// ),
|
||||
/// ),
|
||||
/// ],
|
||||
/// ),
|
||||
/// ),
|
||||
/// child: Container(
|
||||
/// margin: const EdgeInsets.only(
|
||||
/// top: 195,
|
||||
/// ),
|
||||
/// child: ShellRoster(
|
||||
/// startHour: 0,
|
||||
/// endHour: 24,
|
||||
/// blocks: [
|
||||
/// for (Map<String, TimeOfDay> block in blocks) ...[
|
||||
/// getBlock(block),
|
||||
/// ],
|
||||
/// ],
|
||||
/// ),
|
||||
/// ),
|
||||
/// ),
|
||||
///```
|
||||
class DateTimePicker extends StatefulWidget {
|
||||
const DateTimePicker({
|
||||
required this.child,
|
||||
/// A widget that displays a date picker from a sheet form the top of the screen.
|
||||
/// This sheet displays initially displays a week but can be dragged down to show a full month.
|
||||
/// Both views can be dragged sideways to show the next or previous week/month.
|
||||
///
|
||||
/// Example:
|
||||
/// ```dart
|
||||
/// DatePicker(
|
||||
/// dateTimePickerTheme: const DateTimePickerTheme()
|
||||
/// initialDate: selectedDate,
|
||||
/// highlightToday: true,
|
||||
/// onTapDay: (date) {
|
||||
/// setState(() {
|
||||
/// selectedDate = date;
|
||||
/// });
|
||||
/// },
|
||||
/// markedDates: [
|
||||
/// DateTime(2022, 3, 14),
|
||||
/// ],
|
||||
/// wrongTimeDialog:
|
||||
/// AlertDialog(
|
||||
/// title: const Text('Invalid Time'),
|
||||
/// content: SingleChildScrollView(
|
||||
/// child: ListBody(
|
||||
/// children: const <Widget>[
|
||||
/// Text(
|
||||
/// 'The time you try to choose is diabled, try to pick another time.'),
|
||||
/// ],
|
||||
/// ),
|
||||
/// ),
|
||||
/// actions: <Widget>[
|
||||
/// TextButton(
|
||||
/// child: const Text('OK'),
|
||||
/// onPressed: () {
|
||||
/// Navigator.pop(context);
|
||||
/// },
|
||||
/// ),
|
||||
/// ],
|
||||
/// ),
|
||||
/// header: Container(
|
||||
/// height: 100,
|
||||
/// width: MediaQuery.of(context).size.width,
|
||||
/// padding: const EdgeInsets.only(bottom: 10),
|
||||
/// child: Row(
|
||||
/// crossAxisAlignment: CrossAxisAlignment.end,
|
||||
/// mainAxisAlignment: MainAxisAlignment.center,
|
||||
/// children: [
|
||||
/// const SizedBox(
|
||||
/// width: 160,
|
||||
/// height: 34,
|
||||
/// child: Center(
|
||||
/// child: Text(
|
||||
/// 'Personal calendar',
|
||||
/// style: TextStyle(
|
||||
/// fontSize: 16,
|
||||
/// fontWeight: FontWeight.w900,
|
||||
/// ),
|
||||
/// ),
|
||||
/// ),
|
||||
/// ),
|
||||
/// const SizedBox(
|
||||
/// width: 4,
|
||||
/// ),
|
||||
/// Container(
|
||||
/// width: 160,
|
||||
/// height: 34,
|
||||
/// decoration: BoxDecoration(
|
||||
/// color: const Color(0xFF00273D),
|
||||
/// borderRadius: const BorderRadius.all(
|
||||
/// Radius.circular(10),
|
||||
/// ),
|
||||
/// boxShadow: [
|
||||
/// BoxShadow(
|
||||
/// color: const Color(0xFF000000).withOpacity(0.50),
|
||||
/// offset: const Offset(0, 6),
|
||||
/// blurRadius: 9,
|
||||
/// ),
|
||||
/// ],
|
||||
/// ),
|
||||
/// child: const Center(
|
||||
/// child: Text(
|
||||
/// 'Work calendar',
|
||||
/// style: TextStyle(
|
||||
/// color: Colors.white,
|
||||
/// fontSize: 16,
|
||||
/// fontWeight: FontWeight.w900,
|
||||
/// ),
|
||||
/// ),
|
||||
/// ),
|
||||
/// ),
|
||||
/// ],
|
||||
/// ),
|
||||
/// ),
|
||||
/// child: Container(
|
||||
/// margin: const EdgeInsets.only(
|
||||
/// top: 195,
|
||||
/// ),
|
||||
/// child: HolidayRoster(),
|
||||
/// ),
|
||||
/// ),
|
||||
///```
|
||||
DateTimePicker({
|
||||
this.dateTimePickerTheme = const DateTimePickerTheme(),
|
||||
this.header,
|
||||
this.onTapDay,
|
||||
this.highlightToday = true,
|
||||
this.wrongTimeDialog,
|
||||
bool? use24HourFormat,
|
||||
this.pickTime = false,
|
||||
this.initialDate,
|
||||
this.markedDates,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
this.disabledDates,
|
||||
this.disabledTimes,
|
||||
this.child,
|
||||
super.key,
|
||||
}) {
|
||||
alwaysUse24HourFormat = use24HourFormat ?? _useTimeFormatBasedOnLocale();
|
||||
}
|
||||
|
||||
final Widget child;
|
||||
/// The child contained by the DatePicker.
|
||||
final Widget? child;
|
||||
|
||||
/// A [Widget] to display when the user picks a disabled time in the [TimePickerDialog]
|
||||
final Widget? wrongTimeDialog;
|
||||
|
||||
/// Visual properties for the [DateTimePicker]
|
||||
final DateTimePickerTheme dateTimePickerTheme;
|
||||
|
||||
/// Widget shown at the top of the [DateTimePicker]
|
||||
final Widget? header;
|
||||
|
||||
/// Callback that provides the date tapped on as a [DateTime] object.
|
||||
final Function(DateTime)? onTapDay;
|
||||
|
||||
/// Whether the current day should be highlighted in the [DateTimePicker]
|
||||
final bool highlightToday;
|
||||
|
||||
/// a [bool] to set de clock on [TimePickerDialog] to a fixed 24 or 12-hour format.
|
||||
/// By default this gets determined by the [Locale] on the device.
|
||||
late final bool alwaysUse24HourFormat;
|
||||
|
||||
/// [pickTime] is a [bool] that determines if the user is able to pick a time after picking a date usring the [TimePickerDialog].
|
||||
final bool pickTime;
|
||||
|
||||
/// indicates the starting date. Default is [DateTime.now()]
|
||||
final DateTime? initialDate;
|
||||
|
||||
/// [markedDates] contain the dates [DateTime] that will be marked in the [DateTimePicker] by a small dot.
|
||||
final List<DateTime>? markedDates;
|
||||
|
||||
/// a [List] of [DateTime] objects that will be disabled and cannot be interacted with whatsoever.
|
||||
final List<DateTime>? disabledDates;
|
||||
|
||||
/// a [List] of [TimeOfDay] objects that cannot be picked in the [TimePickerDialog].
|
||||
final List<TimeOfDay>? disabledTimes;
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _DateTimePickerState();
|
||||
}
|
||||
|
@ -132,6 +170,9 @@ class DateTimePicker extends StatefulWidget {
|
|||
class _DateTimePickerState extends State<DateTimePicker> {
|
||||
late DateTimePickerController _dateTimePickerController;
|
||||
|
||||
final DraggableScrollableController _dragController =
|
||||
DraggableScrollableController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
@ -139,16 +180,19 @@ class _DateTimePickerState extends State<DateTimePicker> {
|
|||
|
||||
_dateTimePickerController = DateTimePickerController(
|
||||
highlightToday: widget.highlightToday,
|
||||
alwaysUse24HourFormat: widget.alwaysUse24HourFormat,
|
||||
pickTime: widget.pickTime,
|
||||
theme: widget.dateTimePickerTheme,
|
||||
header: widget.header,
|
||||
markedDates: widget.markedDates,
|
||||
disabledDates: widget.disabledDates,
|
||||
disabledTimes: widget.disabledTimes,
|
||||
onTapDayCallBack: widget.onTapDay,
|
||||
browsingDate: widget.initialDate ?? DateTime.now(),
|
||||
selectedDate: widget.initialDate ?? DateTime.now(),
|
||||
);
|
||||
|
||||
_dateTimePickerController.addListener(() {
|
||||
print('BROWSING DATE: ${_dateTimePickerController.browsingDate}');
|
||||
print('SELECTED DATE: ${_dateTimePickerController.selectedDate}');
|
||||
setState(() {});
|
||||
});
|
||||
}
|
||||
|
@ -156,6 +200,7 @@ class _DateTimePickerState extends State<DateTimePicker> {
|
|||
@override
|
||||
void dispose() {
|
||||
_dateTimePickerController.dispose();
|
||||
_dragController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
@ -163,16 +208,20 @@ class _DateTimePickerState extends State<DateTimePicker> {
|
|||
Widget build(BuildContext context) {
|
||||
return Stack(
|
||||
children: [
|
||||
widget.child,
|
||||
if (widget.child != null) ...[
|
||||
widget.child!,
|
||||
],
|
||||
RotatedBox(
|
||||
quarterTurns: 2,
|
||||
child: DraggableScrollableSheet(
|
||||
controller: _dateTimePickerController.getDragController(),
|
||||
controller: _dragController,
|
||||
snap: true,
|
||||
minChildSize: 0.26,
|
||||
initialChildSize: 0.26,
|
||||
maxChildSize: 0.68,
|
||||
minChildSize: 0.2,
|
||||
initialChildSize: 0.2,
|
||||
maxChildSize: 0.6,
|
||||
builder: (context, scrollController) {
|
||||
double dragSize =
|
||||
_dragController.isAttached ? _dragController.size : 0;
|
||||
return RotatedBox(
|
||||
quarterTurns: 2,
|
||||
child: Stack(
|
||||
|
@ -197,17 +246,18 @@ class _DateTimePickerState extends State<DateTimePicker> {
|
|||
),
|
||||
],
|
||||
),
|
||||
child: _dateTimePickerController
|
||||
.getDragController()
|
||||
.size <
|
||||
0.3
|
||||
child: dragSize < 0.3
|
||||
? WeekDateTimePickerSheet(
|
||||
dateTimePickerController:
|
||||
_dateTimePickerController,
|
||||
weekDateBoxSize: widget
|
||||
.dateTimePickerTheme.weekDateBoxSize,
|
||||
)
|
||||
: MonthDateTimePickerSheet(
|
||||
dateTimePickerController:
|
||||
_dateTimePickerController,
|
||||
monthDateBoxSize: widget
|
||||
.dateTimePickerTheme.monthDateBoxSize,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -222,3 +272,24 @@ class _DateTimePickerState extends State<DateTimePicker> {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
bool _useTimeFormatBasedOnLocale() {
|
||||
// Get LocaleName of current platform and split language- and countryCode in 2 List values.
|
||||
List<String> deviceLocale = Platform.localeName.split('_');
|
||||
|
||||
// Make LocaleName of current platform in a Locale Object
|
||||
Locale defaultLocale = Locale.fromSubtags(
|
||||
languageCode: deviceLocale[0],
|
||||
countryCode: deviceLocale[1],
|
||||
);
|
||||
|
||||
// Determine Country.
|
||||
switch (defaultLocale.countryCode) {
|
||||
case 'NL':
|
||||
return true;
|
||||
case 'US':
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
7
lib/src/enums/date_box_shape.dart
Normal file
|
@ -0,0 +1,7 @@
|
|||
|
||||
/// Defines the shape of a specific date.
|
||||
enum DateBoxShape {
|
||||
circle,
|
||||
rectangle,
|
||||
roundedRectangle
|
||||
}
|
|
@ -1,16 +1,17 @@
|
|||
extension DatePickerUtil on DateTime {
|
||||
// Check if the current date is the same as the given date
|
||||
bool sameDayAs(DateTime selectedDate) {
|
||||
extension DateTimeExtension on DateTime {
|
||||
/// Check if the current [DateTime] is the same as the given [selectedDate]
|
||||
bool equals(DateTime selectedDate) {
|
||||
return selectedDate.day == day &&
|
||||
selectedDate.month == month &&
|
||||
selectedDate.year == year;
|
||||
}
|
||||
|
||||
// Check if the current date is contained in the given list
|
||||
bool isContainedIn(List<DateTime> dates) {
|
||||
return dates.any((element) => element.sameDayAs(this));
|
||||
/// Check if the current [DateTime] contains any the given [dates]
|
||||
bool containsAny(List<DateTime> dates) {
|
||||
return dates.any((element) => element.equals(this));
|
||||
}
|
||||
|
||||
// Return a [List] of [DateTime] objects of the week the current [DateTime] is in.
|
||||
List<DateTime> daysOfWeek() {
|
||||
var startFrom = subtract(Duration(days: weekday));
|
||||
return List.generate(
|
||||
|
@ -22,9 +23,11 @@ extension DatePickerUtil on DateTime {
|
|||
);
|
||||
}
|
||||
|
||||
/// Determine if a certain [year] of a [DateTime] object is a leap year.
|
||||
bool get isLeapYear =>
|
||||
(year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0);
|
||||
|
||||
/// Returns the amount of days in the current month of the [DateTime] object
|
||||
int daysInMonth() {
|
||||
late int amountOfDays;
|
||||
|
||||
|
|
13
lib/src/extensions/time_of_day.dart
Normal file
|
@ -0,0 +1,13 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
extension TimeOfDayExtension on TimeOfDay {
|
||||
/// Check if the current [TimeOfDay] contains any the given [times]
|
||||
bool containsAny(List<TimeOfDay> times) {
|
||||
return times.any((element) => element.equals(this));
|
||||
}
|
||||
|
||||
/// Check if the current [TimeOfDay] is the same as the given [selectedTime]
|
||||
bool equals(TimeOfDay selectedTime) {
|
||||
return selectedTime.hour == hour && selectedTime.minute == minute;
|
||||
}
|
||||
}
|
15
lib/src/models/date_box_base_theme.dart
Normal file
|
@ -0,0 +1,15 @@
|
|||
import 'package:flutter/widgets.dart' show Color, TextStyle;
|
||||
|
||||
class DateBoxBaseTheme {
|
||||
/// Default date theme.
|
||||
const DateBoxBaseTheme(
|
||||
this.backgroundColor,
|
||||
this.textStyle,
|
||||
);
|
||||
|
||||
/// Background color of default date
|
||||
final Color? backgroundColor;
|
||||
|
||||
/// The style of the date number.
|
||||
final TextStyle? textStyle;
|
||||
}
|
15
lib/src/models/date_box_current_theme.dart
Normal file
|
@ -0,0 +1,15 @@
|
|||
import 'package:flutter/widgets.dart' show Color, TextStyle;
|
||||
|
||||
class DateBoxCurrentTheme {
|
||||
/// Default date theme.
|
||||
const DateBoxCurrentTheme(
|
||||
this.backgroundColor,
|
||||
this.textStyle,
|
||||
);
|
||||
|
||||
/// Background color of default date
|
||||
final Color backgroundColor;
|
||||
|
||||
/// The style of the date number.
|
||||
final TextStyle textStyle;
|
||||
}
|
15
lib/src/models/date_box_disabled_theme.dart
Normal file
|
@ -0,0 +1,15 @@
|
|||
import 'package:flutter/widgets.dart' show Color, TextStyle;
|
||||
|
||||
class DateBoxDisabledTheme {
|
||||
/// Disabled date theme.
|
||||
const DateBoxDisabledTheme(
|
||||
this.backgroundColor,
|
||||
this.textStyle,
|
||||
);
|
||||
|
||||
/// Background color of selected date.
|
||||
final Color? backgroundColor;
|
||||
|
||||
/// The style of the date number.
|
||||
final TextStyle? textStyle;
|
||||
}
|
15
lib/src/models/date_box_highlight_theme.dart
Normal file
|
@ -0,0 +1,15 @@
|
|||
import 'package:flutter/widgets.dart' show Color, TextStyle;
|
||||
|
||||
class DateBoxHighlightTheme {
|
||||
/// Highlighted date theme.
|
||||
const DateBoxHighlightTheme(
|
||||
this.backgroundColor,
|
||||
this.textStyle,
|
||||
);
|
||||
|
||||
/// Background color of highlighted date.
|
||||
final Color? backgroundColor;
|
||||
|
||||
/// The style of the date number.
|
||||
final TextStyle? textStyle;
|
||||
}
|
15
lib/src/models/date_box_selected_theme.dart
Normal file
|
@ -0,0 +1,15 @@
|
|||
import 'package:flutter/widgets.dart' show Color, TextStyle;
|
||||
|
||||
class DateBoxSelectedTheme {
|
||||
/// Selected date theme.
|
||||
const DateBoxSelectedTheme(
|
||||
this.backgroundColor,
|
||||
this.textStyle,
|
||||
);
|
||||
|
||||
/// Background color of selected date.
|
||||
final Color? backgroundColor;
|
||||
|
||||
/// The style of the date number.
|
||||
final TextStyle? textStyle;
|
||||
}
|
54
lib/src/models/date_time_picker_theme.dart
Normal file
|
@ -0,0 +1,54 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_date_time_picker/flutter_date_time_picker.dart';
|
||||
|
||||
class DateTimePickerTheme {
|
||||
/// The [DateTimePickerTheme] to style [DateTimePicker] in. Define a custom shape for the dates and specifically style
|
||||
/// a basic, hightlighted, selected and disabled date.
|
||||
const DateTimePickerTheme({
|
||||
this.weekDateBoxSize = 35,
|
||||
this.monthDateBoxSize = 45,
|
||||
this.markedIndicatorColor,
|
||||
this.dateBoxShape = DateBoxShape.roundedRectangle,
|
||||
this.baseTheme = const DateBoxBaseTheme(
|
||||
Colors.white,
|
||||
TextStyle(color: Colors.black),
|
||||
),
|
||||
this.highlightTheme = const DateBoxHighlightTheme(
|
||||
Colors.blue,
|
||||
TextStyle(color: Colors.white),
|
||||
),
|
||||
this.selectedTheme = const DateBoxSelectedTheme(
|
||||
Color(0xFFBBDEFB),
|
||||
TextStyle(color: Colors.blue),
|
||||
),
|
||||
this.disabledTheme = const DateBoxDisabledTheme(
|
||||
Colors.grey,
|
||||
TextStyle(color: Colors.white),
|
||||
),
|
||||
});
|
||||
|
||||
/// enum to define a shape dor the date. use [DateBoxShape.circle].
|
||||
/// For a ciruclar date, [DateBoxShape.rectangle] for a plain box and [DateBoxShape.roundedRectangle] to het a rectangle with small rounded borders.
|
||||
final DateBoxShape dateBoxShape;
|
||||
|
||||
/// This theme is used to style a default look for the dates.
|
||||
final DateBoxBaseTheme baseTheme;
|
||||
|
||||
/// This theme is used for when a specific date is highlighted.
|
||||
final DateBoxHighlightTheme highlightTheme;
|
||||
|
||||
/// This theme is used for when a specific date is slected by the user.
|
||||
final DateBoxSelectedTheme selectedTheme;
|
||||
|
||||
/// This theme is used for when a specific date is disabled.
|
||||
final DateBoxDisabledTheme disabledTheme;
|
||||
|
||||
/// Size of date box in a week view.
|
||||
final double weekDateBoxSize;
|
||||
|
||||
/// Size of date box in a month view.
|
||||
final double monthDateBoxSize;
|
||||
|
||||
/// The color used for a indicator for a marked date.
|
||||
final Color? markedIndicatorColor;
|
||||
}
|
|
@ -1,24 +1,37 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_date_time_picker/src/models/date_time_picker_theme.dart';
|
||||
|
||||
class DateTimePickerController extends ChangeNotifier {
|
||||
DateTimePickerController({
|
||||
required this.theme,
|
||||
required this.highlightToday,
|
||||
this.header,
|
||||
this.markedDates,
|
||||
this.onTapDayCallBack,
|
||||
required this.alwaysUse24HourFormat,
|
||||
required this.pickTime,
|
||||
required this.browsingDate,
|
||||
required this.selectedDate,
|
||||
this.header,
|
||||
this.wrongTimeDialog,
|
||||
this.markedDates,
|
||||
this.disabledDates,
|
||||
this.disabledTimes,
|
||||
this.onTapDayCallBack,
|
||||
});
|
||||
|
||||
final DraggableScrollableController _dragController =
|
||||
DraggableScrollableController();
|
||||
final PageController _pageController = PageController(initialPage: 1);
|
||||
|
||||
final bool highlightToday;
|
||||
final bool? alwaysUse24HourFormat;
|
||||
|
||||
final Widget? header;
|
||||
|
||||
final Widget? wrongTimeDialog;
|
||||
|
||||
final DateTimePickerTheme theme;
|
||||
|
||||
final List<DateTime>? markedDates;
|
||||
final List<DateTime>? disabledDates;
|
||||
final List<TimeOfDay>? disabledTimes;
|
||||
final bool pickTime;
|
||||
|
||||
final Function(DateTime)? onTapDayCallBack;
|
||||
|
||||
|
@ -28,7 +41,6 @@ class DateTimePickerController extends ChangeNotifier {
|
|||
@override
|
||||
void dispose() {
|
||||
_pageController.dispose();
|
||||
_dragController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
@ -45,7 +57,7 @@ class DateTimePickerController extends ChangeNotifier {
|
|||
);
|
||||
}
|
||||
|
||||
void onTapDay(date) {
|
||||
void onTapDay(DateTime date) {
|
||||
browsingDate = date;
|
||||
selectedDate = date;
|
||||
|
||||
|
@ -58,13 +70,7 @@ class DateTimePickerController extends ChangeNotifier {
|
|||
}
|
||||
}
|
||||
|
||||
DraggableScrollableController getDragController() {
|
||||
return _dragController;
|
||||
}
|
||||
|
||||
PageController getPageController() {
|
||||
return _pageController;
|
||||
}
|
||||
PageController get pageController => _pageController;
|
||||
|
||||
void setBrowsingDate(DateTime date) {
|
||||
browsingDate = date;
|
||||
|
|
|
@ -1,16 +1,22 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_date_time_picker/src/enums/date_box_shape.dart';
|
||||
import 'package:flutter_date_time_picker/src/extensions/date_time.dart';
|
||||
import 'package:flutter_date_time_picker/src/extensions/time_of_day.dart';
|
||||
import 'package:flutter_date_time_picker/src/models/date_box_current_theme.dart';
|
||||
import 'package:flutter_date_time_picker/src/models/date_time_picker_theme.dart';
|
||||
import 'package:flutter_date_time_picker/src/utils/date_time_picker_controller.dart';
|
||||
|
||||
class MonthDateTimePicker extends StatelessWidget {
|
||||
const MonthDateTimePicker({
|
||||
required this.date,
|
||||
required this.dateTimePickerController,
|
||||
required this.monthDateBoxSize,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
final DateTime date;
|
||||
final DateTimePickerController dateTimePickerController;
|
||||
final double monthDateBoxSize;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -26,101 +32,104 @@ class MonthDateTimePicker extends StatelessWidget {
|
|||
margin: const EdgeInsets.symmetric(horizontal: 30),
|
||||
child: Center(
|
||||
child: GridView.count(
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
crossAxisSpacing: 5,
|
||||
crossAxisCount: 7,
|
||||
children: List.generate(
|
||||
DateTime(date.year, date.month).daysInMonth() + daysToSkip,
|
||||
DateTime(date.year, date.month).daysInMonth() +
|
||||
(daysToSkip >= 7 ? 0 : daysToSkip),
|
||||
(index) {
|
||||
if (index < daysToSkip) {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.red.withOpacity(0.4),
|
||||
border: Border.all(color: Colors.black, width: 1.5),
|
||||
),
|
||||
margin:
|
||||
const EdgeInsets.symmetric(vertical: 5, horizontal: 5),
|
||||
height: 45,
|
||||
width: 45,
|
||||
child: Center(
|
||||
child: Text(
|
||||
(index + 1 - daysToSkip).toString(),
|
||||
style: Theme.of(context).textTheme.bodyText1!.copyWith(
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
late DateBoxCurrentTheme currentDateBoxTheme;
|
||||
|
||||
int addedIndex = index;
|
||||
|
||||
if (daysToSkip >= 7) {
|
||||
addedIndex = index + 7;
|
||||
}
|
||||
if (addedIndex < daysToSkip) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
currentDateBoxTheme = determineCurrentDateBoxTheme(context,
|
||||
addedIndex, daysToSkip, dateTimePickerController.theme);
|
||||
|
||||
return GestureDetector(
|
||||
onTap: isDisabled(
|
||||
addedIndex,
|
||||
daysToSkip,
|
||||
)
|
||||
? null
|
||||
: () async {
|
||||
TimeOfDay? timeOfDay;
|
||||
|
||||
onTap: () async {
|
||||
// await dateTimePickerController.getDragController().animateTo(
|
||||
// 0.26,
|
||||
// duration: const Duration(
|
||||
// milliseconds: 350,
|
||||
// ),
|
||||
// curve: Curves.ease,
|
||||
// );
|
||||
DateTime selectedDate = DateTime(
|
||||
date.year,
|
||||
date.month,
|
||||
addedIndex + 1 - daysToSkip,
|
||||
);
|
||||
|
||||
dateTimePickerController.onTapDay(DateTime(
|
||||
date.year,
|
||||
date.month,
|
||||
index + 1 - daysToSkip,
|
||||
date.hour,
|
||||
date.minute,
|
||||
date.second,
|
||||
));
|
||||
},
|
||||
timeOfDay = const TimeOfDay(hour: 0, minute: 0);
|
||||
|
||||
if (dateTimePickerController.pickTime) {
|
||||
timeOfDay = await displayTimePicker(
|
||||
context, dateTimePickerController);
|
||||
}
|
||||
|
||||
if (dateTimePickerController.wrongTimeDialog != null) {
|
||||
if (timeOfDay != null &&
|
||||
timeOfDay.containsAny(
|
||||
dateTimePickerController.disabledTimes ?? [],
|
||||
)) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) =>
|
||||
dateTimePickerController.wrongTimeDialog!);
|
||||
}
|
||||
}
|
||||
|
||||
DateTime selectedDateTime = DateTime(
|
||||
selectedDate.year,
|
||||
selectedDate.month,
|
||||
selectedDate.day,
|
||||
timeOfDay!.hour,
|
||||
timeOfDay.minute,
|
||||
);
|
||||
|
||||
dateTimePickerController.onTapDay(selectedDateTime);
|
||||
},
|
||||
child: Container(
|
||||
margin:
|
||||
const EdgeInsets.symmetric(vertical: 5, horizontal: 5),
|
||||
decoration: BoxDecoration(
|
||||
color:
|
||||
// isDisabled()
|
||||
// ? Theme.of(context).disabledColor
|
||||
// : Colors.transparent,
|
||||
// isSelected(index, daysToSkip)
|
||||
// ? Theme.of(context).primaryColor.withOpacity(0.2)
|
||||
// : Colors.transparent,
|
||||
shouldHighlight(index, daysToSkip)
|
||||
? Theme.of(context).primaryColor
|
||||
: Colors.transparent,
|
||||
borderRadius: BorderRadius.circular(
|
||||
10,
|
||||
),
|
||||
color: currentDateBoxTheme.backgroundColor,
|
||||
borderRadius:
|
||||
_determineBorderRadius(dateTimePickerController),
|
||||
),
|
||||
height: 45,
|
||||
width: 45,
|
||||
height: monthDateBoxSize,
|
||||
width: monthDateBoxSize,
|
||||
child: Stack(
|
||||
children: [
|
||||
Center(
|
||||
child: Text(
|
||||
(index + 1 - daysToSkip).toString(),
|
||||
style:
|
||||
Theme.of(context).textTheme.bodyText1!.copyWith(
|
||||
color:
|
||||
// isDisabled()
|
||||
// ? Colors.white
|
||||
// : Colors.transparent,
|
||||
// isSelected(index, daysToSkip)
|
||||
// ? Theme.of(context).primaryColor
|
||||
// : Colors.black,
|
||||
shouldHighlight(index, daysToSkip)
|
||||
? Colors.white
|
||||
: Colors.black,
|
||||
),
|
||||
),
|
||||
child: Text((addedIndex + 1 - daysToSkip).toString(),
|
||||
style: currentDateBoxTheme.textStyle),
|
||||
),
|
||||
if (shouldMark(index, daysToSkip)) ...[
|
||||
if (shouldMark(
|
||||
addedIndex,
|
||||
daysToSkip,
|
||||
)) ...[
|
||||
Align(
|
||||
alignment: Alignment.bottomRight,
|
||||
child: Container(
|
||||
width: 12,
|
||||
height: 12,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).indicatorColor,
|
||||
borderRadius: BorderRadius.circular(45),
|
||||
child: IgnorePointer(
|
||||
child: Container(
|
||||
width: monthDateBoxSize / 4,
|
||||
height: monthDateBoxSize / 4,
|
||||
decoration: BoxDecoration(
|
||||
color: dateTimePickerController
|
||||
.theme.markedIndicatorColor ??
|
||||
Theme.of(context).indicatorColor,
|
||||
borderRadius: BorderRadius.circular(
|
||||
(monthDateBoxSize / 4) * 2),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -141,15 +150,56 @@ class MonthDateTimePicker extends StatelessWidget {
|
|||
date.year,
|
||||
date.month,
|
||||
index + 1 - daysToSkip,
|
||||
).sameDayAs(
|
||||
).equals(
|
||||
dateTimePickerController.highlightToday
|
||||
? DateTime.now()
|
||||
: dateTimePickerController.selectedDate,
|
||||
);
|
||||
}
|
||||
|
||||
bool isDisabled() {
|
||||
return true;
|
||||
DateBoxCurrentTheme determineCurrentDateBoxTheme(
|
||||
BuildContext context,
|
||||
int index,
|
||||
int daysToSkip,
|
||||
DateTimePickerTheme theme,
|
||||
) {
|
||||
DateBoxCurrentTheme determinedTheme = DateBoxCurrentTheme(
|
||||
theme.baseTheme.backgroundColor ?? Colors.transparent,
|
||||
theme.baseTheme.textStyle ?? const TextStyle(color: Colors.black),
|
||||
);
|
||||
|
||||
if (isDisabled(index, daysToSkip)) {
|
||||
determinedTheme = DateBoxCurrentTheme(
|
||||
theme.disabledTheme.backgroundColor ?? Theme.of(context).disabledColor,
|
||||
theme.disabledTheme.textStyle ?? const TextStyle(color: Colors.white),
|
||||
);
|
||||
}
|
||||
if (isSelected(index, daysToSkip)) {
|
||||
determinedTheme = DateBoxCurrentTheme(
|
||||
theme.selectedTheme.backgroundColor ??
|
||||
Theme.of(context).primaryColor.withOpacity(0.3),
|
||||
theme.selectedTheme.textStyle ??
|
||||
TextStyle(color: Theme.of(context).primaryColor));
|
||||
}
|
||||
if (shouldHighlight(index, daysToSkip)) {
|
||||
determinedTheme = DateBoxCurrentTheme(
|
||||
theme.highlightTheme.backgroundColor ??
|
||||
Theme.of(context).primaryColor,
|
||||
theme.highlightTheme.textStyle ??
|
||||
const TextStyle(color: Colors.white));
|
||||
}
|
||||
|
||||
return determinedTheme;
|
||||
}
|
||||
|
||||
bool isDisabled(int index, int daysToSkip) {
|
||||
return DateTime(
|
||||
date.year,
|
||||
date.month,
|
||||
index + 1 - daysToSkip,
|
||||
).containsAny(
|
||||
dateTimePickerController.disabledDates ?? [],
|
||||
);
|
||||
}
|
||||
|
||||
bool isSelected(int index, int daysToSkip) {
|
||||
|
@ -157,7 +207,7 @@ class MonthDateTimePicker extends StatelessWidget {
|
|||
date.year,
|
||||
date.month,
|
||||
index + 1 - daysToSkip,
|
||||
).sameDayAs(dateTimePickerController.selectedDate);
|
||||
).equals(dateTimePickerController.selectedDate);
|
||||
}
|
||||
|
||||
bool shouldMark(int index, int daysToSkip) {
|
||||
|
@ -165,7 +215,7 @@ class MonthDateTimePicker extends StatelessWidget {
|
|||
date.year,
|
||||
date.month,
|
||||
index + 1 - daysToSkip,
|
||||
).sameDayAs(
|
||||
).equals(
|
||||
dateTimePickerController.highlightToday
|
||||
? DateTime.now()
|
||||
: dateTimePickerController.selectedDate,
|
||||
|
@ -174,8 +224,35 @@ class MonthDateTimePicker extends StatelessWidget {
|
|||
date.year,
|
||||
date.month,
|
||||
index + 1 - daysToSkip,
|
||||
).isContainedIn(
|
||||
).containsAny(
|
||||
dateTimePickerController.markedDates ?? [],
|
||||
);
|
||||
}
|
||||
|
||||
BorderRadius _determineBorderRadius(
|
||||
DateTimePickerController dateTimePickerController) {
|
||||
switch (dateTimePickerController.theme.dateBoxShape) {
|
||||
case DateBoxShape.circle:
|
||||
return BorderRadius.circular(monthDateBoxSize * 2);
|
||||
case DateBoxShape.rectangle:
|
||||
return BorderRadius.zero;
|
||||
case DateBoxShape.roundedRectangle:
|
||||
return BorderRadius.circular(monthDateBoxSize / 4.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
displayTimePicker(BuildContext context,
|
||||
DateTimePickerController dateTimePickerController) async {
|
||||
return await showTimePicker(
|
||||
context: context,
|
||||
initialTime: TimeOfDay.now(),
|
||||
builder: (BuildContext context, Widget? child) {
|
||||
return MediaQuery(
|
||||
data: MediaQuery.of(context).copyWith(
|
||||
alwaysUse24HourFormat:
|
||||
dateTimePickerController.alwaysUse24HourFormat),
|
||||
child: child!,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -7,10 +7,12 @@ import 'package:intl/intl.dart';
|
|||
class MonthDateTimePickerSheet extends StatelessWidget {
|
||||
const MonthDateTimePickerSheet({
|
||||
required this.dateTimePickerController,
|
||||
required this.monthDateBoxSize,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
final DateTimePickerController dateTimePickerController;
|
||||
final double monthDateBoxSize;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -28,16 +30,14 @@ class MonthDateTimePickerSheet extends StatelessWidget {
|
|||
DateFormat.yMMMM().format(
|
||||
dateTimePickerController.browsingDate,
|
||||
),
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.headlineMedium!
|
||||
.copyWith(color: Colors.black),
|
||||
style: dateTimePickerController.theme.baseTheme.textStyle!
|
||||
.copyWith(fontSize: 25),
|
||||
),
|
||||
SizedBox(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
height: 300,
|
||||
height: MediaQuery.of(context).size.height * 0.33,
|
||||
child: PageView(
|
||||
controller: dateTimePickerController.getPageController(),
|
||||
controller: dateTimePickerController.pageController,
|
||||
onPageChanged: (i) {
|
||||
if (i == 0) {
|
||||
dateTimePickerController.onPageChanged(
|
||||
|
@ -68,21 +68,27 @@ class MonthDateTimePickerSheet extends StatelessWidget {
|
|||
dateTimePickerController.browsingDate.year - 1, 12, 1)
|
||||
: DateTime(dateTimePickerController.browsingDate.year,
|
||||
dateTimePickerController.browsingDate.month - 1, 1),
|
||||
monthDateBoxSize: monthDateBoxSize,
|
||||
dateTimePickerController: dateTimePickerController),
|
||||
MonthDateTimePicker(
|
||||
date: dateTimePickerController.browsingDate,
|
||||
dateTimePickerController: dateTimePickerController),
|
||||
date: DateTime(
|
||||
dateTimePickerController.browsingDate.year,
|
||||
dateTimePickerController.browsingDate.month,
|
||||
1,
|
||||
),
|
||||
dateTimePickerController: dateTimePickerController,
|
||||
monthDateBoxSize: monthDateBoxSize),
|
||||
MonthDateTimePicker(
|
||||
date: dateTimePickerController.browsingDate.month == 12
|
||||
? DateTime(
|
||||
dateTimePickerController.browsingDate.year + 1,
|
||||
1,
|
||||
1,
|
||||
)
|
||||
: DateTime(dateTimePickerController.browsingDate.year,
|
||||
dateTimePickerController.browsingDate.month + 1, 1),
|
||||
dateTimePickerController: dateTimePickerController,
|
||||
),
|
||||
date: dateTimePickerController.browsingDate.month == 12
|
||||
? DateTime(
|
||||
dateTimePickerController.browsingDate.year + 1,
|
||||
1,
|
||||
1,
|
||||
)
|
||||
: DateTime(dateTimePickerController.browsingDate.year,
|
||||
dateTimePickerController.browsingDate.month + 1, 1),
|
||||
dateTimePickerController: dateTimePickerController,
|
||||
monthDateBoxSize: monthDateBoxSize),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_date_time_picker/flutter_date_time_picker.dart';
|
||||
import 'package:flutter_date_time_picker/src/extensions/date_time.dart';
|
||||
import 'package:flutter_date_time_picker/src/extensions/time_of_day.dart';
|
||||
import 'package:flutter_date_time_picker/src/models/date_box_current_theme.dart';
|
||||
import 'package:flutter_date_time_picker/src/utils/date_time_picker_controller.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
|
@ -7,6 +10,7 @@ class WeekDateTimePicker extends StatelessWidget {
|
|||
const WeekDateTimePicker({
|
||||
required this.dateTimePickerController,
|
||||
required this.date,
|
||||
required this.weekDateBoxSize,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
|
@ -14,82 +18,155 @@ class WeekDateTimePicker extends StatelessWidget {
|
|||
|
||||
final DateTime date;
|
||||
|
||||
final double weekDateBoxSize;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: List.generate(
|
||||
date.daysOfWeek().length,
|
||||
(index) => GestureDetector(
|
||||
onTap: () {
|
||||
dateTimePickerController.onTapDay(date.daysOfWeek()[index]);
|
||||
},
|
||||
child: SizedBox(
|
||||
width: 40,
|
||||
height: 60,
|
||||
child: Column(
|
||||
children: [
|
||||
const Spacer(),
|
||||
Text(
|
||||
DateFormat.E()
|
||||
.format(
|
||||
date.daysOfWeek().elementAt(index),
|
||||
)
|
||||
.toUpperCase()[0],
|
||||
style: Theme.of(context).textTheme.titleSmall,
|
||||
),
|
||||
const Spacer(),
|
||||
Container(
|
||||
height: 35,
|
||||
width: 35,
|
||||
decoration: BoxDecoration(
|
||||
color: shouldHighlight(index)
|
||||
? Theme.of(context).primaryColor
|
||||
: Colors.transparent,
|
||||
borderRadius: BorderRadius.circular(
|
||||
10,
|
||||
),
|
||||
(index) {
|
||||
late DateBoxCurrentTheme currentDateBoxTheme;
|
||||
|
||||
currentDateBoxTheme = determineCurrentDateBoxTheme(
|
||||
context, index, dateTimePickerController.theme);
|
||||
return GestureDetector(
|
||||
onTap: isDisabled(
|
||||
index,
|
||||
)
|
||||
? null
|
||||
: () async {
|
||||
TimeOfDay? timeOfDay;
|
||||
|
||||
DateTime selectedDate = date.daysOfWeek()[index];
|
||||
|
||||
timeOfDay = const TimeOfDay(hour: 0, minute: 0);
|
||||
|
||||
if (dateTimePickerController.pickTime) {
|
||||
timeOfDay = await displayTimePicker(
|
||||
context, dateTimePickerController);
|
||||
}
|
||||
|
||||
if (dateTimePickerController.wrongTimeDialog != null) {
|
||||
if (timeOfDay != null &&
|
||||
timeOfDay.containsAny(
|
||||
dateTimePickerController.disabledTimes ?? [],
|
||||
)) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) =>
|
||||
dateTimePickerController.wrongTimeDialog!,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
DateTime selectedDateTime = DateTime(
|
||||
selectedDate.year,
|
||||
selectedDate.month,
|
||||
selectedDate.day,
|
||||
timeOfDay!.hour,
|
||||
timeOfDay.minute,
|
||||
);
|
||||
|
||||
dateTimePickerController.onTapDay(selectedDateTime);
|
||||
},
|
||||
child: SizedBox(
|
||||
width: 40,
|
||||
height: 60,
|
||||
child: Column(
|
||||
children: [
|
||||
const Spacer(),
|
||||
Text(
|
||||
DateFormat.E()
|
||||
.format(
|
||||
date.daysOfWeek().elementAt(index),
|
||||
)
|
||||
.toUpperCase()[0],
|
||||
style: dateTimePickerController.theme.baseTheme.textStyle,
|
||||
),
|
||||
child: Stack(
|
||||
children: [
|
||||
Center(
|
||||
child: Text(
|
||||
date.daysOfWeek().elementAt(index).day.toString(),
|
||||
style:
|
||||
Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||
color: shouldHighlight(index)
|
||||
? Colors.white
|
||||
: Colors.black,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (shouldMark(index)) ...[
|
||||
Align(
|
||||
alignment: Alignment.bottomRight,
|
||||
child: Container(
|
||||
width: 10,
|
||||
height: 10,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).indicatorColor,
|
||||
borderRadius: BorderRadius.circular(45),
|
||||
),
|
||||
const Spacer(),
|
||||
Container(
|
||||
height: weekDateBoxSize,
|
||||
width: weekDateBoxSize,
|
||||
decoration: BoxDecoration(
|
||||
color: currentDateBoxTheme.backgroundColor,
|
||||
borderRadius:
|
||||
_determineBorderRadius(dateTimePickerController),
|
||||
),
|
||||
child: Stack(
|
||||
children: [
|
||||
Center(
|
||||
child: Text(
|
||||
date.daysOfWeek().elementAt(index).day.toString(),
|
||||
style: currentDateBoxTheme.textStyle,
|
||||
),
|
||||
),
|
||||
if (shouldMark(index)) ...[
|
||||
Align(
|
||||
alignment: Alignment.bottomRight,
|
||||
child: Container(
|
||||
width: weekDateBoxSize / 3,
|
||||
height: weekDateBoxSize / 3,
|
||||
decoration: BoxDecoration(
|
||||
color: dateTimePickerController
|
||||
.theme.markedIndicatorColor ??
|
||||
Theme.of(context).indicatorColor,
|
||||
borderRadius:
|
||||
BorderRadius.circular(weekDateBoxSize * 2),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
],
|
||||
const Spacer(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
DateBoxCurrentTheme determineCurrentDateBoxTheme(
|
||||
BuildContext context,
|
||||
int index,
|
||||
DateTimePickerTheme theme,
|
||||
) {
|
||||
DateBoxCurrentTheme determinedTheme = DateBoxCurrentTheme(
|
||||
theme.baseTheme.backgroundColor ?? Colors.transparent,
|
||||
theme.baseTheme.textStyle ?? const TextStyle(color: Colors.black),
|
||||
);
|
||||
|
||||
if (isDisabled(index)) {
|
||||
determinedTheme = DateBoxCurrentTheme(
|
||||
theme.disabledTheme.backgroundColor ?? Theme.of(context).disabledColor,
|
||||
theme.disabledTheme.textStyle ?? const TextStyle(color: Colors.white),
|
||||
);
|
||||
}
|
||||
if (isSelected(index)) {
|
||||
determinedTheme = DateBoxCurrentTheme(
|
||||
theme.selectedTheme.backgroundColor ??
|
||||
Theme.of(context).primaryColor.withOpacity(0.3),
|
||||
theme.selectedTheme.textStyle ??
|
||||
TextStyle(color: Theme.of(context).primaryColor));
|
||||
}
|
||||
if (shouldHighlight(index)) {
|
||||
determinedTheme = DateBoxCurrentTheme(
|
||||
theme.highlightTheme.backgroundColor ??
|
||||
Theme.of(context).primaryColor,
|
||||
theme.highlightTheme.textStyle ??
|
||||
const TextStyle(color: Colors.white));
|
||||
}
|
||||
|
||||
return determinedTheme;
|
||||
}
|
||||
|
||||
bool shouldHighlight(int index) {
|
||||
return date.daysOfWeek().elementAt(index).sameDayAs(
|
||||
return date.daysOfWeek().elementAt(index).equals(
|
||||
dateTimePickerController.highlightToday
|
||||
? DateTime.now()
|
||||
: dateTimePickerController.selectedDate,
|
||||
|
@ -100,11 +177,18 @@ class WeekDateTimePicker extends StatelessWidget {
|
|||
return date
|
||||
.daysOfWeek()
|
||||
.elementAt(index)
|
||||
.sameDayAs(dateTimePickerController.selectedDate);
|
||||
.equals(dateTimePickerController.selectedDate);
|
||||
}
|
||||
|
||||
bool isDisabled(int index) {
|
||||
return date
|
||||
.daysOfWeek()
|
||||
.elementAt(index)
|
||||
.containsAny(dateTimePickerController.disabledDates ?? []);
|
||||
}
|
||||
|
||||
bool shouldMark(int index) {
|
||||
return !date.daysOfWeek().elementAt(index).sameDayAs(
|
||||
return !date.daysOfWeek().elementAt(index).equals(
|
||||
dateTimePickerController.highlightToday
|
||||
? DateTime.now()
|
||||
: dateTimePickerController.selectedDate,
|
||||
|
@ -112,6 +196,33 @@ class WeekDateTimePicker extends StatelessWidget {
|
|||
date
|
||||
.daysOfWeek()
|
||||
.elementAt(index)
|
||||
.isContainedIn(dateTimePickerController.markedDates ?? []);
|
||||
.containsAny(dateTimePickerController.markedDates ?? []);
|
||||
}
|
||||
|
||||
BorderRadius _determineBorderRadius(
|
||||
DateTimePickerController dateTimePickerController) {
|
||||
switch (dateTimePickerController.theme.dateBoxShape) {
|
||||
case DateBoxShape.circle:
|
||||
return BorderRadius.circular(weekDateBoxSize * 2);
|
||||
case DateBoxShape.rectangle:
|
||||
return BorderRadius.zero;
|
||||
case DateBoxShape.roundedRectangle:
|
||||
return BorderRadius.circular(weekDateBoxSize / 4.5);
|
||||
}
|
||||
}
|
||||
|
||||
displayTimePicker(BuildContext context,
|
||||
DateTimePickerController dateTimePickerController) async {
|
||||
return await showTimePicker(
|
||||
context: context,
|
||||
initialTime: TimeOfDay.now(),
|
||||
builder: (BuildContext context, Widget? child) {
|
||||
return MediaQuery(
|
||||
data: MediaQuery.of(context).copyWith(
|
||||
alwaysUse24HourFormat:
|
||||
dateTimePickerController.alwaysUse24HourFormat),
|
||||
child: child!,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,12 +7,14 @@ import 'package:intl/intl.dart';
|
|||
class WeekDateTimePickerSheet extends StatelessWidget {
|
||||
const WeekDateTimePickerSheet({
|
||||
required this.dateTimePickerController,
|
||||
required this.weekDateBoxSize,
|
||||
this.showHeader = false,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
final DateTimePickerController dateTimePickerController;
|
||||
final bool showHeader;
|
||||
final double weekDateBoxSize;
|
||||
|
||||
String getDateHeader() {
|
||||
List<DateTime> weekDays =
|
||||
|
@ -43,7 +45,8 @@ class WeekDateTimePickerSheet extends StatelessWidget {
|
|||
if (showHeader) ...[
|
||||
Text(
|
||||
getDateHeader(),
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
style: dateTimePickerController.theme.baseTheme.textStyle!
|
||||
.copyWith(fontSize: 9),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
|
@ -53,7 +56,7 @@ class WeekDateTimePickerSheet extends StatelessWidget {
|
|||
width: MediaQuery.of(context).size.width,
|
||||
height: 60,
|
||||
child: PageView(
|
||||
controller: dateTimePickerController.getPageController(),
|
||||
controller: dateTimePickerController.pageController,
|
||||
onPageChanged: (i) {
|
||||
if (i == 0) {
|
||||
dateTimePickerController.onPageChanged(
|
||||
|
@ -75,16 +78,19 @@ class WeekDateTimePickerSheet extends StatelessWidget {
|
|||
date: dateTimePickerController.browsingDate.subtract(
|
||||
const Duration(days: 7),
|
||||
),
|
||||
weekDateBoxSize: weekDateBoxSize,
|
||||
),
|
||||
WeekDateTimePicker(
|
||||
dateTimePickerController: dateTimePickerController,
|
||||
date: dateTimePickerController.browsingDate,
|
||||
weekDateBoxSize: weekDateBoxSize,
|
||||
),
|
||||
WeekDateTimePicker(
|
||||
dateTimePickerController: dateTimePickerController,
|
||||
date: dateTimePickerController.browsingDate.add(
|
||||
const Duration(days: 7),
|
||||
),
|
||||
weekDateBoxSize: weekDateBoxSize,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
75
test/date_time_extension_test.dart
Normal file
|
@ -0,0 +1,75 @@
|
|||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:flutter_date_time_picker/src/extensions/date_time.dart';
|
||||
|
||||
void main() {
|
||||
group('DateTimeExtension', () {
|
||||
test('equals() should return true if the same date, if not false', () {
|
||||
expect(DateTime(2022, 01, 01).equals(DateTime(2022, 01, 01)), true);
|
||||
expect(DateTime(2022, 01, 01).equals(DateTime(2022, 01, 02)), false);
|
||||
});
|
||||
|
||||
test(
|
||||
'containsAny() should return a boolean if the date is found in a list of dates or not',
|
||||
() {
|
||||
expect(
|
||||
DateTime(2022, 01, 01).containsAny([
|
||||
DateTime(2022, 01, 01),
|
||||
DateTime(2022, 01, 02),
|
||||
DateTime(2022, 01, 03)
|
||||
]),
|
||||
true);
|
||||
|
||||
expect(
|
||||
DateTime(2022, 01, 01).containsAny([
|
||||
DateTime(2022, 01, 02),
|
||||
DateTime(2022, 01, 03),
|
||||
DateTime(2022, 01, 04)
|
||||
]),
|
||||
false);
|
||||
});
|
||||
|
||||
test(
|
||||
'isLeapYear should return a boolean if the given year is a leap year or not',
|
||||
() {
|
||||
expect(DateTime(2016, 01, 01).isLeapYear, true); // A leap year
|
||||
expect(DateTime(2017, 01, 01).isLeapYear, false); // Not a leap year
|
||||
expect(DateTime(2018, 01, 01).isLeapYear, false); // Not a leap year
|
||||
expect(DateTime(2019, 01, 01).isLeapYear, false); // Not a leap year
|
||||
expect(DateTime(2020, 01, 01).isLeapYear, true); // A leap year
|
||||
});
|
||||
|
||||
test(
|
||||
'daysInMonth() should return the amount of days in the month relative on the date',
|
||||
() {
|
||||
var monthOfJanuary = DateTime(2022, 01, 01);
|
||||
var monthOfFebruary = DateTime(2022, 02, 01);
|
||||
var monthOfMarch = DateTime(2022, 03, 01);
|
||||
var monthOfApril = DateTime(2022, 04, 01);
|
||||
var monthOfMay = DateTime(2022, 05, 01);
|
||||
var monthOfJune = DateTime(2022, 06, 01);
|
||||
var monthOfJuly = DateTime(2022, 07, 01);
|
||||
var monthOfAugust = DateTime(2022, 08, 01);
|
||||
var monthOfSeptember = DateTime(2022, 09, 01);
|
||||
var monthOfOctober = DateTime(2022, 10, 01);
|
||||
var monthOfNovember = DateTime(2022, 11, 01);
|
||||
var monthOfDecember = DateTime(2022, 12, 01);
|
||||
|
||||
expect(monthOfJanuary.daysInMonth(), 31);
|
||||
// 2022 is not a leap year so this should return 28
|
||||
expect(monthOfFebruary.daysInMonth(), 28);
|
||||
expect(monthOfMarch.daysInMonth(), 31);
|
||||
expect(monthOfApril.daysInMonth(), 30);
|
||||
expect(monthOfMay.daysInMonth(), 31);
|
||||
expect(monthOfJune.daysInMonth(), 30);
|
||||
expect(monthOfJuly.daysInMonth(), 31);
|
||||
expect(monthOfAugust.daysInMonth(), 31);
|
||||
expect(monthOfSeptember.daysInMonth(), 30);
|
||||
expect(monthOfOctober.daysInMonth(), 31);
|
||||
expect(monthOfNovember.daysInMonth(), 30);
|
||||
expect(monthOfDecember.daysInMonth(), 31);
|
||||
|
||||
// 2020 is a leap year so this should return 29
|
||||
expect(DateTime(2020, 02, 01).daysInMonth(), 29);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -1,12 +1,48 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_date_time_picker/flutter_date_time_picker.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'package:flutter_date_time_picker/flutter_date_time_picker.dart';
|
||||
|
||||
void main() {
|
||||
test('adds one to input values', () {
|
||||
final calculator = Calculator();
|
||||
expect(calculator.addOne(2), 3);
|
||||
expect(calculator.addOne(-7), -6);
|
||||
expect(calculator.addOne(0), 1);
|
||||
testWidgets('Render App with DateTimePicker Widget', (tester) async {
|
||||
// Render App
|
||||
await tester.pumpWidget(MaterialApp(
|
||||
home: Scaffold(
|
||||
appBar: AppBar(),
|
||||
body: DateTimePicker(
|
||||
pickTime: false,
|
||||
child: Container(),
|
||||
),
|
||||
),
|
||||
));
|
||||
await tester.pump();
|
||||
});
|
||||
|
||||
testWidgets('Test if DateTimePicker Widget swipes', (tester) async {
|
||||
// Render App
|
||||
await tester.pumpWidget(MaterialApp(
|
||||
home: Scaffold(
|
||||
appBar: AppBar(),
|
||||
body: DateTimePicker(
|
||||
pickTime: false,
|
||||
child: Container(),
|
||||
),
|
||||
),
|
||||
));
|
||||
await tester.pump();
|
||||
|
||||
// Forward
|
||||
await tester.drag(
|
||||
find.byType(SingleChildScrollView), const Offset(500.0, 0.0));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Return
|
||||
await tester.drag(
|
||||
find.byType(SingleChildScrollView), const Offset(-500.0, 0.0));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
// Backward
|
||||
await tester.drag(
|
||||
find.byType(SingleChildScrollView), const Offset(-500.0, 0.0));
|
||||
await tester.pumpAndSettle();
|
||||
});
|
||||
}
|
||||
|
|
38
test/time_of_day_extension_test.dart
Normal file
|
@ -0,0 +1,38 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_date_time_picker/src/extensions/time_of_day.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
group('TimeOfDayExtension', () {
|
||||
test('equals() should return true if the same time, if not false', () {
|
||||
expect(
|
||||
const TimeOfDay(hour: 12, minute: 0)
|
||||
.equals(const TimeOfDay(hour: 12, minute: 0)),
|
||||
true);
|
||||
expect(
|
||||
const TimeOfDay(hour: 13, minute: 0)
|
||||
.equals(const TimeOfDay(hour: 12, minute: 0)),
|
||||
false);
|
||||
});
|
||||
|
||||
test(
|
||||
'containsAny() should return a boolean if the time is found in a list of times or not',
|
||||
() {
|
||||
expect(
|
||||
const TimeOfDay(hour: 12, minute: 0).containsAny(const [
|
||||
TimeOfDay(hour: 10, minute: 0),
|
||||
TimeOfDay(hour: 11, minute: 0),
|
||||
TimeOfDay(hour: 12, minute: 0)
|
||||
]),
|
||||
true);
|
||||
|
||||
expect(
|
||||
const TimeOfDay(hour: 12, minute: 0).containsAny(const [
|
||||
TimeOfDay(hour: 9, minute: 0),
|
||||
TimeOfDay(hour: 10, minute: 0),
|
||||
TimeOfDay(hour: 11, minute: 0)
|
||||
]),
|
||||
false);
|
||||
});
|
||||
});
|
||||
}
|