Calendar In Flutter

Calender In Flutter :

Flutter tutorial provide new flutter application Calendar. This is calendar picker is display calendar weekly, monthly, single select, multiple select.

Screenshot :

Calendar In Flutter

Calendar In Flutter

Program :

    Container(
                  padding: EdgeInsets.all(0),
                  child: Calendarro(
                      displayMode: DisplayMode.WEEKS,
                      selectionMode: SelectionMode.SINGLE,
                      startDate: DateTime.now(),
                      //endDate: DateTime.now(),
                      endDate: DateUtils.getLastDayOfNextMonth(),
                      //weekdayLabelsRow: CustomWeekdayLabelsRow(), //Single Character day
                      selectedDate: DateTime.now(),
                      onTap: (date) {
                        setState(() {
                       
                        });
                      }),
                ),

calendar.dart

library calendarro;
import 'package:flutter/material.dart';
import 'calendarro_page.dart';
import 'date_utils.dart';
import 'default_day_tile_builder.dart';
import 'default_weekday_labels_row.dart';

abstract class DayTileBuilder {
  Widget build(BuildContext context, DateTime date, DateTimeCallback onTap);
}

enum DisplayMode { MONTHS, WEEKS }
enum SelectionMode { SINGLE, MULTI }

typedef void DateTimeCallback(DateTime datime);

class Calendarro extends StatefulWidget {
  DateTime startDate;
  DateTime endDate;
  DisplayMode displayMode;
  SelectionMode selectionMode;
  DayTileBuilder dayTileBuilder;
  Widget weekdayLabelsRow;
  DateTimeCallback onTap;

  DateTime selectedDate;
  List<DateTime> selectedDates;

  int startDayOffset;
  CalendarroState state;

  Calendarro(
      {Key key,
      this.startDate,
      this.endDate,
      this.displayMode = DisplayMode.WEEKS,
      this.dayTileBuilder,
      this.selectedDate,
      this.selectedDates,
      this.selectionMode = SelectionMode.SINGLE,
      this.onTap,
      this.weekdayLabelsRow})
      : super(key: key) {
    if (startDate == null) {
      startDate = DateUtils.getFirstDayOfCurrentMonth();
    }
    startDate = DateUtils.toMidnight(startDate);

    if (endDate == null) {
      endDate = DateUtils.getLastDayOfCurrentMonth();
    }
    endDate = DateUtils.toMidnight(endDate);
    startDayOffset = startDate.weekday - DateTime.monday;

    if (dayTileBuilder == null) {
      dayTileBuilder = DefaultDayTileBuilder();
    }

    if (weekdayLabelsRow == null) {
      weekdayLabelsRow = CalendarroWeekdayLabelsView();
    }

    if (selectedDates == null) {
      selectedDates = List();
    }
  }

  static CalendarroState of(BuildContext context) =>
      context.ancestorStateOfType(const TypeMatcher<CalendarroState>());

  @override
  CalendarroState createState() {
    state = CalendarroState(
        selectedDate: selectedDate, selectedDates: selectedDates);
    return state;
  }

  void setSelectedDate(DateTime date) {
    state.setSelectedDate(date);
  }

  void toggleDate(DateTime date) {
    state.toggleDateSelection(date);
  }

  void setCurrentDate(DateTime date) {
    state.setCurrentDate(date);
  }

  int getPositionOfDate(DateTime date) {
    int daysDifference =
        date.difference(DateUtils.toMidnight(startDate)).inDays;
    int weekendsDifference = ((daysDifference + startDate.weekday) / 7).toInt();
    var position = daysDifference - weekendsDifference * 2;
    return position;
  }

  int getPageForDate(DateTime date) {
    if (displayMode == DisplayMode.WEEKS) {
      int daysDifferenceFromStartDate = date.difference(startDate).inDays;
      int page = (daysDifferenceFromStartDate + startDayOffset) ~/ 7;
      return page;
    } else {
      var monthDifference = (date.year * 12 + date.month) -
          (startDate.year * 12 + startDate.month);
      return monthDifference;
    }
  }
}

class CalendarroState extends State<Calendarro> {
  DateTime selectedDate;
  List<DateTime> selectedDates;

  int pagesCount;
  PageView pageView;

  CalendarroState({this.selectedDate, this.selectedDates});

  @override
  void initState() {
    super.initState();

    if (selectedDate == null) {
      selectedDate = widget.startDate;
    }
  }

  void setSelectedDate(DateTime date) {
    setState(() {
      if (widget.selectionMode == SelectionMode.SINGLE) {
        selectedDate = date;
      } else {
        bool dateSelected = false;

        for (var i = selectedDates.length - 1; i >= 0; i--) {
          if (DateUtils.isSameDay(selectedDates[i], date)) {
            selectedDates.removeAt(i);
            dateSelected = true;
          }
        }

        if (!dateSelected) {
          selectedDates.add(date);
        }
      }
    });
  }

  void setCurrentDate(DateTime date) {
    setState(() {
      int page = widget.getPageForDate(date);
      pageView.controller.jumpToPage(page);
    });
  }

  @override
  Widget build(BuildContext context) {
    if (widget.displayMode == DisplayMode.WEEKS) {
      int lastPage = widget.getPageForDate(widget.endDate);
      pagesCount = lastPage + 1;
    } else {
      pagesCount = widget.endDate.month - widget.startDate.month + 1;
    }

    pageView = PageView.builder(
      itemBuilder: (context, position) => buildCalendarPage(position),
      itemCount: pagesCount,
      controller: PageController(
          initialPage:
              selectedDate != null ? widget.getPageForDate(selectedDate) : 0),
    );

    return Container(
        height: widget.displayMode == DisplayMode.WEEKS ? 60.0 : 260.0,
        child: pageView);
  }

  Widget buildCalendarPage(int position) {
    if (widget.displayMode == DisplayMode.WEEKS) {
      return buildCalendarPageInWeeksMode(position);
    } else {
      return buildCalendarPageInMonthsMode(position);
    }
    //DisplayMode == WEEKS
  }

  Widget buildCalendarPageInWeeksMode(int position) {
    DateTime pageStartDate;
    DateTime pageEndDate;

    if (position == 0) {
      pageStartDate = widget.startDate;
      pageEndDate =
          DateUtils.addDaysToDate(widget.startDate, 6 - widget.startDayOffset);
    } else if (position == pagesCount - 1) {
      pageStartDate = DateUtils.addDaysToDate(
          widget.startDate, 7 * position - widget.startDayOffset);
      pageEndDate = widget.endDate;
    } else {
      pageStartDate = DateUtils.addDaysToDate(
          widget.startDate, 7 * position - widget.startDayOffset);
      pageEndDate = DateUtils.addDaysToDate(
          widget.startDate, 7 * position + 6 - widget.startDayOffset);
    }

    return CalendarroPage(
        pageStartDate: pageStartDate,
        pageEndDate: pageEndDate,
        weekdayLabelsRow: widget.weekdayLabelsRow);
  }

  Widget buildCalendarPageInMonthsMode(int position) {
    DateTime pageStartDate;
    DateTime pageEndDate;

    if (position == 0) {
      pageStartDate = widget.startDate;
      DateTime nextMonthFirstDate =
          DateTime(widget.startDate.year, widget.startDate.month + 1, 1);
      pageEndDate = DateUtils.addDaysToDate(nextMonthFirstDate, -1);
    } else if (position == pagesCount - 1) {
      pageEndDate = widget.endDate;
      pageStartDate = DateTime(widget.endDate.year, widget.endDate.month, 1);
    } else {
      pageStartDate =
          DateTime(widget.startDate.year, widget.startDate.month + position, 1);
      DateTime nextMonthFirstDate = DateTime(
          widget.startDate.year, widget.startDate.month + position + 1, 1);
      pageEndDate = DateUtils.addDaysToDate(nextMonthFirstDate, -1);
      ;
    }

    return CalendarroPage(
      pageStartDate: pageStartDate,
      pageEndDate: pageEndDate,
      weekdayLabelsRow: widget.weekdayLabelsRow,
    );
  }

  bool isDateSelected(DateTime date) {
    if (widget.selectionMode == SelectionMode.MULTI) {
      return selectedDates.contains(date);
    } else {
      return DateUtils.isSameDay(selectedDate, date);
    }
  }

  void toggleDateSelection(DateTime date) {
    setState(() {
      for (var i = selectedDates.length - 1; i >= 0; i--) {
        if (DateUtils.isSameDay(selectedDates[i], date)) {
          selectedDates.removeAt(i);
          return;
        }
      }

      selectedDates.add(date);
    });
  }

  void update() {
    setState(() {});
  }
}

calendar_page.dart

import 'package:flutter/material.dart';

import 'calendarro.dart';
import 'date_utils.dart';

class CalendarroPage extends StatelessWidget {

  static final MAX_ROWS_COUNT = 6;

  DateTime pageStartDate;
  DateTime pageEndDate;
  Widget weekdayLabelsRow;

  int startDayOffset;

  CalendarroPage({this.pageStartDate, this.pageEndDate, this.weekdayLabelsRow}) {
    startDayOffset = pageStartDate.weekday - DateTime.monday;
  }

  @override
  Widget build(BuildContext context) {
    return Container(
        child: Column(
            children: buildRows(context),
            mainAxisSize: MainAxisSize.min
        )
    );
  }

  List<Widget> buildRows(BuildContext context) {
    List<Widget> rows = [];
    rows.add(weekdayLabelsRow);

    DateTime rowLastDayDate = DateUtils.addDaysToDate(pageStartDate, 6 - startDayOffset);
//    DateTime rowLastDayDate = pageStartDate.add(Duration(days: 6 - startDayOffset));

    if (pageEndDate.isAfter(rowLastDayDate)) {
      rows.add(Row(
          children: buildCalendarRow(context, pageStartDate, rowLastDayDate))
      );

      for (var i = 1; i < MAX_ROWS_COUNT; i++) {
        DateTime nextRowFirstDayDate = DateUtils.addDaysToDate(pageStartDate, 7 * i - startDayOffset);

        if (nextRowFirstDayDate.isAfter(pageEndDate)) {
          break;
        }

        DateTime nextRowLastDayDate = DateUtils.addDaysToDate(pageStartDate, 7 * i - startDayOffset + 6);


        if (nextRowLastDayDate.isAfter(pageEndDate)) {
          nextRowLastDayDate = pageEndDate;
        }

        rows.add(Row(
            children: buildCalendarRow(
                context, nextRowFirstDayDate, nextRowLastDayDate)));
      }
    } else {
      rows.add(Row(
          children: buildCalendarRow(context, pageStartDate, pageEndDate))
      );
    }

    return rows;
  }

  List<Widget> buildCalendarRow(
      BuildContext context, DateTime rowStartDate, DateTime rowEndDate) {
    List<Widget> items = [];

    DateTime currentDate = rowStartDate;
    for (int i = 0; i < 7; i++) {
      if (i + 1 >= rowStartDate.weekday && i + 1 <= rowEndDate.weekday) {
        CalendarroState calendarroState = Calendarro.of(context);
          Widget dayTile = calendarroState.widget.dayTileBuilder.build(context, currentDate, calendarroState.widget.onTap);
          items.add(dayTile);
        currentDate = currentDate.add(Duration(days: 1));
      } else {
        items.add(Expanded(
          child: Text(""),
        ));
      }
    }

    return items;
  }
}

date_utils.dart

class DateUtils {
  static DateTime toMidnight(DateTime dateTime) {
    return DateTime(dateTime.year, dateTime.month, dateTime.day);
  }

  static bool isWeekend(DateTime date) {
    return date.weekday == DateTime.saturday || date.weekday == DateTime.sunday;
  }

  static bool isToday(DateTime date) {
    var now = DateTime.now();
    return date.day == now.day && date.month == now.month && date.year == now.year;
  }

  static bool isPastDay(DateTime date) {
    var today = toMidnight(DateTime.now());
    return date.isBefore(today);
  }

  static DateTime addDaysToDate(DateTime date, int days) {
    DateTime newDate = date.add(Duration(days: days));

    if (date.hour != newDate.hour) {
      var hoursDifference = date.hour - newDate.hour;

      if (hoursDifference <= 3 && hoursDifference >= -3) {
        newDate = newDate.add(Duration(hours: hoursDifference));
      } else if (hoursDifference <= -21) {
        newDate = newDate.add(Duration(hours: 24 + hoursDifference));
      } else if (hoursDifference >= 21) {
        newDate = newDate.add(Duration(hours: hoursDifference - 24));
      }

    }
    return newDate;
  }

  static bool isSpecialPastDay(DateTime date) {
    return isPastDay(date) || (isToday(date) && DateTime.now().hour >= 12);
  }

  static DateTime getFirstDayOfCurrentMonth() {
    var dateTime = DateTime.now();
    dateTime = getFirstDayOfMonth(dateTime.month);
    return dateTime;
  }


  static DateTime getFirstDayOfMonth(int month) {
    var dateTime = DateTime.now();
    dateTime = DateTime(dateTime.year, month, 1);
    return dateTime;
  }

  static DateTime getFirstDayOfNextMonth() {
    var dateTime = getFirstDayOfCurrentMonth();
    dateTime = addDaysToDate(dateTime, 31);
    dateTime = DateTime(dateTime.year, dateTime.month, 1);
    return dateTime;
  }

  static DateTime getLastDayOfCurrentMonth() {
    return getFirstDayOfNextMonth().subtract(Duration(days: 1));
  }

  static DateTime getLastDayOfNextMonth() {
    var nextNextMonth = addDaysToDate(getFirstDayOfCurrentMonth(), 32 * 2);
    return DateTime(nextNextMonth.year, nextNextMonth.month, 1)
        .subtract(Duration(days: 1));
  }

  static bool isSameDay(DateTime date1, DateTime date2) {
    return date1.day == date2.day && date1.month == date2.month && date1.year == date2.year;
  }

  static bool isCurrentMonth(DateTime date) {
    var now = DateTime.now();
    return date.month == now.month && date.year == now.year;
  }
}

default_day_tile.dart

import 'package:flutter/material.dart';
import 'calendarro.dart';
import 'date_utils.dart';

class CalendarroDayItem extends StatelessWidget {
  CalendarroDayItem({this.date, this.calendarroState, this.onTap});

  DateTime date;
  CalendarroState calendarroState;
  DateTimeCallback onTap;

  @override
  Widget build(BuildContext context) {
    bool isWeekend = DateUtils.isWeekend(date);
    bool isToday = DateUtils.isToday(date);
    calendarroState = Calendarro.of(context);

    bool daySelected = calendarroState.isDateSelected(date);

    BoxDecoration boxDecoration;
    if (daySelected) {
      boxDecoration = BoxDecoration(color: Colors.deepOrangeAccent, shape: BoxShape.circle);
    } else if (isToday) {
      boxDecoration = BoxDecoration(
          border: Border.all(
            color: Colors.white,
            width: 1.0,
          ),
          shape: BoxShape.circle);
    }

    return Expanded(
        child: GestureDetector(
          child: Container(
              height: 40.0,
              decoration: boxDecoration,
              child: Center(
                  child: Text(
                    "${date.day}",
                    textAlign: TextAlign.center,
                    style: TextStyle(color: daySelected? Colors.white : Colors.grey),
                  ))),
          onTap: handleTap,
          behavior: HitTestBehavior.translucent,
        ));
  }

  void handleTap() {
    if (onTap != null) {
      onTap(date);
    }

    calendarroState.setSelectedDate(date);
    calendarroState.setCurrentDate(date);
  }
}

default_day_tile_builder.dart

import 'package:flutter/material.dart';
import 'calendarro.dart';
import 'default_day_tile.dart';

class DefaultDayTileBuilder extends DayTileBuilder {

  DefaultDayTileBuilder();

  @override
  Widget build(BuildContext context, DateTime date, DateTimeCallback onTap) {
    return CalendarroDayItem(date: date, calendarroState: Calendarro.of(context), onTap: onTap);
  }
}

default_weekday_labels_row.dart

import 'package:flutter/widgets.dart';

class CalendarroWeekdayLabelsView extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      children: <Widget>[
        Expanded(child: Text("Mon", textAlign: TextAlign.center)),
        Expanded(child: Text("Tue", textAlign: TextAlign.center)),
        Expanded(child: Text("Wed", textAlign: TextAlign.center)),
        Expanded(child: Text("Thu", textAlign: TextAlign.center)),
        Expanded(child: Text("Fri", textAlign: TextAlign.center)),
        Expanded(child: Text("Sat", textAlign: TextAlign.center)),
        Expanded(child: Text("Sun", textAlign: TextAlign.center)),
      ],
    );
  }
}

The flutter tutorial  is a website that bring you the latest and amazing resources of code. All the languages codes are included in this website. The languages like flutter, android, java,kotlin etc.with the help of this languages any user can develop the beautiful application

For more information about Flutter. visit www.fluttertutorial.in