πŸ“… Customizable flutter calendar widget including day and week views

Overview

πŸ“… Customizable, animated calendar widget including day, week, and month views.

Navigation Animation
Callbacks Changing the VisibleDateRange

Available Layouts

MultiDateTimetable

A Timetable widget that displays multiple consecutive days.

Light Mode Dark Mode

RecurringMultiDateTimetable

A Timetable widget that displays multiple consecutive days without their dates and without a week indicator.

Light Mode Dark Mode

CompactMonthTimetable

A Timetable widget that displays MonthWidgets in a page view.

Light Mode Dark Mode

Getting started

0. General Information

Timetable doesn't care about any time-zone related stuff. All supplied DateTimes must have isUtc set to true, but the actual time zone is then ignored when displaying events.

Some date/time-related parameters also have special suffixes:

  • date: A DateTime with a time of zero.
  • month: A DateTime with a time of zero and a day of one.
  • timeOfDay: A Duration between zero and 24 hours.
  • dayOfWeek: An int between one and seven (DateTime.monday through DateTime.sunday).

Timetable currently offers localizations for Chinese, English, French, German, Hungarian, Italian, Japanese, Portuguese, and Spanish. Even if you're just supporting English in your app, you have to add Timetable's localization delegate to your MaterialApp/CupertinoApp/WidgetsApp:

MaterialApp(
  localizationsDelegates: [
    TimetableLocalizationsDelegate(),
    // Other delegates, e.g., `GlobalMaterialLocalizations.delegate`
  ],
  // ...
);

You want to contribute a new localization? Awesome! Please follow the steps listed in the doc comment of TimetableLocalizationsDelegate.

1. Define your Events

Events are provided as instances of Event. To get you started, there's the subclass BasicEvent, which you can instantiate directly. If you want to be more specific, you can also implement your own class extending Event.

⚠️ Most of Timetable's classes accept a type-parameter E extends Event. Please set it to your chosen Event-subclass (e.g., BasicEvent) to avoid runtime exceptions.

In addition, you also need a Widget to display your events. When using BasicEvent, this can simply be BasicEventWidget.

2. Create a DateController (optional)

Similar to a ScrollController or a TabController, a DateController is responsible for interacting with Timetable's widgets and managing their state. As the name suggests, you can use a DateController to access the currently visible dates, and also animate or jump to different days. And by supplying a VisibleDateRange, you can also customize how many days are visible at once and whether they, e.g., snap to weeks.

final myDateController = DateController(
  // All parameters are optional and displayed with their default value.
  initialDate: DateTimeTimetable.today(),
  visibleRange: VisibleDateRange.week(startOfWeek: DateTime.monday),
);

Don't forget to dispose your controller, e.g., in State.dispose!

Here are some of the available VisibleDateRanges:

  • VisibleDateRange.days: displays visibleDayCount consecutive days, snapping to every swipeRange days (aligned to alignmentDate) in the range from minDate to maxDate
  • VisibleDateRange.week: displays and snaps to whole weeks with a customizable startOfWeek in the range from minDate to maxDate
  • VisibleDateRange.weekAligned: displays visibleDayCount consecutive days while snapping to whole weeks with a customizable firstDay in the range from minDate to maxDate – can be used, e.g., to display a five-day workweek

3. Create a TimeController (optional)

Similar to the DateController above, a TimeController is also responsible for interacting with Timetable's widgets and managing their state. More specifically, it controls the visible time range and zoom factor in a MultiDateTimetable or RecurringMultiDateTimetable. You can also programmatically change those and, e.g., animate out to reveal the full day.

final myTimeController = TimeController(
  // All parameters are optional. By default, the whole day is revealed
  // initially and you can zoom in to view just a single minute.
  minDuration: 15.minutes, // The closest you can zoom in.
  maxDuration: 23.hours, // The farthest you can zoom out.
  initialRange: TimeRange(9.hours, 17.hours),
  maxRange: TimeRange(0.hours, 24.hours),
);

This example uses some of supercharged's extension methods on int to create a Duration more concisely.

Don't forget to dispose your controller, e.g., in State.dispose!

4. Create your Timetable widget

The configuration for Timetable's widgets is provided via inherited widgets. You can use a TimetableConfig<E> to provide all at once:

TimetableConfig<BasicEvent>(
  // Required:
  dateController: _dateController,
  timeController: _timeController,
  eventBuilder: (context, event) => BasicEventWidget(event),
  child: MultiDateTimetable<BasicEvent>(),
  // Optional:
  eventProvider: (date) => someListOfEvents,
  allDayEventBuilder: (context, event, info) =>
      BasicAllDayEventWidget(event, info: info),
  callbacks: TimetableCallbacks(
    // onWeekTap, onDateTap, onDateBackgroundTap, onDateTimeBackgroundTap
  ),
  theme: TimetableThemeData(
    context,
    // startOfWeek: DateTime.monday,
    // See the "Theming" section below for more options.
  ),
)

And you're done πŸŽ‰

Theming

Timetable already supports light and dark themes out of the box, adapting to the ambient ThemeData. You can, however, customize the styles of almost all components by providing a custom TimetableThemeData.

To apply your own theme, specify it in the TimetableConfig<E> (or directly in a TimetableTheme):

TimetableConfig<BasicEvent>(
  theme: TimetableThemeData(
    context,
    startOfWeek: DateTime.monday,
    dateDividersStyle: DateDividersStyle(
      context,
      color: Colors.blue.withOpacity(.3),
      width: 2,
    ),
    dateHeaderStyleProvider: (date) =>
        DateHeaderStyle(context, date, tooltip: 'My custom tooltip'),
    nowIndicatorStyle: NowIndicatorStyle(
      context,
      lineColor: Colors.green,
      shape: TriangleNowIndicatorShape(color: Colors.green),
    ),
    // See the "Theming" section below for more.
  ),
  // Other properties...
)

TimetableThemeData and all component styles provide two constructors each:

  • The default constructor takes a BuildContext and sometimes a day or month, using information from the ambient theme and locale to generate default values. You can still override all options via optional, named parameters.
  • The named raw constructor is usually const and has required parameters for all options.

Advanced Features

Drag and Drop

Drag and Drop demo

You can easily make events inside the content area of MultiDateTimetable or RecurringMultiDateTimetable draggable by wrapping them in a PartDayDraggableEvent:

PartDayDraggableEvent(
  // The user started dragging this event.
  onDragStart: () {},
  // The event was dragged to the given [DateTime].
  onDragUpdate: (dateTime) {},
  // The user finished dragging the event and landed on the given [DateTime].
  onDragEnd: (dateTime) {},
  child: MyEventWidget(),
  // By default, the child is displayed with a reduced opacity when it's
  // dragged. But, of course, you can customize this:
  childWhileDragging: OptionalChildWhileDragging(),
)

Timetable doesn't automatically show a moving feedback widget at the current pointer position. Instead, you can customize this and, e.g., snap to multiples of 15 minutes. Have a look at the included example app where we implemented exactly that by displaying the drag feedback as a time overlay.

Time Overlays

Drag and Drop demo

In addition to displaying events, MultiDateTimetable and RecurringMultiDateTimetable can display overlays for time ranges on every day. In the screenshot above, a light gray overlay is displayed on weekdays before 8β€―a.m. and after 8β€―p.m., and over the full day for weekends. Time overlays are provided similarly to events: Just add a timeOverlayProvider to your TimetableConfig<E> (or use a DefaultTimeOverlayProvider directly).

TimetableConfig<MyEvent>(
  timeOverlayProvider: (context, date) => <TimeOverlay>[
    TimeOverlay(
      start: 0.hours,
      end: 8.hours,
      widget: ColoredBox(color: Colors.black12),
      position: TimeOverlayPosition.behindEvents, // the default, alternatively `inFrontOfEvents`
    ),
    TimeOverlay(
      start: 20.hours,
      end: 24.hours,
      widget: ColoredBox(color: Colors.black12),
    ),
  ],
  // Other properties...
)

The provider is just a function that receives a date and returns a list of TimeOverlay for that date. The example above therefore draws a light gray background before 8β€―a.m. and after 8β€―p.m. on every day.

Comments
  • feat: Available dates range support

    feat: Available dates range support

    Closes: #25, #38

    Features

    • ability to define min and max dates
    • ability to define swipeRange for a VisibleRange.days
    • added jumpTo, jumpToToday, jumpToInitialDate, animateToInitialDate methods to controller

    Features for discussion

    • support of min/max date for WeekVisibleRange

    Checklist

    • [ ] remove redundant code
    • [ ] fix lint issues
    • [ ] update existing tests
    • [ ] update example App
    • [ ] Tests for the changes have been added (for bug fixes / features)
    • [ ] Docs have been added / updated (for bug fixes / features)
    T: Feat C: Timetable 
    opened by TatsuUkraine 19
  • Change color of currently selected day in CompactMonthTimetable

    Change color of currently selected day in CompactMonthTimetable

    How can currently selected date in CompactMonthTimetable be changed?

    In a way so that today date is always selected in its own colour (as it is now which is good), but for those manually selected dates in CompactMonthTimetable to set some custom color?

    image

    opened by ghost 18
  • Allow to specify min hour height

    Allow to specify min hour height

    Prev version of the package had the ability to specify min cell height. New package version forces you to provide min duration. With various screen sizes this type of config a little bit problematic. Especially if take into account that there is no setter for this value.

    So whenever screen size change only one option is to grab screen size or layout constraints, calculate min duration somehow, dispose existing controller, and create a new one. And this flow may happen quite often due to device rotate.

    Proposition Add ability specify min cell height.

    An additional feature that may be useful - allow changing min duration in time controller

    T: Feat 
    opened by TatsuUkraine 11
  • Date controller contains wrong selected date

    Date controller contains wrong selected date

    Describe the bug Story

    • open example project
    • switch to 3 days view
    • scroll to state when Today (sometimes day after today) is a first one in 3 days list
    • swipe less than 40% width of the day column in the past
    • remove finger so time table return back to original date

    Expected behavior Date controller emits (has) date that 3 days interval start with

    Actual behavior Date controller has date that is one day before the actual one

    Screenshots

    https://user-images.githubusercontent.com/621542/121596282-ea75a780-ca47-11eb-876c-8e67e2fd84d6.mov

    Environment:

    • Device: Android Pixel 3 emulator/Android pixel 5 real device
    • OS version: Android 11
    • Package version: 1.0.0-alpha.1
    T: Fix 
    opened by TatsuUkraine 10
  • TimetableController's scrollController does not update its page value

    TimetableController's scrollController does not update its page value

    Description

    Scrolling on the calendar doesn't seem to change the value of the current page. I added the following listener:

    timetableController.scrollControllers.addPageChangedListener(() {
          print('Page changed to ${timetableController.scrollControllers.page}');
        });
    

    This causes it to print a message every time I try to scroll, but the value of the page printed always remains the same.

    As a side-effect of this, other listeners that depend on the page value, such as TimetableController.dateListenable and TimetableController.currentlyVisibleDatesListenable are also triggering their listeners, but their values aren't changing, and are remaining the same as the initialDate and initialTimeRange values.

    Screenshots

    image

    Environment:

    • Device: Huawei Honor 9 Lite
    • OS version: Android 9.0.0
    • Package version: 0.2.3
    T: Fix C: Timetable 
    opened by RedMarbles 10
  • Hide and disable week indicator

    Hide and disable week indicator

    How can week indicator be removed/hidden and disabled? image

    There is option to change styling of week indicator, but what about removing it?

    weekIndicatorStyleProvider: (week) => 
        WeekIndicatorStyle(context, week, labels: , textStyle: , tooltip: , padding: , decoration: ),
    
    opened by ghost 8
  • Add BoxDecoration theme to header container and hours container (left side)

    Add BoxDecoration theme to header container and hours container (left side)

    Add the ability to define BoxDecoration for the header container and hours container.

    It will be useful to keep the timetable up to date with any custom theme (like shadows aka Material elevation, shapes, borders and etc.) that dev is using in his App.

    P.S. Sorry that I'm spamming your package with issues)) But everything that I create is something that I need in my current task)

    T: Feat 
    opened by TatsuUkraine 8
  • Main layout repaints each second

    Main layout repaints each second

    Describe the bug When timetable widget is initialized it starts to repaint entire table each second

    Screenshots timetable-repaint

    Environment:

    • Package version: 1.0.0-alpha.0
    T: Fix 
    opened by TatsuUkraine 7
  • Custom hour of day label formatter

    Custom hour of day label formatter

    These changes add the features to custom the hour column. Currently, we can only set the TextStyle with the hour format of HH:mm and column width set at 48.0. This update adds the ability to set custom time formatting and column width.

    • [x] Adds theme property for formatting the hour of the day label.
    • [x] Adds theme property to set the width of hour column

    Example

    final theme = TimetableThemeData(
      formatHour: (time) => '${time.hourOf12HourClock} ${time.hourOfDay > 11 ? "PM" : "AM"}',
      hourColumnWidth: 40,
    );
    

    Checklist

    • [x] Tests for the changes have been added (for bug fixes / features)
    • [x] Docs have been added / updated (for bug fixes / features)

    Screenshots

    Format hour

    | Android | iOS | | :------------: | :------------: | | Screen Shot 2020-07-19 at 4 16 10 PM | Screen Shot 2020-07-19 at 4 19 12 PM |

    Set column width

    | Larger | Zero width | | :------------: | :------------: | | Screen Shot 2020-07-20 at 9 56 19 AM | Screen Shot 2020-07-20 at 9 56 32 AM|

    opened by kennethj 6
  • Tap on Backgrounds for DateEvents and AllDayEvents

    Tap on Backgrounds for DateEvents and AllDayEvents

    Closes: #18

    I thought I'd issue a pull request at the current state regarding #18.

    Background taps are currently recognized across DateEvents and AllDayEvents. Tapping on headers is currently not implemented yet. The pull request adapted the example with a snackbar function.

    There are some things on my mind and I'm looking forward to your feedback:

    1. Is the name onCreateEvent and onCreateAllDayEvent really appliceable? Maybe we should change it to somehting like onBackgroundTap or onCellTap?

    2. Regarding DateEvents I'm not quite sure why when calculating the position of the tapped cell I need to add a +1 here:

    final dateAndTime = DateTime(date.year, date.monthOfYear, date.dayOfYear, tappedCell.toInt() + 1);
    
    1. For allday events I even had to do +2 for the day.
    final dateAndTime = DateTime(date.year, date.monthOfYear, date.dayOfYear + 2);
    

    I'm not really sure about the calculations at all. The offset issue with the days might be related to wrong rounding? Might also be a conversion problem related to final startTime = LocalDateTime.dateTime(dateAndTime) I think? Maybe you could shed some light into this and the calculation at all. Also the time of the giving back object is always 23:00:00 eventhough it should be 00:00:00

    1. I think there are still some parts where I could make the code partly more elegant. Advices are appreciated :) !
    T: Feat C: Timetable C: Example 
    opened by raLaaaa 6
  • Listener when tapping the background (e.g. for creating an event)

    Listener when tapping the background (e.g. for creating an event)

    Hello there,

    any ideas on when this will be live? Are you open for foreign contributions?

    I could not find a contribution guide but I'd be happy to start working on this one since I could need it for a personal project.

    Just wanted to check in whether you are basically open for foreign contributions etc. and what a foreign contributor should consider?

    Would be a pity if I start working on this one and it's nearly done on your side or you don't want anyone to contribute to this project.

    T: Feat 
    opened by raLaaaa 6
  • _RenderWeekIndicatorText does not meet its constraints

    _RenderWeekIndicatorText does not meet its constraints

    Using alpha 10 version, loading the timetable widget throws an exception:

    ======== Exception caught by rendering library ===================================================== The following assertion was thrown during performLayout(): _RenderWeekIndicatorText does not meet its constraints.

    Constraints: BoxConstraints(0.0<=w<=14.0, 0.0<=h<=309.5) Size: Size(16.0, 16.0)

    If you are not writing your own RenderBox subclass, then this is not your fault. Contact support: https://github.com/flutter/flutter/issues/new?template=2_bug.md

    The relevant error-causing widget was: MultiDateTimetable MultiDateTimetable:file:///C:/Users/healt/AndroidStudioProjects/MyWod/lib/screens/timetable/timetable.dart:67:24 When the exception was thrown, this was the stack: #0 RenderBox.debugAssertDoesMeetConstraints. (package:flutter/src/rendering/box.dart:2295:9) #1 RenderBox.debugAssertDoesMeetConstraints (package:flutter/src/rendering/box.dart:2382:6) #2 RenderBox.size=. (package:flutter/src/rendering/box.dart:2066:7) #3 RenderBox.size= (package:flutter/src/rendering/box.dart:2068:6) #4 _RenderWeekIndicatorText.performLayout (package:timetable/src/components/week_indicator.dart:241:5) #5 RenderObject.layout (package:flutter/src/rendering/object.dart:2135:7) #6 RenderBox.layout (package:flutter/src/rendering/box.dart:2418:11) #7 RenderPadding.performLayout (package:flutter/src/rendering/shifted_box.dart:249:12) #8 RenderObject.layout (package:flutter/src/rendering/object.dart:2135:7) #9 RenderBox.layout (package:flutter/src/rendering/box.dart:2418:11) #10 RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:120:14) #11 RenderObject.layout (package:flutter/src/rendering/object.dart:2135:7) #12 RenderBox.layout (package:flutter/src/rendering/box.dart:2418:11) #13 RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:120:14) #14 RenderObject.layout (package:flutter/src/rendering/object.dart:2135:7) #15 RenderBox.layout (package:flutter/src/rendering/box.dart:2418:11) #16 RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:120:14) #17 RenderObject.layout (package:flutter/src/rendering/object.dart:2135:7) #18 RenderBox.layout (package:flutter/src/rendering/box.dart:2418:11) #19 RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:120:14) #20 RenderObject.layout (package:flutter/src/rendering/object.dart:2135:7) #21 RenderBox.layout (package:flutter/src/rendering/box.dart:2418:11) #22 RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:120:14) #23 RenderObject.layout (package:flutter/src/rendering/object.dart:2135:7) #24 RenderBox.layout (package:flutter/src/rendering/box.dart:2418:11) #25 RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:120:14) #26 RenderObject.layout (package:flutter/src/rendering/object.dart:2135:7) #27 RenderBox.layout (package:flutter/src/rendering/box.dart:2418:11) #28 RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:120:14) #29 RenderObject.layout (package:flutter/src/rendering/object.dart:2135:7) #30 RenderBox.layout (package:flutter/src/rendering/box.dart:2418:11) #31 RenderPositionedBox.performLayout (package:flutter/src/rendering/shifted_box.dart:451:14) #32 RenderObject.layout (package:flutter/src/rendering/object.dart:2135:7) #33 RenderBox.layout (package:flutter/src/rendering/box.dart:2418:11) #34 RenderConstrainedBox.performLayout (package:flutter/src/rendering/proxy_box.dart:292:14) #35 RenderObject.layout (package:flutter/src/rendering/object.dart:2135:7) #36 RenderBox.layout (package:flutter/src/rendering/box.dart:2418:11) #37 RenderFlex._computeSizes (package:flutter/src/rendering/flex.dart:836:43) #38 RenderFlex.performLayout (package:flutter/src/rendering/flex.dart:938:32) #39 RenderObject.layout (package:flutter/src/rendering/object.dart:2135:7) #40 RenderBox.layout (package:flutter/src/rendering/box.dart:2418:11) #41 RenderConstrainedBox.performLayout (package:flutter/src/rendering/proxy_box.dart:292:14) #42 RenderObject.layout (package:flutter/src/rendering/object.dart:2135:7) #43 RenderBox.layout (package:flutter/src/rendering/box.dart:2418:11) #44 RenderFlex._computeSizes (package:flutter/src/rendering/flex.dart:836:43) #45 RenderFlex.performLayout (package:flutter/src/rendering/flex.dart:938:32) #46 RenderObject.layout (package:flutter/src/rendering/object.dart:2135:7) #47 RenderBox.layout (package:flutter/src/rendering/box.dart:2418:11) #48 _RenderLayoutBuilder.performLayout (package:flutter/src/widgets/layout_builder.dart:318:14) #49 RenderObject.layout (package:flutter/src/rendering/object.dart:2135:7) #50 RenderBox.layout (package:flutter/src/rendering/box.dart:2418:11) #51 RenderPadding.performLayout (package:flutter/src/rendering/shifted_box.dart:249:12) #52 RenderObject.layout (package:flutter/src/rendering/object.dart:2135:7) #53 RenderBox.layout (package:flutter/src/rendering/box.dart:2418:11) #54 RenderFlex._computeSizes (package:flutter/src/rendering/flex.dart:903:45) #55 RenderFlex.performLayout (package:flutter/src/rendering/flex.dart:938:32) #56 RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:1973:7) #57 PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:999:18) #58 RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:513:19) #59 WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:884:13) #60 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:378:5) #61 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1175:15) #62 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1104:9) #63 SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1015:5) #64 _invoke (dart:ui/hooks.dart:148:13) #65 PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:318:5) #66 _drawFrame (dart:ui/hooks.dart:115:31) The following RenderObject was being processed when the exception was fired: _RenderWeekIndicatorText#95959 relayoutBoundary=up16 ... parentData: offset=Offset(8.0, 2.0) (can use size) ... constraints: BoxConstraints(0.0<=w<=14.0, 0.0<=h<=309.5) ... size: Size(16.0, 16.0) RenderObject: _RenderWeekIndicatorText#95959 relayoutBoundary=up16 parentData: offset=Offset(8.0, 2.0) (can use size) constraints: BoxConstraints(0.0<=w<=14.0, 0.0<=h<=309.5) size: Size(16.0, 16.0)

    My code:

    Container( padding: EdgeInsets.symmetric(horizontal: 10), child: TimetableConfig<BasicEvent>( child: MultiDateTimetable<BasicEvent>(), dateController: ref.read(dateControllerProvider.state).state, timeController: ref.read(timeControllerProvider.state).state, eventProvider: eventProviderFromFixedList(basicEvents ?? []), theme: TimetableThemeData(context, weekdayIndicatorStyleProvider: (date) => WeekdayIndicatorStyle(context, date, textStyle: date == DateTimeTimetable.today() ? TextStyle(fontSize: 12, color: boxData.highlight) : null), dateIndicatorStyleProvider: (date) => DateIndicatorStyle(context, date, decoration: date == DateTimeTimetable.today() ? BoxDecoration (shape: BoxShape.circle, color: boxData.highlight) : null), nowIndicatorStyle: NowIndicatorStyle(context, lineColor: boxData.highlight), timeIndicatorStyleProvider: (time) => TimeIndicatorStyle(context, time, alwaysUse24HourFormat: true)), eventBuilder: (context, event) => BasicEventWidget(event, onTap: () => _showEventDetails(event, sessionEvents, boxData, context), ) ), ),

    T: Fix 
    opened by abel-123 0
  • Vertical scrolling while dragging the event

    Vertical scrolling while dragging the event

    using the dateController.animateToPage is smooth in scrolling horizontally while dragging the event but using the timeController.animateTo to scroll vertically has a slow and weird behavior while dragging ... any help, please ?

    T: Fix 
    opened by HaneenAhmedMohy 3
  • WeekIndicator Width changes on Screen Change to the Timetable

    WeekIndicator Width changes on Screen Change to the Timetable

    When I am switching to the timetable screen, the width of the WeekIndicator changes. The change happens once, every time I change to this screen. It goes from full WeekIndicator to short.

    Example: Week 11, 2022 -> W11

    This is how I am using the MultiDateTimetable

    Widget build(BuildContext context) { return TimetableConfig<BasicEvent>( dateController: _dateController, timeController: _timeController, eventBuilder: (context, event) => BasicEventWidget(event), child: MultiDateTimetable<BasicEvent>(), ); }

    This is a part of a stateful widget. This is wrapped by a Scaffold which is then wrapped by a SafeArea.

    See the gif:

    ezgif com-gif-maker

    T: Fix 
    opened by georgiossalon 0
  • Detect when page in MultiDateTimetable completes

    Detect when page in MultiDateTimetable completes

    How to detect when page completely changes? For example to get a callback not after you just begin with swiping, nor when you release a press while swiping, but when animation of page swipe ends? If you were to start swiping form one page to another and while on the middle between two pages you release a press, page will continue with animation to second page, and when it finishes animation i would like to get a callback.

    Reason why I'm asking is because I would like to fetch events from server whenever user swipes to new page, and issue with _dateController.addListener() is because it triggers a callback somewhat good when you swipe to next page, but when you try to swipe to previous page listener is triggered almost instantly as you being to swipe to previous page.

    I though to use NotificationListener, and it does work properly for horizontal swiping but issues with this approach is that it also detects when scrolling is active vertically, what i need is only to listen when horizontal page swiping ends

    void handleScrollListener(ScrollNotification scrollNotification) {
      if (scrollNotification is ScrollStartNotification) {
        print("SCROLLING");
      } else if (scrollNotification is ScrollEndNotification) {
        print("STOPPED SCROLLING!");
      }
    }
    
    @override
    Widget build(BuildContext context) {
      return NotificationListener<ScrollNotification>(
        onNotification: (scrollNotification) {
          SchedulerBinding.instance!.addPostFrameCallback(
              (_) => handleScrollListener(scrollNotification));
          return true;
        },
        child: Stack(
          children: [
            TimetableConfig<EventModel>(
    
    opened by ghost 0
  • Drag on slots to create an event

    Drag on slots to create an event

    First off, great library!

    I know it's possible to drag events around but is it possible to drag on empty slots to create an event? Or even drag on empty slots to trigger an action? Example from google calendar below. In google calendar, you hold onto a slot and drag down/up.

    IMG_BFA77077B745-1

    T: Feat 
    opened by mikeyyyzhao 2
Releases(v1.0.0-alpha.9)
  • v1.0.0-alpha.9(Aug 19, 2022)

    ⚠️ BREAKING CHANGES

    • remove DateTimeTimetable.interval in favor of .fullDayInterval (bee93d7)
    • TimetableThemeData.raw(…) takes a new required parameter MultiDateTimetableStyle multiDateTimetableStyle (1fef623)

    πŸŽ‰ New Features

    • MultiDateEventHeader supports limiting the number of rows to display events in. If there are more events in parallel, overflow indicators are displayed.
      • add multiDateEventHeaderStyle.maxEventRows (0ea6549) and multiDateTimetableStyle.maxHeaderFraction (1fef623), closes: #89
      • coerce multiDateEventHeaderStyle.maxEventRows to fit available height (0009716), closes: #63
      • add timetableCallbacks.onMultiDateHeaderOverflowTap (ec18ef1)
    • add timeController.minDayHeight to ensure that labels and events have enough space available when zooming out (8dafaa5), closes: #76
    • enable dragging widgets into timetable content (b54154d), closes: #124
      • add contentGeometryKey to MultiDateTimetable and MultiDateTimetableHeader constructors (caf9ef9)
    • complete remaining Event's and BasicEvent's debugFillProperties(…) (c3a15e9)
    • add .raw constructors for MultiDateTimetable, MultiDateTimetableHeader, and MultiDateTimetableContent (bb7767e)

    πŸ› Bug Fixes

    • honor initial vertical pointer alignment while dragging events (b54154d)

    πŸ“œ Documentation updates

    • add detailed error messages for isValidTimetable… assertions (3b6f115), closes: #127
    Source code(tar.gz)
    Source code(zip)
  • v1.0.0-alpha.10(Aug 19, 2022)

  • v1.0.0-alpha.8(Jun 8, 2022)

  • v1.0.0-alpha.7(Apr 23, 2022)

    πŸŽ‰ New Features

    • add dateController.visibleDates, datePageValue.visibleDates, .firstVisibleDate, .firstVisiblePage,.lastVisibleDate, and .lastVisiblePage (74df510), closes: #119
    • support scrolling with a Scrollbar in TimeZoom (e196576)
    • support mouse scrolling in TimeZoom (1a286f2), closes: #115

    ⚑ Changes

    • WeekIndicator no longer uses a LayoutBuilder internally (a8d04ee)

    πŸ› Bug Fixes

    • remove scrollbar for default time indicators (47cb162), closes: #116
    Source code(tar.gz)
    Source code(zip)
  • v1.0.0-alpha.6(Sep 29, 2021)

  • v1.0.0-alpha.5(Aug 7, 2021)

  • v1.0.0-alpha.4(Aug 6, 2021)

  • 1.0.0-alpha.3(Aug 2, 2021)

    πŸŽ‰ New Features

    • add Spanish localization (#84). Thanks to @paolovalerdi!
    • add missing exports for DateContent, TimeOverlays, EventBuilder<E>, and DefaultEventBuilder<E> (3877220)

    πŸ› Bug Fixes

    • support scrolling when inside a ScrollView (b4ffeee), closes: #80
    • avoid unsafe calls to DefaultTimeController.of(…) in TimeZoom (7bd6447), closes: #90. Thanks to @paolovalerdi for investigating the cause!

    πŸ“œ Documentation updates

    • document how to support a new locale (d2f369c)
    Source code(tar.gz)
    Source code(zip)
  • v1.0.0-alpha.2(Jul 15, 2021)

    ⚠ BREAKING CHANGES

    • TimeIndicators' factories no longer accept an AlignmentGeometry, but only an Alignment (8d8985d)

    πŸŽ‰ New Features

    • add Japanese and Chinese localizations (#82). Thanks to @MasterHiei!
    • add Italian localization (#88). Thanks to @mircoboschi!
    • add alwaysUse24HourFormat to TimeIndicatorStyle's constructor (#82). Thanks to @MasterHiei!
    • add partDayDraggableEvent.onDragCanceled (#82). Thanks to @MasterHiei!
    • TimeIndicators' factories now accept additional parameters for the first and last hour / half hour and whether to align the outer labels inside (8d8985d), closes: #77
    • MultiDateTimetable's constructor now allows you to override only the contentLeading widget (8e65964)

    πŸ› Bug Fixes

    Source code(tar.gz)
    Source code(zip)
  • v1.0.0-alpha.1(Jun 9, 2021)

  • v1.0.0-alpha.0(Jun 6, 2021)

  • v0.2.9(Oct 26, 2020)

  • v0.2.8(Sep 18, 2020)

  • v0.2.7(Sep 2, 2020)

    πŸŽ‰ New Features

    • add TimetableThemeData.minimumHourZoom & .maximumHourZoom, closes: #40 & #45

    πŸ› Bug Fixes

    • support null values in InitialTimeRange.range

    πŸ“¦ Build & CI

    • update dartx to ^0.5.0
    Source code(tar.gz)
    Source code(zip)
  • v0.2.6(Jul 12, 2020)

    πŸŽ‰ New Features

    • add custom builders for date header and leading area of the header (usually a week indicator) (#28), closes: #27. Thanks to @TatsuUkraine!
    • add theme properties for disabling event stacking and configuring the minimum overlap (#34), closes: #31

    πŸ› Bug Fixes

    • Expand part-day events to fill empty columns (#30), closes: #29
    Source code(tar.gz)
    Source code(zip)
  • v0.2.5(Jul 6, 2020)

  • v0.2.4(Jun 25, 2020)

    πŸŽ‰ New Features

    • Timetable.onEventBackgroundTap: called when tapping the background, e.g. for creating an event (#20), closes: #18. Thanks to @raLaaaa!
    • add EventProvider.simpleStream as a simpler interface than EventProvider.stream (e63bfb4)

    πŸ“œ Documentation updates

    • improve streaming EventProvider documentation (e63bfb4), fixes: #19
    Source code(tar.gz)
    Source code(zip)
  • v0.2.3(Jun 15, 2020)

    πŸŽ‰ New Features

    • Customizable date/weekday format with TimetableThemeData.weekDayIndicatorPattern, .dateIndicatorPattern & temporary .totalDateIndicatorHeight (#16), closes: (#15)
    Source code(tar.gz)
    Source code(zip)
  • v0.2.2(May 30, 2020)

    πŸŽ‰ New Features

    • optional onTap-parameter for BasicEventWidget & BasicAllDayEventWidget (#12), closes: (#11)

    πŸ“¦ Build & CI

    • specify minimum Dart version (v2.7.0) in pubspec.yaml
    Source code(tar.gz)
    Source code(zip)
  • v0.2.1(May 30, 2020)

    Published on 2020-05-19

    πŸŽ‰ New Features

    • All-day events (shown at the top) (#8), closes: (#5)
    • Theming (#9) — see the README for more information!

    πŸ“¦ Build & CI

    • specify minimum Flutter version (v1.17.0) in pubspec.yaml
    • example: upload generated APK as artifact
    Source code(tar.gz)
    Source code(zip)
  • v0.2.0(May 8, 2020)

    ⚠ BREAKING CHANGES

    • fix week scroll alignment (#6)
      • To provide a simpler API the exposed methods of VisibleRange were changed slightly. This doesn't affect you if you just instantiate one of the given implementations, but only if you extend it yourself or call one of its methods directly.

    πŸ› Bug Fixes

    • support Flutter v1.17.0 (#4)
    Source code(tar.gz)
    Source code(zip)
  • v0.1.3(May 6, 2020)

  • v0.1.2(May 5, 2020)

  • v0.1.1(May 5, 2020)

  • v0.1.0(Apr 2, 2020)

Owner
Jonas Wanke
Flutter dev @smusy-GmbH Β· πŸ₯‰ WorldSkills Abu Dhabi, Skill 9: IT Software Solutions for Business
Jonas Wanke
The flutter_calendar_widget is highly customizable calendar widget.

flutter_calendar_widget The flutter_calendar_widget is highly customizable calendar widget. Not only can you change the style, but you can also change

dooboolab 4 Jun 24, 2022
A super powerful widget to help developers build complex views quickly and comfortably.

FSuper FSuper can help developers build complex views quickly and comfortably. It supports rich text, rounded corners, borders, pictures, small red do

Fliggy Mobile 481 Dec 29, 2022
A super powerful widget to help developers build complex views quickly and comfortably.

FSuper FSuper can help developers build complex views quickly and comfortably. It supports rich text, rounded corners, borders, pictures, small red do

Fliggy Mobile 481 Dec 29, 2022
Admob Flutter plugin that shows banner ads using native platform views.

Looking for Maintainers. Unfortunately I haven't been able to keep up with demand for features and improvments. If you are interested in helping maint

Kevin McGill 418 Dec 3, 2022
A flutter appliction listing all the widgets covered in Flutter widget of the week playlist.

Flutter Widget Guide A flutter appliction listing all the widgets covered in Flutter widget of the week playlist Get the app Now featured on itsallwid

Annsh Singh 371 Dec 28, 2022
Flutter mobile app with firestore authentication including Email and Social auth.

Flutter mobile app with firestore authentication including Email and Social auth.

Ionicfirebaseapp 96 Dec 7, 2022
A port of kotlin-stdlib for Dart/Flutter including immutable collections (KtList, KtMap, KtSet) and other packages

kt.dart This project is a port of Kotlin's Kotlin Standard library for Dart/Flutter projects. It's a useful addition to dart:core and includes collect

Pascal Welsch 460 Jan 9, 2023
CARP Mobile Sensing for Flutter, including mobile sensing framework, data backend support, and the CARP mobile sensing app.

This repo hold the source code for the CACHET Research Platform (CARP) Mobile Sensing (CAMS) Flutter software. It contains the source code for CACHET

Copenhagen Center for Health Technology (CACHET) 61 Dec 16, 2022
A iOS like table view including section, row, section header and divider

flutter_section_table_view A iOS like table view including section, row, section header and divider Support both Android and iOS Support drop-down ref

刘彦博 73 Nov 4, 2022
An app to show everything bus related in Singapore, including arrival times and a directory

NextBus SG An app to show everything bus related in Singapore, including bus arrival times and a directory, with extra features. ?? Gallery Click here

null 103 Sep 13, 2022
Custom dropdown widget allows to add highly customizable widget in your projects with proper open and close animations and also comes with form required validation.

Custom Dropdown Custom Dropdown package lets you add customizable animated dropdown widget. Features Lots of properties to use and customize dropdown

Abdullah Chauhan 22 Dec 29, 2022
Boilerplate codes including Superbase settings for Flutter

flutter_boilerplate_supabase Boilerplate codes including Superbase settings for Flutter. Getting Started You have to create the .env file. Rename the

Flutter Seoul 2 Feb 7, 2022
Building a simple Flutter app for understanding the BLoC State Management including: Cubit, Managing Route & showSnackBar.

Building a simple Flutter app for understanding the BLoC State Management including: Cubit, Managing Route & showSnackBar.

TAD 8 Dec 3, 2022
Building a simple Flutter app * Switch Theme * for understanding the BLoC State Management including: Cubit Communications with StreamSubscription & Managing Route.

Building a simple Flutter app * Switch Theme * for understanding the BLoC State Management including: Cubit Communications with StreamSubscription & Managing Route.

TAD 1 Oct 3, 2022
A customizable carousel slider widget in Flutter which supports inifinte scrolling, auto scrolling, custom child widget, custom animations and built-in indicators.

flutter_carousel_widget A customizable carousel slider widget in Flutter. Features Infinite Scroll Custom Child Widget Auto Play Horizontal and Vertic

NIKHIL RAJPUT 7 Nov 26, 2022
Custom calendar dialog widget for flutter with (multi select, single select, date range) mode

some calendar Custom calendar with Multi-select & range configurable calendar New Features Added View Mode Somecalendar #15 Help Maintenance I've take

Irvan Lutfi Gunawan 69 Jan 3, 2023
Daynightswitch - A day night switch widget for Flutter.

DayNightSwitch A day night switch widget for Flutter. Installation Add to pubspec.yaml. dependencies: day_night_switch: Usage To use plugin, just i

Divyanshu Bhargava 103 Oct 25, 2022
A simple day / night switcher widget made in pure Dart.

DayNightSwitcher Just a simple simple day / night switcher widget made in pure Dart. It allows you to quickly show a beautiful dark mode switcher widg

Hugo Delaunay 38 Oct 28, 2022
Control your week, days, hours, and even minutes. ⏳

Info An advanced, minimalist, and powerful time management application. Where you can create the task, give it a duration, and select which weekdays y

Ismael Shakverdiev 86 Dec 18, 2022