Highly customizable, feature-packed calendar widget for Flutter

Overview

TableCalendar

Pub Package Awesome Flutter

Highly customizable, feature-packed calendar widget for Flutter.

Image Image
TableCalendar with custom styles TableCalendar with custom builders

Features

  • Extensive, yet easy to use API
  • Preconfigured UI with customizable styling
  • Custom selective builders for unlimited UI design
  • Locale support
  • Range selection support
  • Multiple selection support
  • Dynamic events and holidays
  • Vertical autosizing - fit the content, or fill the viewport
  • Multiple calendar formats (month, two weeks, week)
  • Horizontal swipe boundaries (first day, last day)

Usage

Make sure to check out examples and API docs for more details.

Installation

Add the following line to pubspec.yaml:

dependencies:
  table_calendar: ^3.0.3

Basic setup

The complete example is available here.

TableCalendar requires you to provide firstDay, lastDay and focusedDay:

  • firstDay is the first available day for the calendar. Users will not be able to access days before it.
  • lastDay is the last available day for the calendar. Users will not be able to access days after it.
  • focusedDay is the currently targeted day. Use this property to determine which month should be currently visible.
TableCalendar(
  firstDay: DateTime.utc(2010, 10, 16),
  lastDay: DateTime.utc(2030, 3, 14),
  focusedDay: DateTime.now(),
);

Adding interactivity

You will surely notice that previously set up calendar widget isn't quite interactive - you can only swipe it horizontally, to change the currently visible month. While it may be sufficient in certain situations, you can easily bring it to life by specifying a couple of callbacks.

Adding the following code to the calendar widget will allow it to respond to user's taps, marking the tapped day as selected:

selectedDayPredicate: (day) {
  return isSameDay(_selectedDay, day);
},
onDaySelected: (selectedDay, focusedDay) {
  setState(() {
    _selectedDay = selectedDay;
    _focusedDay = focusedDay; // update `_focusedDay` here as well
  });
},

In order to dynamically update visible calendar format, add those lines to the widget:

calendarFormat: _calendarFormat,
onFormatChanged: (format) {
  setState(() {
    _calendarFormat = format;
  });
},

Those two changes will make the calendar interactive and responsive to user's input.

Updating focusedDay

Setting focusedDay to a static value means that whenever TableCalendar widget rebuilds, it will use that specific focusedDay. You can quickly test it by using hot reload: set focusedDay to DateTime.now(), swipe to next month and trigger a hot reload - the calendar will "reset" to its initial state. To prevent this from happening, you should store and update focusedDay whenever any callback exposes it.

Add this one callback to complete the basic setup:

onPageChanged: (focusedDay) {
  _focusedDay = focusedDay;
},

It is worth noting that you don't need to call setState() inside onPageChanged() callback. You should just update the stored value, so that if the widget gets rebuilt later on, it will use the proper focusedDay.

The complete example is available here. You can find other examples here.

Events

The complete example is available here.

You can supply custom events to TableCalendar widget. To do so, use eventLoader property - you will be given a DateTime object, to which you need to assign a list of events.

eventLoader: (day) {
  return _getEventsForDay(day);
},

_getEventsForDay() can be of any implementation. For example, a Map<DateTime, List<T>> can be used:

List<Event> _getEventsForDay(DateTime day) {
  return events[day] ?? [];
}

One thing worth remembering is that DateTime objects consist of both date and time parts. In many cases this time part is redundant for calendar related aspects.

If you decide to use a Map, I suggest making it a LinkedHashMap - this will allow you to override equality comparison for two DateTime objects, comparing them just by their date parts:

final events = LinkedHashMap(
  equals: isSameDay,
  hashCode: getHashCode,
)..addAll(eventSource);

Cyclic events

eventLoader allows you to easily add events that repeat in a pattern. For example, this will add an event to every Monday:

eventLoader: (day) {
  if (day.weekday == DateTime.monday) {
    return [Event('Cyclic event')];
  }

  return [];
},

Events selected on tap

Often times having a sublist of events that are selected by tapping on a day is desired. You can achieve that by using the same method you provided to eventLoader inside of onDaySelected callback:

void _onDaySelected(DateTime selectedDay, DateTime focusedDay) {
  if (!isSameDay(_selectedDay, selectedDay)) {
    setState(() {
      _focusedDay = focusedDay;
      _selectedDay = selectedDay;
      _selectedEvents = _getEventsForDay(selectedDay);
    });
  }
}

The complete example is available here.

Custom UI with CalendarBuilders

To customize the UI with your own widgets, use CalendarBuilders. Each builder can be used to selectively override the UI, allowing you to implement highly specific designs with minimal hassle.

You can return null from any builder to use the default style. For example, the following snippet will override only the Sunday's day of the week label (Sun), leaving other dow labels unchanged:

calendarBuilders: CalendarBuilders(
  dowBuilder: (context, day) {
    if (day.weekday == DateTime.sunday) {
      final text = DateFormat.E().format(day);

      return Center(
        child: Text(
          text,
          style: TextStyle(color: Colors.red),
        ),
      );
    }
  },
),

Locale

To display the calendar in desired language, use locale property. If you don't specify it, a default locale will be used.

Initialization

Before you can use a locale, you might need to initialize date formatting.

A simple way of doing it is as follows:

  • First of all, add intl package to your pubspec.yaml file
  • Then make modifications to your main():
import 'package:intl/date_symbol_data_local.dart';

void main() {
  initializeDateFormatting().then((_) => runApp(MyApp()));
}

After those two steps your app should be ready to use TableCalendar with different languages.

Specifying a language

To specify a language, simply pass it as a String code to locale property.

For example, this will make TableCalendar use Polish language:

TableCalendar(
  locale: 'pl_PL',
),
Image Image Image Image
'en_US' 'pl_PL' 'fr_FR' 'zh_CN'

Note, that if you want to change the language of FormatButton's text, you have to do this yourself. Use availableCalendarFormats property and pass the translated Strings there. Use i18n method of your choice.

You can also hide the button altogether by setting formatButtonVisible to false.

Comments
  • Feature Request : Events can be updated for each month

    Feature Request : Events can be updated for each month

    Thanks for such an awesome library. Can we have provision to update the events map, based on the month selected. Typically on load of each month, we send a request to server to get the events for that month. I tried updating the _events on each request's result, but the event markers are not reflecting as the controller is still referring to the previous events map.

    opened by pvsvamsi 33
  • Avoid blank space when swipping between two months

    Avoid blank space when swipping between two months

    This is a great project! But is it possible to reduce the time between 2 months when we swipe horizontally ? I would like to avoid the "blank" space between the two months.

    opened by adriende 29
  • [FEAT] - Disable navigation when selecting invisible days in the next or previous month

    [FEAT] - Disable navigation when selecting invisible days in the next or previous month

    Hi, great work with this project!

    Would it be possible to disable the navigation to the next/previous month when a date in the next/previous month is selected?

    As far as I can see the setSelectedDay method on the CalendarController always updates the visible days via _updateVisibleDays.

    https://github.com/aleksanderwozniak/table_calendar/blob/2cd1c7cabc3025bd227ce8cc2a32075d942a5df6/lib/src/calendar_controller.dart#L229-L233

    Perhaps we could supply the formats that this animation is enabled for? Defaulting to the current implementaton, which would be all except CalendarFormat.twoWeeks? Something similar to:

     void _updateVisibleDays(bool isProgrammatic) { 
       if (!navigateInvisibleDaysForFormats.any((x) => x == calendarFormat)  || isProgrammatic) { 
         _visibleDays.value = _getVisibleDays(); 
       } 
     } 
    
    opened by royston-c 21
  • Mode week event error.

    Mode week event error.

    When the calendar is in week mode, if I click on the 29th or 30th (if they are on the 1st and 2nd day each week), events from days 1 (Tuesday) through 5 (Saturday), next month, disappear.

    In month mode this does not happen as no two month events appear at the same time.

    opened by MarceloRab 16
  • Holidays not displaying

    Holidays not displaying

    Hi,

    I have changed the holiday years to 2020, but nothing appears when using the builder version.

    final Map<DateTime, List> _holidays = {
      DateTime(2020, 1, 1): ['New Year\'s Day'],
      DateTime(2020, 1, 6): ['Epiphany'],
      DateTime(2020, 2, 14): ['Valentine\'s Day'],
      DateTime(2020, 4, 21): ['Easter Sunday'],
      DateTime(2020, 4, 22): ['Easter Monday'],
    };
    
      Widget _buildHolidaysMarker() {
        return Icon(
          Icons.cake,
          size: 20.0,
          color: Colors.lightGreenAccent,
        );
      }
    

    image

    opened by KrunchMuffin 15
  • How to make today's list automatically show on the screen instead of tap the day to show it?

    How to make today's list automatically show on the screen instead of tap the day to show it?

    Hi, I have been working a lot trying to figure out how to use Table Calendar, right not I can add list or event to the calendar and on each day it will show dots, but everytime when I first open the calendar screen, it only show a calendar with dots below the date, but not showing the list, only if I tap on the day, it will show. Here is part of the code: onDaySelected: (date, events) { setState(() { _selectedList = _selectedDayEvents; }); }, And I can see today is the initial selectedDay, so today should be selected, but I can not automatically see today's list unless I tap on it. Is it designed this way? is there way to change?

    Any help is appreciated, Thank you!

    Lu

    opened by lutang123 14
  • Create event example

    Create event example

    Examples are great but since I moved to new version lots of things changed and I'm having different issues trying to refactor my code.

    Can you provide a quick example for events creation?

    opened by erperejildo 13
  • Locale 'ru_RU' doesn't work and throw an error. InitializeDateFormatting has beed used.

    Locale 'ru_RU' doesn't work and throw an error. InitializeDateFormatting has beed used.

    @aleksanderwozniak, Russian locale haven't work. I've done all by instruction. I found samples of code for Portuguese and implemented it and It works. But when I try to use Russian or Ukrainian or Belorussia it wont. I've even try Iraq and its work) but not with 'ru_RU' Screenshot 2021-03-14 at 17 35 38 Screenshot 2021-03-14 at 17 36 22 Screenshot 2021-03-14 at 17 36 46

    Originally posted by @KrillioSokolov in https://github.com/aleksanderwozniak/table_calendar/issues/417#issuecomment-798928612

    opened by KrillioSokolov 13
  • Widget state does not persist

    Widget state does not persist

    I need to switch screen layouts dynamically, conditionally showing the calendar widget. My problem is that the current month is reset to initialSelectedDay every time the widget shows. I'd think that it should respect the 'CalendarController.focusedDay` field since the controller instance is reused? Is it a bug?

    opened by duzenko 12
  • Bring CalendarController inside the plugin and expose it through callbacks

    Bring CalendarController inside the plugin and expose it through callbacks

    Breaking change that will require a major version bump. There is a big problem in the current architecture of the package. Two separate objects: TableCalendar and CalendarController. The state of TableCalendar completely depends on the state of CalendarController but users are responsible for instantiating each of these objects separately of one another themselves. This breaks encapsulation principle of object oriented design and makes the package difficult to use. If users want 3 calendars, they must instantiate 3 calendarcontroller, 3 tablecalendar and map the state of each calendar controller to the correct state of the specific tablecalendar that maps to that calendarcontroller. Presumably CalendarController was created for abstraction and/or to have TableCalendar be a smaller object. However the way it was implemented was causing significant problems with both hot reload and statefulness. This PR resolves those issues. Users no longer need to instantiate their own CalendarController. CalendarController is now inside of TableCalendar and instantiation occurs automatically. If the user needs to access the state of CalendarController for the builders, it is exposed as parameters.

    Fixes #243 Fixes #248

    Let me know if I missed anything.

    opened by shamilovtim 12
  • Wrong calendar format

    Wrong calendar format

    I'm using the table calendar, and i tried to set the calendar format to month, but what i got is: image

    I set to "Week" and the button display Month, and when i try set the calendar format from calendar controller (in the first load), i got the error: The setter 'value=' was called on null. Receiver: null Tried calling: value=Instance of 'CalendarFormat'

    I can't set the calendar format...

    opened by lucas-sesti 11
  • TableBorder doesn't cut background color corners when rounded

    TableBorder doesn't cut background color corners when rounded

    Description Calendar Style doesn't cut corners when TableBorder is circular. Maybe some clipBehavior is needed.
    That looks my calendarStyle:

    calendarStyle: CalendarStyle(
              selectedDecoration: const BoxDecoration(color: AppColors.orange),
              defaultDecoration: const BoxDecoration(color: AppColors.inputFillAlpineGoat),
              weekendDecoration: const BoxDecoration(color: AppColors.inputFillAlpineGoat),
              outsideDaysVisible: false,
              isTodayHighlighted: false,
              cellMargin: EdgeInsets.zero,
              selectedTextStyle: h500TextStyle.copyWith(fontSize: 18.sp, color: AppColors.white),
              defaultTextStyle: h500TextStyle.copyWith(fontSize: 18.sp, color: AppColors.black),
              weekendTextStyle: h500TextStyle.copyWith(fontSize: 18.sp, color: AppColors.black),
              tableBorder: TableBorder.all(
                borderRadius: BorderRadius.circular(12.h),
                color: AppColors.neutralGray,
                width: 1.24.w,
              ),
            ),
    

    Screenshots Zrzut ekranu 2023-01-4 o 11 01 29

    bug 
    opened by radeckid 0
  • Not compatible with Intl 0.18.0

    Not compatible with Intl 0.18.0

    Hello

    If I update Intl package to the new version 0.18.0 I got an error.

    Because table_calendar 3.0.8 depends on intl ^0.17.0 and no versions of table_calendar match >3.0.8 <4.0.0, table_calendar ^3.0.8 requires intl ^0.17.0.

    Thanks

    bug 
    opened by Paroca72 0
  • centring the Selected day

    centring the Selected day

    Is your feature request related to a problem? Please describe. Yes, I would like to keep the "selectedDay" to the center whenever a user changes it

    Describe the solution you'd like Whener a user chooses a different day, the calendar shall scroll to the center instead

    Screenshot 2022-11-27 at 3 09 31 PM enhancement 
    opened by PavieOlivier 0
Owner
Aleksander Woźniak
Flutter and Kotlin enthusiast
Aleksander Woźniak
Progress State Button - A customizable progress button for Flutter

Progress State Button - A customizable progress button for Flutter

Selim 108 Dec 12, 2022
A customizable and easy to use UI widgets to help develop apps faster

Lenore UI Beautiful, customizable and easy to use UI widgets to help me (or maybe you) develop my (or maybe your) apps faster. This is my personal pac

Lenore 3 Nov 4, 2022
Easy to use, customizable and pluggable Theme Provider.

theme_provider Easy to use, customizable Theme Provider. This provides app color schemes throughout the app and automatically rebuilds the UI dynamica

K.D. Sunera Avinash Chandrasiri 143 Dec 10, 2022
A Flutter widget that easily adds the flipping animation to any widget

flip_card A component that provides a flip card animation. It could be used for hiding and showing details of a product. How to use import 'package:fl

Bruno Jurković 314 Dec 31, 2022
A widget that allow user resize the widget with drag

Flutter-Resizable-Widget A widget that allow user resize the widget with drag Note: this widget uses Getx Example bandicam.2021-11-11.12-34-41-056.mp4

MohammadAminZamani.afshar 22 Dec 13, 2022
A draggable Flutter widget that makes implementing a SlidingUpPanel much easier!

sliding_up_panel A draggable Flutter widget that makes implementing a SlidingUpPanel much easier! Based on the Material Design bottom sheet component,

Akshath Jain 1.2k Jan 7, 2023
Circular Reveal Animation as Flutter widget!

Circular Reveal Animation Circular Reveal Animation as Flutter widget! Inspired by Android's ViewAnimationUtils.createCircularReveal(...). Статья с оп

Alexander Zhdanov 48 Aug 15, 2022
A Flutter Package providing Avatar Glow Widget

Avatar Glow This Flutter package provides a Avatar Glow Widget with cool background glowing animation. Live Demo: https://apgapg.github.io/avatar_glow

Ayush P Gupta 250 Dec 22, 2022
✨A clean and lightweight loading/toast widget for Flutter, easy to use without context, support iOS、Android and Web

Flutter EasyLoading English | 简体中文 Live Preview ?? https://nslog11.github.io/flutter_easyloading Installing Add this to your package's pubspec.yaml fi

nslog11 1k Jan 9, 2023
A beautiful animated flutter widget package library. The tab bar will attempt to use your current theme out of the box, however you may want to theme it.

Motion Tab Bar A beautiful animated widget for your Flutter apps Preview: | | Getting Started Add the plugin: dependencies: motion_tab_bar: ^0.1.5 B

Rezaul Islam 237 Nov 15, 2022
a widget provided to the flutter scroll component drop-down refresh and pull up load.

flutter_pulltorefresh Intro a widget provided to the flutter scroll component drop-down refresh and pull up load.support android and ios. If you are C

Jpeng 2.5k Jan 5, 2023
Flutter 3D Flip Animation Widget

flutter_flip_view This is a flutter Widget base on pure Dart code that provides 3D flip card visuals. Usage add package in your pubspec.yaml dependenc

WosLovesLife 57 Dec 30, 2022
A simple toggle switch widget for Flutter.

Toggle Switch A simple toggle switch widget. It can be fully customized with desired icons, width, colors, text, corner radius, animation etc. It also

Pramod Joshi 84 Nov 20, 2022
Base Flutter widget which triggers rebuild only of props changed

pure_widget Base widget which triggers rebuild only if props changed Installation pubspec.yaml: dependencies: pure_widget: ^1.0.0 Example import 'da

Andrei Lesnitsky 9 Dec 12, 2022
A Stepper Widget in Flutter using GetX

Stepper Flutter GetX Donate If you found this project helpful or you learned something from the source code and want to thank me, consider buying me a

Ripples Code 0 Nov 27, 2021
A Flutter dropdown widget.

Flutter Dropdown_Below A Flutter Dropdown library which is customize flutter dropdownbutton widget. Options options description type required itemWidt

Denny Hong 27 Sep 7, 2022
Flutter's core Dropdown Button widget with steady dropdown menu and many options you can customize to your needs.

Flutter DropdownButton2 Intro Flutter's core Dropdown Button widget with steady dropdown menu and many options you can customize to your needs. Featur

AHMED ELSAYED 125 Jan 4, 2023
Flutter widget that automatically resizes text to fit perfectly within its bounds.

ONLY FOR FLUTTER WEB Flutter widget that automatically resizes text to fit perfectly within its bounds. Show some ❤️ and star the repo to support the

Rebar Ahmad 4 Jan 6, 2022
Flutter fluid slider - A fluid design slider that works just like the Slider material widget

Fluid Slider for Flutter Inspired by a dribbble by Virgil Pana. A fluid design s

Jay Raj 2 Feb 18, 2022