Skip to content

Instantly share code, notes, and snippets.

@chaudharydeepanshu
Last active August 6, 2022 19:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chaudharydeepanshu/762d835c5b9acadd785ee9269294c1e6 to your computer and use it in GitHub Desktop.
Save chaudharydeepanshu/762d835c5b9acadd785ee9269294c1e6 to your computer and use it in GitHub Desktop.
Example-custom-calendar
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