flutter_date_time_picker/lib/src/date_time_picker.dart

301 lines
9.9 KiB
Dart
Raw Normal View History

2022-11-01 09:43:38 +01:00
// SPDX-FileCopyrightText: 2022 Iconica
//
// SPDX-License-Identifier: BSD-3-Clause
2022-08-31 08:53:34 +02:00
import 'dart:io';
2022-08-26 09:56:44 +02:00
import 'package:flutter/material.dart';
2022-09-01 16:09:20 +02:00
import 'package:flutter_date_time_picker/src/models/date_time_picker_theme.dart';
2022-08-26 09:56:44 +02:00
import 'package:flutter_date_time_picker/src/utils/date_time_picker_controller.dart';
2022-11-01 09:43:38 +01:00
import 'package:flutter_date_time_picker/src/widgets/month_date_time_picker/month_date_time_picker_sheet.dart';
2022-08-26 09:56:44 +02:00
import 'package:flutter_date_time_picker/src/widgets/week_date_time_picker/week_date_time_picker_sheet.dart';
2022-08-29 10:56:41 +02:00
import 'package:intl/date_symbol_data_local.dart';
2022-08-26 09:56:44 +02:00
class DateTimePicker extends StatefulWidget {
2022-09-05 12:12:50 +02:00
/// 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(),
/// ),
/// ),
///```
2022-08-31 08:53:34 +02:00
DateTimePicker({
2022-09-01 16:09:20 +02:00
this.dateTimePickerTheme = const DateTimePickerTheme(),
2022-08-26 09:56:44 +02:00
this.header,
this.onTapDay,
this.highlightToday = true,
this.wrongTimeDialog,
2022-08-31 08:53:34 +02:00
bool? use24HourFormat,
this.pickTime = false,
2022-08-26 09:56:44 +02:00
this.initialDate,
this.markedDates,
2022-08-31 08:53:34 +02:00
this.disabledDates,
this.disabledTimes,
2022-09-01 16:09:20 +02:00
this.child,
2022-08-31 08:53:34 +02:00
super.key,
}) {
alwaysUse24HourFormat = use24HourFormat ?? _useTimeFormatBasedOnLocale();
2022-08-31 08:53:34 +02:00
}
2022-08-26 09:56:44 +02:00
/// The child contained by the DatePicker.
2022-09-01 16:09:20 +02:00
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]
2022-09-01 16:09:20 +02:00
final DateTimePickerTheme dateTimePickerTheme;
/// Widget shown at the top of the [DateTimePicker]
2022-08-26 09:56:44 +02:00
final Widget? header;
/// Callback that provides the date tapped on as a [DateTime] object.
2022-08-26 09:56:44 +02:00
final Function(DateTime)? onTapDay;
/// Whether the current day should be highlighted in the [DateTimePicker]
2022-08-26 09:56:44 +02:00
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.
2022-08-31 08:53:34 +02:00
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].
2022-08-31 08:53:34 +02:00
final bool pickTime;
/// indicates the starting date. Default is [DateTime.now()]
2022-08-26 09:56:44 +02:00
final DateTime? initialDate;
/// [markedDates] contain the dates [DateTime] that will be marked in the [DateTimePicker] by a small dot.
2022-08-26 09:56:44 +02:00
final List<DateTime>? markedDates;
/// a [List] of [DateTime] objects that will be disabled and cannot be interacted with whatsoever.
2022-08-31 08:53:34 +02:00
final List<DateTime>? disabledDates;
/// a [List] of [TimeOfDay] objects that cannot be picked in the [TimePickerDialog].
2022-08-31 08:53:34 +02:00
final List<TimeOfDay>? disabledTimes;
2022-08-26 09:56:44 +02:00
@override
State<StatefulWidget> createState() => _DateTimePickerState();
}
class _DateTimePickerState extends State<DateTimePicker> {
late DateTimePickerController _dateTimePickerController;
2022-09-01 09:13:03 +02:00
final DraggableScrollableController _dragController =
DraggableScrollableController();
2022-08-26 09:56:44 +02:00
@override
void initState() {
super.initState();
2022-08-29 10:56:41 +02:00
initializeDateFormatting();
2022-08-26 09:56:44 +02:00
_dateTimePickerController = DateTimePickerController(
highlightToday: widget.highlightToday,
2022-08-31 08:53:34 +02:00
alwaysUse24HourFormat: widget.alwaysUse24HourFormat,
pickTime: widget.pickTime,
2022-09-01 16:09:20 +02:00
theme: widget.dateTimePickerTheme,
2022-08-26 09:56:44 +02:00
header: widget.header,
markedDates: widget.markedDates,
2022-08-31 08:53:34 +02:00
disabledDates: widget.disabledDates,
disabledTimes: widget.disabledTimes,
2022-08-26 09:56:44 +02:00
onTapDayCallBack: widget.onTapDay,
browsingDate: widget.initialDate ?? DateTime.now(),
selectedDate: widget.initialDate ?? DateTime.now(),
);
_dateTimePickerController.addListener(() {
setState(() {});
});
}
@override
void dispose() {
_dateTimePickerController.dispose();
2022-09-01 09:13:03 +02:00
_dragController.dispose();
2022-08-26 09:56:44 +02:00
super.dispose();
}
@override
Widget build(BuildContext context) {
return Stack(
children: [
2022-09-01 16:09:20 +02:00
if (widget.child != null) ...[
widget.child!,
],
2022-08-26 09:56:44 +02:00
RotatedBox(
quarterTurns: 2,
child: DraggableScrollableSheet(
2022-09-01 09:13:03 +02:00
controller: _dragController,
2022-08-26 09:56:44 +02:00
snap: true,
2022-11-15 11:47:53 +01:00
minChildSize: _dateTimePickerController.theme.weekViewSize,
initialChildSize: _dateTimePickerController.theme.weekViewSize,
maxChildSize: _dateTimePickerController.theme.monthViewSize,
2022-08-26 09:56:44 +02:00
builder: (context, scrollController) {
2022-09-01 09:13:03 +02:00
double dragSize =
_dragController.isAttached ? _dragController.size : 0;
2022-08-26 09:56:44 +02:00
return RotatedBox(
quarterTurns: 2,
child: Stack(
children: [
SingleChildScrollView(
physics: const ClampingScrollPhysics(),
reverse: true,
controller: scrollController,
child: Padding(
padding: const EdgeInsets.only(bottom: 12.5),
child: Container(
decoration: BoxDecoration(
2022-11-11 13:01:28 +01:00
color:
_dateTimePickerController.theme.backgroundColor,
2022-08-26 09:56:44 +02:00
borderRadius: const BorderRadius.only(
bottomLeft: Radius.circular(20),
bottomRight: Radius.circular(20),
),
boxShadow: [
BoxShadow(
blurRadius: 5,
color: Colors.black.withOpacity(0.2),
),
],
),
2022-11-15 11:47:53 +01:00
child: dragSize < _dateTimePickerController.theme.weekMonthTriggerSize
2022-08-26 09:56:44 +02:00
? WeekDateTimePickerSheet(
dateTimePickerController:
_dateTimePickerController,
2022-09-01 16:09:20 +02:00
weekDateBoxSize: widget
.dateTimePickerTheme.weekDateBoxSize,
2022-08-26 09:56:44 +02:00
)
: MonthDateTimePickerSheet(
dateTimePickerController:
_dateTimePickerController,
2022-09-01 16:09:20 +02:00
monthDateBoxSize: widget
.dateTimePickerTheme.monthDateBoxSize,
2022-08-26 09:56:44 +02:00
),
),
),
),
],
),
);
},
),
),
],
);
}
}
2022-08-31 08:53:34 +02:00
bool _useTimeFormatBasedOnLocale() {
2022-08-31 08:53:34 +02:00
// Get LocaleName of current platform and split language- and countryCode in 2 List values.
2022-09-01 16:23:39 +02:00
List<String> deviceLocale = Platform.localeName.split('_');
2022-08-31 08:53:34 +02:00
// 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;
}
}