Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev #12

Merged
merged 7 commits into from
Jan 14, 2024
Merged

Dev #12

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified 3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
A Flutter library that provides a customizable Material Design date and range picker widgets.

<div>
<img src="https://raw.githubusercontent.com/hasanmhallak/date_picker/master/1.png" alt="1" width="200" height="225"/>
<img src="https://raw.githubusercontent.com/hasanmhallak/date_picker/master/1.png" alt="1" width="200" height="225"/>
<img src="https://raw.githubusercontent.com/hasanmhallak/date_picker/master/2.png" alt="2" width="200" height="225"/>
<img src="https://raw.githubusercontent.com/hasanmhallak/date_picker/master/3.png" alt="3" width="200" height="225"/>
<img src="https://raw.githubusercontent.com/hasanmhallak/date_picker/master/4.png" alt="4" width="200" height="225"/>
Expand Down Expand Up @@ -86,6 +86,7 @@ final date = await showDatePickerDialog(
slidersSize: 20,
splashColor: Colors.lightBlueAccent,
splashRadius: 40,
centerLeadingDate: true,
);
```

Expand Down Expand Up @@ -115,6 +116,7 @@ final range = await showRangePickerDialog(
slidersSize: 20,
splashColor: Colors.lightBlueAccent,
splashRadius: 40,
centerLeadingDate: true,
);
```

Expand Down
1 change: 1 addition & 0 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class MyApp extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center,
children: [
RangeDatePicker(
centerLeadingDate: true,
minDate: DateTime(2020, 10, 10),
maxDate: DateTime(2024, 10, 30),
),
Expand Down
69 changes: 48 additions & 21 deletions lib/src/date/date_picker.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,16 @@ class DatePicker extends StatefulWidget {
/// displayed. By default it will show the day grid, but this can be changed
/// with [initialPickerType].
///
/// [maxDate] must be after or equal to [minDate].
///
/// [initialDate] and [selectedDate], if provided, must be between [maxDate] and [minDate]
/// or equal to one of them.
/// The [minDate] is the earliest allowable date. The [maxDate] is the latest
/// allowable date. [initialDate] and [selectedDate] must either fall between
/// these dates, or be equal to one of them.
///
/// The [currentDate] represents the current day (i.e. today). This
/// date will be highlighted in the day grid. If null, the date of
/// `DateTime.now()` will be used.
///
/// For each of these [DateTime] parameters, only
/// their dates are considered. Their time fields are ignored.
DatePicker({
super.key,
required this.maxDate,
Expand All @@ -68,22 +70,26 @@ class DatePicker extends StatefulWidget {
this.highlightColor,
this.splashColor,
this.splashRadius,
this.centerLeadingDate = false,
}) {
assert(
!maxDate.isBefore(minDate),
'maxDate $maxDate must be on or after minDate $minDate.',
);
assert(!minDate.isAfter(maxDate), "minDate can't be after maxDate");
}

/// The date which will be displayed on first opening.
/// If not specified, the picker will default to `DateTime.now()` date.
///
/// Note that only dates are considered. time fields are ignored.
final DateTime? initialDate;

/// The date to which the picker will consider as current date. e.g (today).
/// If not specified, the picker will default to `DateTime.now()` date.
///
/// Note that only dates are considered. time fields are ignored.
final DateTime? currentDate;

/// The initially selected date when the picker is first opened.
///
/// Note that only dates are considered. time fields are ignored.
final DateTime? selectedDate;

/// Called when the user picks a date.
Expand All @@ -92,11 +98,15 @@ class DatePicker extends StatefulWidget {
/// The earliest date the user is permitted to pick.
///
/// This date must be on or before the [maxDate].
///
/// Note that only dates are considered. time fields are ignored.
final DateTime minDate;

/// The latest date the user is permitted to pick.
///
/// This date must be on or after the [minDate].
///
/// Note that only dates are considered. time fields are ignored.
final DateTime maxDate;

/// The initial display of the calendar picker.
Expand Down Expand Up @@ -186,6 +196,12 @@ class DatePicker extends StatefulWidget {
/// The radius of the ink splash.
final double? splashRadius;

/// Centring the leading date. e.g:
///
/// < December 2023 >
///
final bool centerLeadingDate;

@override
State<DatePicker> createState() => _DatePickerState();
}
Expand All @@ -197,23 +213,28 @@ class _DatePickerState extends State<DatePicker> {

@override
void initState() {
_displayedDate = widget.initialDate ?? DateUtils.dateOnly(DateTime.now());
_displayedDate = DateUtils.dateOnly(widget.initialDate ?? DateTime.now());
_pickerType = widget.initialPickerType;
_selectedDate = widget.selectedDate;

_selectedDate = widget.selectedDate != null
? DateUtils.dateOnly(widget.selectedDate!)
: null;

super.initState();
}

@override
void didUpdateWidget(covariant DatePicker oldWidget) {
if (oldWidget.initialDate != widget.initialDate) {
_displayedDate = widget.initialDate ?? DateUtils.dateOnly(DateTime.now());
_displayedDate = DateUtils.dateOnly(widget.initialDate ?? DateTime.now());
}
if (oldWidget.initialPickerType != widget.initialPickerType) {
_pickerType = widget.initialPickerType;
}
if (oldWidget.selectedDate != widget.selectedDate) {
_selectedDate = widget.selectedDate;
_selectedDate = widget.selectedDate != null
? DateUtils.dateOnly(widget.selectedDate!)
: null;
}
super.didUpdateWidget(oldWidget);
}
Expand All @@ -225,11 +246,13 @@ class _DatePickerState extends State<DatePicker> {
return Padding(
padding: widget.padding,
child: DaysPicker(
centerLeadingDate: widget.centerLeadingDate,
initialDate: _displayedDate,
selectedDate: _selectedDate,
currentDate: widget.currentDate,
maxDate: widget.maxDate,
minDate: widget.minDate,
currentDate:
DateUtils.dateOnly(widget.currentDate ?? DateTime.now()),
maxDate: DateUtils.dateOnly(widget.maxDate),
minDate: DateUtils.dateOnly(widget.minDate),
daysOfTheWeekTextStyle: widget.daysOfTheWeekTextStyle,
enabledCellsTextStyle: widget.enabledCellsTextStyle,
enabledCellsDecoration: widget.enabledCellsDecoration,
Expand Down Expand Up @@ -263,11 +286,13 @@ class _DatePickerState extends State<DatePicker> {
return Padding(
padding: widget.padding,
child: MonthPicker(
centerLeadingDate: widget.centerLeadingDate,
initialDate: _displayedDate,
selectedDate: _selectedDate,
currentDate: widget.currentDate,
maxDate: widget.maxDate,
minDate: widget.minDate,
currentDate:
DateUtils.dateOnly(widget.currentDate ?? DateTime.now()),
maxDate: DateUtils.dateOnly(widget.maxDate),
minDate: DateUtils.dateOnly(widget.minDate),
currentDateDecoration: widget.currentDateDecoration,
currentDateTextStyle: widget.currentDateTextStyle,
disbaledCellsDecoration: widget.disbaledCellsDecoration,
Expand Down Expand Up @@ -299,11 +324,13 @@ class _DatePickerState extends State<DatePicker> {
return Padding(
padding: widget.padding,
child: YearsPicker(
centerLeadingDate: widget.centerLeadingDate,
initialDate: _displayedDate,
selectedDate: _selectedDate,
currentDate: widget.currentDate,
maxDate: widget.maxDate,
minDate: widget.minDate,
currentDate:
DateUtils.dateOnly(widget.currentDate ?? DateTime.now()),
maxDate: DateUtils.dateOnly(widget.maxDate),
minDate: DateUtils.dateOnly(widget.minDate),
currentDateDecoration: widget.currentDateDecoration,
currentDateTextStyle: widget.currentDateTextStyle,
disbaledCellsDecoration: widget.disbaledCellsDecoration,
Expand Down
61 changes: 43 additions & 18 deletions lib/src/date/days_picker.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,16 @@ class DaysPicker extends StatefulWidget {
/// The optional [onDateSelected] callback will be called if provided when a date
/// is selected.
///
///
/// [maxDate] must be after or equal to [minDate].
///
/// [initialDate] and [selectedDate], if provided, must be between [maxDate] and [minDate]
/// or equal to one of them.
/// The [minDate] is the earliest allowable date. The [maxDate] is the latest
/// allowable date. [initialDate] and [selectedDate] must either fall between
/// these dates, or be equal to one of them.
///
/// The [currentDate] represents the current day (i.e. today). This
/// date will be highlighted in the day grid. If null, the date of
/// `DateTime.now()` will be used.
///
/// For each of these [DateTime] parameters, only
/// their dates are considered. Their time fields are ignored.
DaysPicker({
super.key,
required this.maxDate,
Expand All @@ -62,14 +63,16 @@ class DaysPicker extends StatefulWidget {
this.highlightColor,
this.splashColor,
this.splashRadius,
this.centerLeadingDate = false,
}) {
assert(!minDate.isAfter(maxDate), "minDate can't be after maxDate");
assert(
() {
if (initialDate == null) return true;
final init = DateTime(initialDate!.year, initialDate!.month);
final init =
DateTime(initialDate!.year, initialDate!.month, initialDate!.day);

final min = DateTime(minDate.year, minDate.month);
final min = DateTime(minDate.year, minDate.month, minDate.day);

return init.isAfter(min) || init.isAtSameMomentAs(min);
}(),
Expand All @@ -78,9 +81,10 @@ class DaysPicker extends StatefulWidget {
assert(
() {
if (initialDate == null) return true;
final init = DateTime(initialDate!.year, initialDate!.month);
final init =
DateTime(initialDate!.year, initialDate!.month, initialDate!.day);

final max = DateTime(maxDate.year, maxDate.month);
final max = DateTime(maxDate.year, maxDate.month, maxDate.day);
return init.isBefore(max) || init.isAtSameMomentAs(max);
}(),
'initialDate $initialDate must be on or before maxDate $maxDate.',
Expand All @@ -89,13 +93,19 @@ class DaysPicker extends StatefulWidget {

/// The date which will be displayed on first opening.
/// If not specified, the picker will default to `DateTime.now()` date.
///
/// Note that only dates are considered. time fields are ignored.
final DateTime? initialDate;

/// The date to which the picker will consider as current date. e.g (today).
/// If not specified, the picker will default to `DateTime.now()` date.
///
/// Note that only dates are considered. time fields are ignored.
final DateTime? currentDate;

/// The initially selected date when the picker is first opened.
///
/// Note that only dates are considered. time fields are ignored.
final DateTime? selectedDate;

/// Called when the user picks a date.
Expand All @@ -104,11 +114,15 @@ class DaysPicker extends StatefulWidget {
/// The earliest date the user is permitted to pick.
///
/// This date must be on or before the [maxDate].
///
/// Note that only dates are considered. time fields are ignored.
final DateTime minDate;

/// The latest date the user is permitted to pick.
///
/// This date must be on or after the [minDate].
///
/// Note that only dates are considered. time fields are ignored.
final DateTime maxDate;

/// Called when the user tap on the leading date.
Expand Down Expand Up @@ -195,6 +209,12 @@ class DaysPicker extends StatefulWidget {
/// The radius of the ink splash.
final double? splashRadius;

/// Centring the leading date. e.g:
///
/// < December 2023 >
///
final bool centerLeadingDate;

@override
State<DaysPicker> createState() => _DaysPickerState();
}
Expand All @@ -212,8 +232,10 @@ class _DaysPickerState extends State<DaysPicker> {

@override
void initState() {
_displayedMonth = widget.initialDate ?? DateUtils.dateOnly(DateTime.now());
_selectedDate = widget.selectedDate;
_displayedMonth = DateUtils.dateOnly(widget.initialDate ?? DateTime.now());
_selectedDate = widget.selectedDate != null
? DateUtils.dateOnly(widget.selectedDate!)
: null;
_pageController = PageController(
initialPage: DateUtils.monthDelta(widget.minDate, _displayedMonth!),
);
Expand All @@ -228,15 +250,17 @@ class _DaysPickerState extends State<DaysPicker> {
// if it changes.
if (oldWidget.initialDate != widget.initialDate) {
_displayedMonth =
widget.initialDate ?? DateUtils.dateOnly(DateTime.now());
DateUtils.dateOnly(widget.initialDate ?? DateTime.now());

_pageController.jumpToPage(
DateUtils.monthDelta(widget.minDate, _displayedMonth!),
);
}

if (oldWidget.selectedDate != widget.selectedDate) {
_selectedDate = widget.selectedDate;
_selectedDate = widget.selectedDate != null
? DateUtils.dateOnly(widget.selectedDate!)
: null;
}
super.didUpdateWidget(oldWidget);
}
Expand Down Expand Up @@ -356,6 +380,7 @@ class _DaysPickerState extends State<DaysPicker> {
mainAxisSize: MainAxisSize.min,
children: [
Header(
centerLeadingDate: widget.centerLeadingDate,
leadingDateTextStyle: leadingDateTextStyle,
slidersColor: slidersColor,
slidersSize: slidersSize,
Expand Down Expand Up @@ -386,8 +411,8 @@ class _DaysPickerState extends State<DaysPicker> {
},
),
const SizedBox(height: 10),
AnimatedContainer(
duration: const Duration(milliseconds: 200),
SizedBox(
key: ValueKey(maxHeight),
height: maxHeight,
child: PageView.builder(
scrollDirection: Axis.horizontal,
Expand All @@ -409,9 +434,9 @@ class _DaysPickerState extends State<DaysPicker> {
return DaysView(
key: ValueKey<DateTime>(month),
currentDate:
widget.currentDate ?? DateUtils.dateOnly(DateTime.now()),
minDate: widget.minDate,
maxDate: widget.maxDate,
DateUtils.dateOnly(widget.currentDate ?? DateTime.now()),
maxDate: DateUtils.dateOnly(widget.maxDate),
minDate: DateUtils.dateOnly(widget.minDate),
displayedMonth: month,
selectedDate: _selectedDate,
daysOfTheWeekTextStyle: daysOfTheWeekTextStyle,
Expand Down
Loading
Loading