Skip to content

Commit

Permalink
Merge pull request #12 from hasanmhallak/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
hasanmhallak committed Jan 14, 2024
2 parents de43179 + 2045bf6 commit 3d47df1
Show file tree
Hide file tree
Showing 22 changed files with 561 additions and 302 deletions.
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

0 comments on commit 3d47df1

Please sign in to comment.