搜尋套件、儲存庫與 APP 分類

timetable 封面
套件詳情v0.2.9

timetable

📅 可自定的動畫日曆組件,包含日視圖與週視圖

近 30 天下載
413
喜歡數
220
Pub 分數
40

安裝套件

flutter pub add timetable

套件介紹

根據套件公開資料產生的選型評估,僅供參考。

時序表套件為 Flutter 提供了一個可自訂的動畫日曆小工具,支援日視圖與週視圖。設計具有流暢的動畫與直覺導航,讓使用者能以互動方式呈現日程與活動。由 jonaswanke.dev 所開發,此套件非常適合需要時間規劃功能的應用程式,例如任務管理器、預約排程器或課表。可輕鬆整合至 Flutter 專案,並提供彈性樣式選項以符合應用設計。原始碼公開於 GitHub,確保透明度並歡迎貢獻。

適用情境

  • 排程應用程式
  • 任務和事件管理
  • 教育時間表
  • 預約訂位系統
  • 每日計畫介面

主要特色

  • 視圖之間的動畫過渡
  • 支援日視圖與週視圖
  • 可自訂的 UI 與樣式
  • 與 Flutter 的輕鬆整合
  • 開源並由社群支援

適合對象

  • 開發基於日曆應用程式的開發者
  • 需要互動式時間可視化的應用
  • 需要輕量級日曆小部件的項目
  • 希望獲得透明、開源解決方案的團隊
  • 尋求靈活版面選項的設計師

使用建議

  • 未提及特定平台的優化
  • 除了基本設定之外,文件內容有限
  • 需要手動處理事件資料
  • 未針對大型資料集進行優化
  • 無內建的本地化支援

原始 README

以下為關聯原始碼儲存庫的 README 原文快照,最新內容請造訪原始碼儲存庫。

📅 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 time'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),
  allDayOverflowBuilder: (date, overflowedEvents) => /* … */,
  callbacks: TimetableCallbacks(
    // onWeekTap, onDateTap, onDateBackgroundTap, onDateTimeBackgroundTap, and
    // onMultiDateHeaderOverflowTap
  ),
  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 event starts 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.

If you have widgets outside of timetable that can be dragged into timetable, you have to give your MultiDateContent and each PartDayDraggableEvent a geometryKey. A geometryKey is a GlobalKey<MultiDateContentGeometry> with which the current drag offset can be converted to a DateTime.

final geometryKey = GlobalKey<MultiDateContentGeometry>();

final timetable = MultiDateTimetable(contentGeometryKey: geometryKey);
// Or `MultiDateContent(geometryKey: geometryKey)` if you build your timetable
// from the provided, modular widgets.

final draggableEvent = PartDayDraggableEvent.forGeometryKeys(
  {geometryKey},
  // `child`, `childWhileDragging`, and the callbacks are available here as
  // well.
);

// Alternatively, you can manually convert an offset to a `DateTime:`
final dateTime = geometryKey.currentState!.resolveOffset(globalOffset);

You could even offer to drag the event into one of multiple timetables: Give each timetable its own geometryKey and pass all of them to PartDayDraggableEvent.forGeometryKeys. In the callbacks, you receive the geometryKey of the timetable that the event is currently being dragged over. See PartDayDraggableEvent.geometryKeys for the exact behavior.

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.

所屬分類

依賴

依賴清單 7 項

原始碼儲存庫

使用此套件的專案

暫無相關資料。