Skip to content
Open
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
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ Flutter Date Picker Library that provides a calendar as a horizontal timeline.
<img src="https://raw.githubusercontent.com/iamvivekkaushik/DatePickerTimelineFlutter/master/screenshots/demo.gif?raw=true"/>
</p>

<p>
<img src="https://raw.githubusercontent.com/tanmaypandharipande/DatePickerTimelineFlutter/master/screenshots/monthDatePicker.png?raw=true"/>
</p>

## How To Use

Import the following package in your dart file
Expand All @@ -31,6 +35,7 @@ Column(
initialSelectedDate: DateTime.now(),
selectionColor: Colors.black,
selectedTextColor: Colors.white,
// timelineType: TimelineType.MONTH,
onDateChange: (date) {
// New date selected
setState(() {
Expand All @@ -45,22 +50,23 @@ Column(
##### Constructor:

```dart
DatePicker(
this.startDate, {
DatePicker(this.startDate, {
Key key,
this.width = 60,
this.height = 80,
this.controller,
this.monthTextStyle = defaultMonthTextStyle,
this.dayTextStyle = defaultDayTextStyle,
this.dateTextStyle = defaultDateTextStyle,
this.yearTextStyle = defaultYearTextStyle,
this.selectedTextColor = Colors.white,
this.selectionColor = AppColors.defaultSelectionColor,
this.initialSelectedDate,
this.daysCount = 500,
this.onDateChange,
this.locale = "en_US",
}) : super(key: key);
this.timelineType = TimelineType.DAY
}) : super(key: key);
```

Author
Expand Down
1 change: 1 addition & 0 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ class _MyHomePageState extends State<MyHomePage> {
initialSelectedDate: DateTime.now(),
selectionColor: Colors.black,
selectedTextColor: Colors.white,
// timelineType: TimelineType.MONTH,
onDateChange: (date) {
// New date selected
setState(() {
Expand Down
1 change: 1 addition & 0 deletions lib/date_picker_timeline.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
library date_picker_timeline;

export 'date_picker_widget.dart';
export 'timelineType.dart';
108 changes: 92 additions & 16 deletions lib/date_picker_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import 'package:date_picker_timeline/date_widget.dart';
import 'package:date_picker_timeline/extra/color.dart';
import 'package:date_picker_timeline/extra/style.dart';
import 'package:date_picker_timeline/gestures/tap.dart';
import 'package:date_picker_timeline/month_widget.dart';
import 'package:date_picker_timeline/timelineType.dart';
import 'package:flutter/material.dart';
import 'package:intl/date_symbol_data_local.dart';

Expand Down Expand Up @@ -34,6 +36,9 @@ class DatePicker extends StatefulWidget {
/// TextStyle for the date Value
final TextStyle dateTextStyle;

/// TextStyle for the year Value
final TextStyle yearTextStyle;

/// Current Selected Date
final DateTime initialSelectedDate;

Expand All @@ -47,21 +52,27 @@ class DatePicker extends StatefulWidget {
/// Locale for the calendar default: en_us
final String locale;

DatePicker(
this.startDate, {
/// Setting the TimelineType
/// TimelineType.DAY & TimelineType.MONTH
/// Default is TimelineType.DAY
final TimelineType timelineType;

DatePicker(this.startDate, {
Key key,
this.width = 60,
this.height = 80,
this.controller,
this.monthTextStyle = defaultMonthTextStyle,
this.dayTextStyle = defaultDayTextStyle,
this.dateTextStyle = defaultDateTextStyle,
this.yearTextStyle = defaultYearTextStyle,
this.selectedTextColor = Colors.white,
this.selectionColor = AppColors.defaultSelectionColor,
this.initialSelectedDate,
this.daysCount = 500,
this.onDateChange,
this.locale = "en_US",
this.timelineType = TimelineType.DAY
}) : super(key: key);

@override
Expand All @@ -76,10 +87,16 @@ class _DatePickerState extends State<DatePicker> {
TextStyle selectedDateStyle;
TextStyle selectedMonthStyle;
TextStyle selectedDayStyle;
TextStyle selectedYearStyle;
//For Creation of month data
DateTime _monthStartDate;
int _monthDayCount;
List<DateTime> monthList;
//

@override
void initState() {
// Init the calendar locale
monthList = new List();
initializeDateFormatting(widget.locale, null);
// Set initial Values
_currentDate = widget.initialSelectedDate;
Expand All @@ -91,7 +108,11 @@ class _DatePickerState extends State<DatePicker> {
this.selectedDateStyle = createTextStyle(widget.dateTextStyle);
this.selectedMonthStyle = createTextStyle(widget.monthTextStyle);
this.selectedDayStyle = createTextStyle(widget.dayTextStyle);

this.selectedYearStyle = createTextStyle(widget.yearTextStyle);
WidgetsBinding.instance.addPostFrameCallback((_) async {
//Creating month data
await monthDataCreation();
});
super.initState();
}

Expand All @@ -111,9 +132,23 @@ class _DatePickerState extends State<DatePicker> {
}
}

///Creating month data on basis of daysCount parameter passed
///Selected month will give First Day of the month on selected.
monthDataCreation() async {
_monthStartDate = widget.startDate;
_monthDayCount = 0;
setState(() {
while (_monthDayCount < widget.daysCount) {
monthList.add(DateTime(_monthStartDate.year, _monthStartDate.month, 01));
_monthStartDate = _monthStartDate.add(Duration(days: 31));
_monthDayCount++;
}
});
}

@override
Widget build(BuildContext context) {
return Container(
return widget.timelineType == TimelineType.DAY ? Container(
height: widget.height,
child: ListView.builder(
itemCount: widget.daysCount,
Expand All @@ -123,24 +158,57 @@ class _DatePickerState extends State<DatePicker> {
// get the date object based on the index position
// if widget.startDate is null then use the initialDateValue
DateTime date;
DateTime _date = widget.startDate.add(Duration(days: index));
date = new DateTime(_date.year, _date.month, _date.day);
bool isSelected = false;

// Check if this date is the one that is currently selected
bool isSelected = _currentDate != null? _compareDate(date, _currentDate) : false;
if (widget.timelineType == TimelineType.DAY) {
DateTime _date = widget.startDate.add(Duration(days: index));
date = new DateTime(_date.year, _date.month, _date.day);
// Check if this date is the one that is currently selected
isSelected = _compareDate(date, _currentDate);
}

// Return the Date Widget
return DateWidget(
date: date,
monthTextStyle:
isSelected ? selectedMonthStyle : widget.monthTextStyle,
isSelected ? selectedMonthStyle : widget.monthTextStyle,
dateTextStyle:
isSelected ? selectedDateStyle : widget.dateTextStyle,
isSelected ? selectedDateStyle : widget.dateTextStyle,
dayTextStyle: isSelected ? selectedDayStyle : widget.dayTextStyle,
width: widget.width,
locale: widget.locale,
selectionColor:
isSelected ? widget.selectionColor : Colors.transparent,
isSelected ? widget.selectionColor : Colors.transparent,
onDateSelected: (selectedDate) {
// A date is selected
if (widget.onDateChange != null) {
widget.onDateChange(selectedDate);
}
setState(() {
_currentDate = selectedDate;
});
},
);
},
),
) : Container(
height: widget.height,
child: ListView.builder(
itemCount: monthList.length,
scrollDirection: Axis.horizontal,
controller: _controller,
itemBuilder: (context, index) {
bool isSelected = _compareMonth(monthList[index], _currentDate);
// Return the Date Widget
return MonthWidget(
date: monthList[index],
monthTextStyle:
isSelected ? selectedMonthStyle : widget.monthTextStyle,
yearTextStyle: isSelected ? selectedYearStyle : widget.yearTextStyle,
width: widget.width,
locale: widget.locale,
selectionColor:
isSelected ? widget.selectionColor : Colors.transparent,
onDateSelected: (selectedDate) {
// A date is selected
if (widget.onDateChange != null) {
Expand All @@ -163,6 +231,12 @@ class _DatePickerState extends State<DatePicker> {
date1.month == date2.month &&
date1.year == date2.year;
}

/// Helper function to compare two dates (month & year)
/// Returns True if both dates(month & year) are the same
bool _compareMonth(DateTime date1, DateTime date2) {
return date1.month == date2.month && date1.year == date2.year;
}
}

class DatePickerController {
Expand All @@ -174,7 +248,7 @@ class DatePickerController {

void jumpToSelection() {
assert(_datePickerState != null,
'DatePickerController is not attached to any DatePicker View.');
'DatePickerController is not attached to any DatePicker View.');

// jump to the current Date
_datePickerState._controller
Expand All @@ -185,7 +259,7 @@ class DatePickerController {
void animateToSelection(
{duration = const Duration(milliseconds: 500), curve = Curves.linear}) {
assert(_datePickerState != null,
'DatePickerController is not attached to any DatePicker View.');
'DatePickerController is not attached to any DatePicker View.');

// animate to the current date
_datePickerState._controller.animateTo(
Expand All @@ -199,7 +273,7 @@ class DatePickerController {
void animateToDate(DateTime date,
{duration = const Duration(milliseconds: 500), curve = Curves.linear}) {
assert(_datePickerState != null,
'DatePickerController is not attached to any DatePicker View.');
'DatePickerController is not attached to any DatePicker View.');

_datePickerState._controller.animateTo(_calculateDateOffset(date),
duration: duration, curve: curve);
Expand All @@ -208,7 +282,9 @@ class DatePickerController {
/// Calculate the number of pixels that needs to be scrolled to go to the
/// date provided in the argument
double _calculateDateOffset(DateTime date) {
int offset = date.difference(_datePickerState.widget.startDate).inDays + 1;
int offset = date
.difference(_datePickerState.widget.startDate)
.inDays + 1;
return (offset * _datePickerState.widget.width) + (offset * 6);
}
}
1 change: 1 addition & 0 deletions lib/extra/dimen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ class Dimen {
static const double dateTextSize = 24;
static const double dayTextSize = 11;
static const double monthTextSize = 11;
static const double yearTextSize = 15;
}
7 changes: 7 additions & 0 deletions lib/extra/style.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,10 @@ const TextStyle defaultDayTextStyle = TextStyle(
fontSize: Dimen.dayTextSize,
fontWeight: FontWeight.w500,
);


const TextStyle defaultYearTextStyle = TextStyle(
color: AppColors.defaultDayColor,
fontSize: Dimen.yearTextSize,
fontWeight: FontWeight.w500,
);
58 changes: 58 additions & 0 deletions lib/month_widget.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import 'package:date_picker_timeline/gestures/tap.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';

class MonthWidget extends StatelessWidget {
final double width;
final DateTime date;
final TextStyle monthTextStyle,yearTextStyle;
final Color selectionColor;
final DateSelectionCallback onDateSelected;
final String locale;

MonthWidget(
{@required this.date,
@required this.monthTextStyle,
@required this.yearTextStyle,
@required this.selectionColor,
this.width,
this.onDateSelected,
this.locale,
});

@override
Widget build(BuildContext context) {
return InkWell(
child: Container(
width: width,
margin: EdgeInsets.all(3.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(8.0)),
color: selectionColor,
),
child: Padding(
padding: EdgeInsets.all(8),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: Text(new DateFormat("yyyy", locale).format(date).toUpperCase(), // Month
style: yearTextStyle),
),
Text(new DateFormat("MMM", locale).format(date).toUpperCase(), // Month
style: monthTextStyle),
],
),
),
),
onTap: () {
// Check if onDateSelected is not null
if (onDateSelected != null) {
// Call the onDateSelected Function
onDateSelected(this.date);
}
},
);
}
}
1 change: 1 addition & 0 deletions lib/timelineType.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
enum TimelineType { DAY, MONTH }
Binary file added screenshots/monthDatePicker.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.