-
-
Save BrianCraig/23b68df986ef6d1b84bdf46aeed9bbae to your computer and use it in GitHub Desktop.
data_grid_jank_example
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/material.dart'; | |
void main() { | |
runApp(const MyApp()); | |
} | |
class MyApp extends StatelessWidget { | |
const MyApp({Key? key}) : super(key: key); | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
theme: ThemeData.light( | |
useMaterial3: true, | |
), | |
darkTheme: ThemeData.dark( | |
useMaterial3: true, | |
), | |
themeMode: ThemeMode.system, | |
home: const Home(), | |
); | |
} | |
} | |
class Home extends StatefulWidget { | |
const Home({Key? key}) : super(key: key); | |
@override | |
State<Home> createState() => _HomeState(); | |
} | |
const int pages = 10000; | |
class _HomeState extends State<Home> { | |
late PageController _controller; | |
// This points always to the mid-element in _list | |
late int _initialIndex; | |
@override | |
void initState() { | |
super.initState(); | |
// Calculate mid. | |
_controller = | |
PageController(initialPage: pages ~/ 2, viewportFraction: 1); | |
} | |
@override | |
void dispose() { | |
_controller.dispose(); | |
super.dispose(); | |
} | |
List months = [ | |
'jan', | |
'feb', | |
'mar', | |
'apr', | |
'may', | |
'jun', | |
'jul', | |
'aug', | |
'sep', | |
'oct', | |
'nov', | |
'dec' | |
]; | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar( | |
elevation: 2, | |
title: const Text("Data Grid"), | |
), | |
body: PageView.builder( | |
controller: _controller, | |
itemCount: pages, | |
itemBuilder: (BuildContext context, int index) { | |
int relIndex = index - (pages ~/ 2); | |
return Column( | |
children: [ | |
Text(months[DateTime(2022, 8 + relIndex, 1).month - 1] + | |
" " + | |
DateTime(2022, 8 + relIndex, 1).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( | |
dataIndex: getDatesForACalendarMonthAsUTC( | |
dateTime: DateTime(2022, 8 + relIndex, 1))[i], | |
gridIndex: DateTime(2022, 8 + relIndex, 1), | |
); | |
}, | |
), | |
], | |
); | |
}), | |
); | |
} | |
} | |
class DataWidget extends StatelessWidget { | |
const DataWidget({Key? key, required this.dataIndex, required this.gridIndex}) | |
: super(key: key); | |
final DateTime dataIndex; | |
final DateTime gridIndex; | |
@override | |
Widget build(BuildContext context) { | |
return Row( | |
children: [ | |
const Expanded( | |
child: SizedBox(), | |
), | |
OutlinedButton( | |
style: OutlinedButton.styleFrom( | |
minimumSize: Size.zero, | |
padding: EdgeInsets.zero, | |
foregroundColor: Theme.of(context).colorScheme.onSurface, | |
tapTargetSize: MaterialTapTargetSize.shrinkWrap, | |
side: BorderSide.none, | |
shape: const RoundedRectangleBorder( | |
borderRadius: BorderRadius.all(Radius.circular(12)), | |
), | |
).copyWith(elevation: ButtonStyleButton.allOrNull(0.0)), | |
onPressed: dataIndex.month == gridIndex.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( | |
dataIndex.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 = | |
getLastDayOfAMonth(currentDateTime: currentDateTime); | |
List<DateTime> datesFirstToLastDayOfMonthAsUTC = | |
getDaysInBetweenIncludingStartEndDate( | |
startDateTime: firstDayOfMonthAsUTC, | |
endDateTime: lastDayOfMonthAsUTC); | |
calendarMonthDaysAsUTC = List.generate(datesFirstToLastDayOfMonthAsUTC.length, | |
(index) => datesFirstToLastDayOfMonthAsUTC[index]); | |
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))) { | |
// Converting back UTC date to Local date before inserting in list | |
// You can keep in UTC format depending on your case | |
if (startDateTime.isUtc) { | |
daysInFormat.add(i); | |
} else { | |
daysInFormat.add(DateTime(i.year, i.month, i.day)); | |
} | |
} | |
return daysInFormat; | |
} | |
DateTime getLastDayOfAMonth({required DateTime currentDateTime}) { | |
// Getting the 15th-day date of the month for the date provided | |
DateTime fifteenthDayOfMonth = | |
DateTime(currentDateTime.year, currentDateTime.month, 15); | |
// Converting the 15th-day date to UTC | |
// So that all things like DST don't affect subtraction and addition on date | |
DateTime twentiethDayOfMonthInUTC = fifteenthDayOfMonth.toUtc(); | |
// Getting a random date of next month by adding 20 days to twentiethDayOfMonthInUTC | |
// Adding number 20 to any month 15th-day will definitely give a next month date | |
DateTime nextMonthRandomDateInUTC = | |
twentiethDayOfMonthInUTC.add(const Duration(days: 20)); | |
DateTime nextMonthRandomDateZeroDayInUTC = DateTime.utc( | |
nextMonthRandomDateInUTC.year, nextMonthRandomDateInUTC.month, 0); | |
// Now getting the 0th day date of the next month | |
// This will give us the current month last date | |
DateTime nextMonthRandomDateZeroDayInLocal = DateTime( | |
nextMonthRandomDateInUTC.year, nextMonthRandomDateInUTC.month, 0); | |
DateTime lastDayOfAMonth; | |
if (currentDateTime.isUtc) { | |
lastDayOfAMonth = nextMonthRandomDateZeroDayInUTC; | |
} else { | |
lastDayOfAMonth = nextMonthRandomDateZeroDayInLocal; | |
} | |
return lastDayOfAMonth; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment