calendar
unknown
dart
3 years ago
16 kB
2
Indexable
Never
import 'package:flutter/material.dart'; import 'components/model/calendar_model.dart'; enum CalendarViews { dates, months, year } class MyApp extends StatefulWidget { @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { int _currentPage = 0; final PageController _controller = PageController( initialPage: 999, ); DateTime? _currentDateTime; DateTime? _selectedDateTime; List<CalendarModel>? _sequentialDates; int? midYear; CalendarViews _currentView = CalendarViews.dates; final List<String> _weekDays = [ 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN' ]; final List<String> _monthNames = [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ]; List<int> _selectedItems = []; @override void initState() { super.initState(); final date = DateTime.now(); _currentDateTime = DateTime(date.year, date.month); _selectedDateTime = DateTime(date.year, date.month, date.day); WidgetsBinding.instance!.addPostFrameCallback((timeStamp) { setState(() => _getCalendar()); }); } @override void dispose() { super.dispose(); } onChanged(int index) { bool next = index > _currentPage; _currentPage = index; print("currentPage: ${_currentPage}"); print("next: ${next}"); print("index: ${index}"); if (_currentView == CalendarViews.dates) { setState(() => (next) ? _getNextMonth() : _getPrevMonth()); } else if (_currentView == CalendarViews.year) { if (next) { midYear = (midYear == null) ? _currentDateTime!.year + 9 : midYear! + 9; } else { midYear = (midYear == null) ? _currentDateTime!.year - 9 : midYear! - 9; } setState(() {}); } } @override Widget build(BuildContext context) { return Scaffold( body: SafeArea( child: Center( child: Column( children: [ /// Dropdown Align( alignment: Alignment.centerRight, child: DropdownButtonHideUnderline( child: DropdownButton<String>( focusColor: Theme.of(context).primaryColor, value: _monthNames[_currentDateTime!.month - 1], /* value: changeMonthIndex .state[ref.watch(changeMontIndexWithSlider)],*/ //value: changeMonthIndex.state[ref.watch(selectedIndex)], icon: const Icon(Icons.keyboard_arrow_down), items: _monthNames.map<DropdownMenuItem<String>>((String value) { return DropdownMenuItem<String>( value: value, child: Text( value, style: TextStyle( fontSize: 18, color: Theme.of(context).accentColor), )); }).toList(), onChanged: (value) { setState(() { _monthNames[_currentDateTime!.month - 1] = value!; }); // ref.read(changeMonth.state).state = value as List<String>; //_chosenValue = value!; /*setState(() { _chosenValue = value; });*/ }, )), ), /// Middle month year InkWell( onTap: () => setState(() => _currentView = CalendarViews.months), child: Center( child: Text( '${_monthNames[_currentDateTime!.month - 1]} ${_currentDateTime!.year}', style: TextStyle( color: Theme.of(context).accentColor, fontSize: 18, fontWeight: FontWeight.w700), ), ), ), const SizedBox( height: 50, ), /// Date List SizedBox( height: 40, child: GridView.builder( gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 7), itemCount: _weekDays.length, itemBuilder: (context, index) { return Padding( padding: EdgeInsets.symmetric(horizontal: 10), child: FittedBox( fit: BoxFit.scaleDown, child: Text(_weekDays[index])), ); }), ), Expanded( child: PageView.builder( controller: _controller, scrollDirection: Axis.horizontal, physics: const BouncingScrollPhysics(), onPageChanged: onChanged, itemBuilder: (BuildContext context, int index) { return Container( margin: const EdgeInsets.all(15), height: MediaQuery.of(context).size.height, //height: MediaQuery.of(context).size.height * 0.6, child: (_currentView == CalendarViews.dates) ? _datesView() : (_currentView == CalendarViews.months) ? _showMonthsList() : _yearsView( midYear ?? _currentDateTime!.year)); }, ), ), ], ), ), ), ); } // dates view Widget _datesView() { return _calendarBody(); } // next / prev month buttons Widget _toggleBtn(bool next) { return InkWell( onTap: () { if (_currentView == CalendarViews.dates) { setState(() => (next) ? _getNextMonth() : _getPrevMonth()); } else if (_currentView == CalendarViews.year) { if (next) { midYear = (midYear == null) ? _currentDateTime!.year + 9 : midYear! + 9; } else { midYear = (midYear == null) ? _currentDateTime!.year - 9 : midYear! - 9; } setState(() {}); } }, child: Container( alignment: Alignment.center, width: 50, height: 50, decoration: BoxDecoration( borderRadius: BorderRadius.circular(25), border: Border.all(color: Theme.of(context).primaryColor), boxShadow: [ BoxShadow( color: Colors.white.withOpacity(0.5), offset: const Offset(3, 3), blurRadius: 3, spreadRadius: 0, ), ], gradient: LinearGradient( colors: [Colors.black, Colors.black.withOpacity(0.1)], stops: [0.5, 1], begin: Alignment.bottomRight, end: Alignment.topLeft, )), child: Icon( (next) ? Icons.arrow_forward_ios : Icons.arrow_back_ios, color: Colors.white, ), )); } // calendar Widget _calendarBody() { if (_sequentialDates == null) return Container(); return GridView.builder( shrinkWrap: true, padding: EdgeInsets.zero, itemCount: _sequentialDates!.length + 7, gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( mainAxisSpacing: 20, crossAxisCount: 7, crossAxisSpacing: 20, ), itemBuilder: (context, index) { if (index < 7) return Text(''); if (_sequentialDates![index - 7].date == _selectedDateTime) { /*if (_selectedItems.contains(index)) { setState(() { _selectedItems.removeWhere((val) => val == index); }); } else { setState(() { _selectedItems.add(index); }); }*/ return _selector( _sequentialDates![index - 7],index, ); } return _calendarDates(_sequentialDates![index - 7]); }, ); } // calendar header Widget _weekDayTitle(int index) { return Text( _weekDays[index], style: TextStyle( color: Theme.of(context).cardColor, fontSize: 12, fontWeight: FontWeight.w500, ), ); } // calendar element Widget _calendarDates(CalendarModel calendarDate) { return InkWell( onTap: () { if (_selectedDateTime != calendarDate.date) { if (calendarDate.nextMonth) { _getNextMonth(); } else if (calendarDate.prevMonth) { _getPrevMonth(); } setState(() => _selectedDateTime = calendarDate.date!); } }, child: Column( mainAxisSize: MainAxisSize.min, children: [ const Spacer(), Container( height: 5, width: 5, decoration: BoxDecoration( shape: BoxShape.circle, color: calendarDate.thisMonth ? Theme.of(context).accentColor : Theme.of(context).cardColor.withOpacity(0.5)), ), const Spacer(), Text( '${calendarDate.date!.day}', style: TextStyle( color: (calendarDate.thisMonth) ? Theme.of(context).accentColor //(calendarDate.date!.weekday == DateTime.sunday) ? Colors.black : Colors.white : Theme.of(context).cardColor.withOpacity(0.5) //(calendarDate.date!.weekday == DateTime.sunday) ? Colors.yellow.withOpacity(0.5) : Colors.white.withOpacity(0.5), ), ), const Spacer(), ], ), ); } // date selector Widget _selector(CalendarModel calendarDate,int index) { return GestureDetector( onTap: (){ if (_sequentialDates!.contains(index)) { setState(() { _sequentialDates!.removeWhere((val) => val == index); }); } else { setState(() { _selectedItems.add(index); }); } }, child: Container( width: 30, height: 30, decoration: BoxDecoration( color: calendarDate == _sequentialDates ? Theme.of(context).secondaryHeaderColor : Theme.of(context).buttonColor, borderRadius: BorderRadius.circular(10), ), child: Container( decoration: BoxDecoration( //color: Colors.white.withOpacity(0.9), borderRadius: BorderRadius.circular(10), ), child: Column( children: [ const Spacer(), Container( height: 5, width: 5, decoration: BoxDecoration( shape: BoxShape.circle, color: calendarDate == _sequentialDates ? Theme.of(context).accentColor : Theme.of(context).primaryColor), ), const Spacer(), Text( '${calendarDate.date!.day}', style: TextStyle( color: calendarDate == _sequentialDates ? Colors.black : Colors.white, fontWeight: FontWeight.w700), ), const Spacer(), ], ), ), ), ); } // get next month calendar void _getNextMonth() { if (_currentDateTime!.month == 12) { _currentDateTime = DateTime(_currentDateTime!.year + 1, 1); } else { _currentDateTime = DateTime(_currentDateTime!.year, _currentDateTime!.month + 1); } _getCalendar(); } // get previous month calendar void _getPrevMonth() { if (_currentDateTime!.month == 1) { _currentDateTime = DateTime(_currentDateTime!.year - 1, 12); } else { _currentDateTime = DateTime(_currentDateTime!.year, _currentDateTime!.month - 1); } _getCalendar(); } // get calendar for current month void _getCalendar() { _sequentialDates = CustomCalendar().getMonthCalendar( _currentDateTime!.month, _currentDateTime!.year, startWeekDay: StartWeekDay.monday); } // show months list Widget _showMonthsList() { return Column( children: <Widget>[ InkWell( onTap: () => setState(() => _currentView = CalendarViews.year), child: Padding( padding: const EdgeInsets.all(20.0), child: Text( '${_currentDateTime!.year}', style: const TextStyle( fontSize: 18, fontWeight: FontWeight.w700, color: Colors.black), ), ), ), const Divider( color: Colors.white, ), Expanded( child: ListView.builder( padding: EdgeInsets.zero, itemCount: _monthNames.length, itemBuilder: (context, index) => ListTile( onTap: () { _currentDateTime = DateTime(_currentDateTime!.year, index + 1); _getCalendar(); setState(() => _currentView = CalendarViews.dates); }, title: Center( child: Text( _monthNames[index], style: TextStyle( fontSize: 18, color: (index == _currentDateTime!.month - 1) ? Colors.blueAccent : Colors.black), ), ), ), ), ), ], ); } // years list views Widget _yearsView(int midYear) { return Column( children: <Widget>[ Row( children: <Widget>[ _toggleBtn(false), const Spacer(), _toggleBtn(true), ], ), Expanded( child: GridView.builder( shrinkWrap: true, itemCount: 9, physics: const NeverScrollableScrollPhysics(), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, ), itemBuilder: (context, index) { int thisYear; if (index < 4) { thisYear = midYear - (4 - index); } else if (index > 4) { thisYear = midYear + (index - 4); } else { thisYear = midYear; } return ListTile( onTap: () { _currentDateTime = DateTime(thisYear, _currentDateTime!.month); _getCalendar(); setState(() => _currentView = CalendarViews.months); }, title: Text( '$thisYear', style: TextStyle( fontSize: 18, color: (thisYear == _currentDateTime!.year) ? Colors.pink : Colors.black), ), ); }), ), ], ); } }