Last active
August 6, 2022 19:33
-
-
Save chaudharydeepanshu/762d835c5b9acadd785ee9269294c1e6 to your computer and use it in GitHub Desktop.
Example-custom-calendar
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/gestures.dart'; | |
import 'package:flutter/material.dart'; | |
void main() { | |
runApp(const MyApp()); | |
} | |
List months = [ | |
'jan', | |
'feb', | |
'mar', | |
'apr', | |
'may', | |
'jun', | |
'jul', | |
'aug', | |
'sep', | |
'oct', | |
'nov', | |
'dec' | |
]; | |
class MyApp extends StatelessWidget { | |
const MyApp({Key? key}) : super(key: key); | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
theme: ThemeData.light( | |
), | |
darkTheme: ThemeData.dark( | |
), | |
themeMode: ThemeMode.system, | |
home: const Home(), | |
); | |
} | |
} | |
class Home extends StatefulWidget { | |
const Home({Key? key}) : super(key: key); | |
@override | |
State<Home> createState() => _HomeState(); | |
} | |
class _HomeState extends State<Home> { | |
late PageController controller = PageController(initialPage: 300); | |
List<int> listOfIntegersFromStartToAndEndDateWithInitialAs0 = [ | |
for (var i = -300; i <= 300; i += 1) i | |
]; | |
@override | |
void dispose() { | |
controller.dispose(); | |
super.dispose(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar( | |
elevation: 2, | |
title: const Text("Data Grid"), | |
), | |
body: ScrollConfiguration( | |
behavior: ScrollConfiguration.of(context).copyWith( | |
dragDevices: { | |
PointerDeviceKind.mouse, | |
PointerDeviceKind.touch, | |
}, | |
), | |
child: PageView.custom( | |
// physics: const NeverScrollableScrollPhysics(), | |
controller: controller, | |
childrenDelegate: SliverChildBuilderDelegate( | |
(BuildContext context, int index) { | |
return KeepAlive( | |
data: DateTime.utc( | |
DateTime(2022, 8, 1).year, | |
DateTime(2022, 8, 1).month + | |
listOfIntegersFromStartToAndEndDateWithInitialAs0[ | |
index], | |
1), | |
key: ValueKey<int>( | |
listOfIntegersFromStartToAndEndDateWithInitialAs0[index]), | |
); | |
}, | |
childCount: | |
listOfIntegersFromStartToAndEndDateWithInitialAs0.length, | |
findChildIndexCallback: (Key key) { | |
final ValueKey<int> valueKey = key as ValueKey<int>; | |
final int data = valueKey.value; | |
return listOfIntegersFromStartToAndEndDateWithInitialAs0 | |
.indexOf(data); | |
}), | |
), | |
), | |
); | |
} | |
} | |
class KeepAlive extends StatefulWidget { | |
const KeepAlive({Key? key, required this.data}) : super(key: key); | |
final DateTime data; | |
@override | |
State<KeepAlive> createState() => _KeepAliveState(); | |
} | |
class _KeepAliveState extends State<KeepAlive> | |
with AutomaticKeepAliveClientMixin { | |
@override | |
bool get wantKeepAlive => true; | |
@override | |
Widget build(BuildContext context) { | |
super.build(context); | |
List<DateTime> allDatesOfCalendarMonth = | |
getDatesForACalendarMonthAsUTC(dateTime: widget.data); | |
return Column( | |
children: [ | |
Text(months[widget.data.month - 1] + " " + widget.data.year.toString()), | |
GridView.builder( | |
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( | |
childAspectRatio: 1, | |
crossAxisCount: 7, | |
mainAxisExtent: 40, | |
), | |
itemCount: 42, | |
// physics: const NeverScrollableScrollPhysics(), | |
shrinkWrap: true, | |
itemBuilder: (context, i) { | |
return DataWidget( | |
dataDateTime: allDatesOfCalendarMonth[i], | |
gridDateTime: widget.data, | |
); | |
}, | |
), | |
], | |
); | |
} | |
} | |
class DataWidget extends StatelessWidget { | |
const DataWidget( | |
{Key? key, required this.dataDateTime, required this.gridDateTime}) | |
: super(key: key); | |
final DateTime dataDateTime; | |
final DateTime gridDateTime; | |
@override | |
Widget build(BuildContext context) { | |
return Row( | |
children: [ | |
const Expanded( | |
child: SizedBox(), | |
), | |
OutlinedButton( | |
style: OutlinedButton.styleFrom( | |
minimumSize: Size.zero, | |
padding: EdgeInsets.zero, | |
tapTargetSize: MaterialTapTargetSize.shrinkWrap, | |
side: BorderSide.none, | |
shape: const RoundedRectangleBorder( | |
borderRadius: BorderRadius.all(Radius.circular(12)), | |
), | |
).copyWith(elevation: ButtonStyleButton.allOrNull(0.0)), | |
onPressed: dataDateTime.month == gridDateTime.month | |
? () { | |
//do something | |
} | |
: null, | |
child: SizedBox( | |
width: 40, | |
child: Container( | |
margin: const EdgeInsets.all(4.0), | |
child: Ink( | |
decoration: BoxDecoration( | |
border: Border.all( | |
color: Theme.of(context).dividerColor, width: 1), | |
borderRadius: const BorderRadius.all(Radius.circular(12)), | |
), | |
child: Center( | |
child: Text( | |
dataDateTime.day.toString(), | |
style: const TextStyle(), | |
), | |
), | |
), | |
), | |
), | |
), | |
const Expanded( | |
child: SizedBox(), | |
), | |
], | |
); | |
} | |
} | |
List<DateTime> getDatesForACalendarMonthAsUTC({required DateTime dateTime}) { | |
List<DateTime> calendarMonthDaysAsUTC = []; | |
DateTime currentDateTime = DateTime.utc(dateTime.year, dateTime.month, 1); | |
DateTime firstDayOfMonthAsUTC = | |
DateTime.utc(currentDateTime.year, currentDateTime.month, 1); | |
DateTime lastDayOfMonthAsUTC = | |
DateTime.utc(currentDateTime.year, currentDateTime.month + 1, 0); | |
List<DateTime> datesFirstToLastDayOfMonthAsUTC = | |
getDaysInBetweenIncludingStartEndDate( | |
startDateTime: firstDayOfMonthAsUTC, | |
endDateTime: lastDayOfMonthAsUTC); | |
calendarMonthDaysAsUTC = List.from(datesFirstToLastDayOfMonthAsUTC); | |
int firstDayOfMonthWeekDay = firstDayOfMonthAsUTC.weekday; | |
for (int i = 1; | |
i <= firstDayOfMonthWeekDay && firstDayOfMonthWeekDay != 7; | |
i++) { | |
calendarMonthDaysAsUTC.insert( | |
0, firstDayOfMonthAsUTC.subtract(Duration(days: i))); | |
} | |
int daysLeftAfterMonthEndDate = 42 - calendarMonthDaysAsUTC.length; | |
for (int i = 1; i <= daysLeftAfterMonthEndDate; i++) { | |
calendarMonthDaysAsUTC.add(lastDayOfMonthAsUTC.add(Duration(days: i))); | |
} | |
return calendarMonthDaysAsUTC; | |
} | |
List<DateTime> getDaysInBetweenIncludingStartEndDate( | |
{required DateTime startDateTime, required DateTime endDateTime}) { | |
// Converting dates provided to UTC | |
// So that all things like DST don't affect subtraction and addition on dates | |
DateTime startDateInUTC = | |
DateTime.utc(startDateTime.year, startDateTime.month, startDateTime.day); | |
DateTime endDateInUTC = | |
DateTime.utc(endDateTime.year, endDateTime.month, endDateTime.day); | |
// Created a list to hold all dates | |
List<DateTime> daysInFormat = []; | |
// Starting a loop with the initial value as the Start Date | |
// With an increment of 1 day on each loop | |
// With condition current value of loop is smaller than or same as end date | |
for (DateTime i = startDateInUTC; | |
i.isBefore(endDateInUTC) || i.isAtSameMomentAs(endDateInUTC); | |
i = i.add(const Duration(days: 1))) { | |
if (startDateTime.isUtc) { | |
daysInFormat.add(i); | |
} else { | |
daysInFormat.add(DateTime(i.year, i.month, i.day)); | |
} | |
} | |
return daysInFormat; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment