TableCalendar

repository·master·Indexed 21 days ago

https://github.com/aleksanderwozniak/table_calendar

A highly customizable and feature-packed calendar widget for Flutter. It supports various formats, range and multiple selections, dynamic event loading via eventLoader, and extensive UI customization through CalendarStyle and CalendarBuilders. The library provides granular control over day cell rendering, event markers, and locale-specific formatting.

Tokens
5.1K
Snippets
15
Records
27
Agent score
84%

What's inside table_calendar

  1. Customize TableCalendar UI with Styles and Builders

    master

    The table_calendar package provides two primary ways to customize the calendar's appearance:

    1. Custom Styles: A low-effort way to achieve polished results by modifying existing visual properties.
    2. Custom Builders: A high-control method that allows for full UI customization. Builders should typically be used in conjunction with custom Styles to achieve complete control over the calendar's layout and components.

    For detailed implementation details, refer to the official API docs.

  2. Basic setup of TableCalendar

    master

    The TableCalendar widget requires three mandatory properties to define its date boundaries and initial view:

    • firstDay: The earliest date the user can access.
    • lastDay: The latest date the user can access.
    • focusedDay: The currently targeted day, which determines which month is visible.

    Note: To prevent the calendar from resetting to the initial focusedDay during hot reloads or rebuilds, you must store and update the focusedDay value using the onPageChanged callback.

    TableCalendar(
      firstDay: DateTime.utc(2010, 10, 16),
      lastDay: DateTime.utc(2030, 3, 14),
      focusedDay: DateTime.now(),
    );
  3. Customize iOS launch screen assets

    master

    To customize the iOS launch screen, you can either replace the image files directly in the example/ios/Runner/Assets.xcassets/LaunchImage.imageset/ directory or use Xcode for a visual approach.

    Using Xcode:

    1. Open your Flutter project's iOS workspace using open ios/Runner.xcworkspace.
    2. In the Xcode Project Navigator, select Runner/Assets.xcassets.
    3. Drag and drop your desired images into the asset catalog.
    open ios/Runner.xcworkspace
  4. Customize UI with CalendarBuilders

    master

    Use the calendarBuilders property to override specific parts of the calendar UI with your own widgets. Each builder allows you to selectively target elements (like day labels, week day labels, etc.). If a builder returns null, the default style for that element is used.

    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),
            ),
          );
        }
        return null; // Use default for other days
      },
    ),
  5. Configure Locale and Language

    master

    To support different languages, follow these steps:

    1. Initialize Formatting: Add the intl package and call initializeDateFormatting() in your main() function.
    2. Set Locale: Pass a locale string (e.g., 'pl_PL', 'fr_FR') to the locale property of TableCalendar.

    Note on FormatButton: If you use the built-in FormatButton, you must manually translate its text by providing translated strings to the availableCalendarFormats property. Alternatively, hide the button using formatButtonVisible: false.

    // 1. Initialization in main.dart
    import 'package:intl/date_symbol_data_local.dart';
    
    void main() {
      initializeDateFormatting().then((_) => runApp(MyApp()));
    }
    
    // 2. Usage in widget
    TableCalendar(
      locale: 'pl_PL',
    );
  6. Display events using eventLoader

    master

    To show events on specific days, use the eventLoader property. This callback provides a DateTime object for each day, and you must return a list of events associated with that day.

    Best Practice for Date Matching: Since DateTime objects include time components, using them as keys in a standard Map can lead to mismatches. It is recommended to use a LinkedHashMap with a custom equals implementation using isSameDay to ensure events are correctly retrieved regardless of the time part.

    // Basic implementation
    eventLoader: (day) {
      return _getEventsForDay(day);
    },
    
    // Example helper
    List<Event> _getEventsForDay(DateTime day) {
      return events[day] ?? [];
    }
    
    // Recommended Map setup for DateTime keys
    final events = LinkedHashMap(
      equals: isSameDay,
      hashCode: getHashCode,
    )..addAll(eventSource);
  7. Make TableCalendar interactive

    master

    By default, TableCalendar only allows horizontal swiping to change months. To enable day selection and calendar format switching, implement the following callbacks:

    1. Day Selection: Use selectedDayPredicate to define which day is currently selected and onDaySelected to update your state when a user taps a day.
    2. Format Switching: Use calendarFormat to control the current view (e.g., month, week) and onFormatChanged to update the state when the user changes the format.
    3. Page Navigation: Use onPageChanged to update your stored focusedDay so the calendar maintains its position during rebuilds.
    TableCalendar(
      // Day selection
      selectedDayPredicate: (day) {
        return isSameDay(_selectedDay, day);
      },
      onDaySelected: (selectedDay, focusedDay) {
        setState(() {
          _selectedDay = selectedDay;
          _focusedDay = focusedDay;
        });
      },
    
      // Format switching
      calendarFormat: _calendarFormat,
      onFormatChanged: (format) {
        setState(() {
          _calendarFormat = format;
        });
      },
    
      // Maintain focus during rebuilds
      onPageChanged: (focusedDay) {
        _focusedDay = focusedDay;
      },
    );
  8. Customize TableCalendar UI with CalendarBuilders

    master

    The CalendarBuilders<T> class allows you to provide custom widget builders for various parts of the TableCalendar, such as day cells, event markers, and headers. You pass an instance of CalendarBuilders to the builders property of the TableCalendar widget.

    Day Cell Builders

    TableCalendar uses a priority system for day cell rendering. If multiple builders match a day, the following hierarchy generally applies:

    1. prioritizedBuilder: Highest priority; overrides all other day builders.
    2. todayBuilder: For the current day.
    3. selectedBuilder: For days matching selectedDayPredicate.
    4. rangeStartBuilder / rangeEndBuilder: For the boundaries of a selected range.
    5. withinRangeBuilder: For days inside a selected range.
    6. outsideBuilder: For days belonging to a different month than the focusedDay.
    7. disabledBuilder: For days disabled by enabledDayPredicate or out of bounds.
    8. holidayBuilder: For days matching holidayPredicate.
    9. defaultBuilder: The fallback builder.

    Event Marker Builders

    You can customize how events are displayed on a day cell using two types of builders:

    • singleMarkerBuilder: Creates a single marker for a given event. Markers are typically displayed in a Row above the day cell.
    • markerBuilder: Overrides both singleMarkerBuilder and the default markers. It provides a list of all events for that day, allowing you to design a custom multi-event UI.
  9. Configure the visual appearance with CalendarStyle

    master

    The CalendarStyle class is used to customize the visual appearance of the TableCalendar widget. It allows you to define styles (text and decoration) for various states of day cells, such as being selected, being the current day, being a holiday, or being part of a range selection. It also controls the appearance of event markers and the overall table layout.

    const CalendarStyle({
      this.isTodayHighlighted = true,
      this.canMarkersOverflow = true,
      this.outsideDaysVisible = true,
      this.markersAutoAligned = true,
      this.markerSize,
      this.markerSizeScale = 0.2,
      this.markersAnchor = 0.7,
      this.rangeHighlightScale = 1.0,
      this.markerMargin = const EdgeInsets.symmetric(horizontal: 0.3),
      this.markersAlignment = Alignment.bottomCenter,
      this.markersMaxCount = 4,
      this.cellMargin = const EdgeInsets.all(6.0),
      this.cellPadding = EdgeInsets.zero,
      this.cellAlignment = Alignment.center,
      this.markersOffset = const PositionedOffset(),
      this.rangeHighlightColor = const Color(0xFFBBDDFF),
      this.markerDecoration = const BoxDecoration(
        color: Color(0xFF263238),
        shape: BoxShape.circle,
      ),
      // ... other properties
    });
  10. Customize day cell text formatting

    master

    The dayTextFormatter property in CalendarStyle allows you to change how the day number is displayed within the cell. It accepts a TextFormatter function which takes the DateTime and the locale string.

    Example usage:

    CalendarStyle(
      dayTextFormatter: (date, locale) => DateFormat.d(locale).format(date),
    )
    // Example usage:
    // dayTextFormatter: (date, locale) => DateFormat.d(locale).format(date),