FlutterCalendarWidget
A calendar control on Flutter can be customized to look as you want. Making the address
introduce
I wrote an open source library for the Flutter calendar. Recently, I added some features, refactoring the code, and some performance optimizations. (The previous code is really ****, no state frame, but also a variety of nested code)
The sample
Calendar supports Web preview: Click here for preview
The main function
- Support the Gregorian calendar, lunar calendar, solar terms, traditional festivals, common holidays
- Date range Settings. The maximum date range supported by default is 1971.01-2055.12
- Disable the setting of date range. For example, you can click the date in a certain range and turn off the date outside the range
- Supports single or multiple callbacks. Multiple callbacks that exceed the specified number of callbacks are supported.
- Jump to a specified date, default support animation switch
- Custom calendar items, support the way of combining widgets and drawing with canvas
- Customize the WeekBar at the top
- Depending on the actual scenario, you can add additional custom data to Item to achieve various additional functions. For example, the implementation of the progress bar style calendar, the realization of the calendar of various marks
- Supports weekly view display
- Display and switch linkage between month and week views
The recent changes
[1.0.0] – 2019/10/10
- Refactoring calendar code for performance optimization
- Create the Configuration class and place the configuration information here
- Introduce provider state management, avoid various nested transfers of data, and implement local refreshes
- Realize the weekly view and the linkage between the weekly view and the monthly view. Use IndexStack to wrap the two weekly and monthly views. Switch to changing the index of IndexStack
- DateModel adds isCurrentMonth to draw the month view to mask days that are not in the current month. IsCurrentMonth is false for days preceding or following the current month.
- Click item to refresh, and control the refresh range: refresh only two items, the current item and the previous item, in radio mode. In multi-select mode, only the selected item is refreshed.
- Data initialization of DateModel, some properties lazily loaded using get method
[0.0.1] – 2019/5/19.
- Support the Gregorian calendar, lunar calendar, solar terms, traditional festivals, common holidays
- Date range Settings. The maximum date range supported by default is 1971.01-2055.12
- Disable the setting of date range. For example, you can click the date in a certain range and turn off the date outside the range
- Supports single or multiple callbacks. Multiple callbacks that exceed the specified number of callbacks are supported.
- Jump to a specified date, default support animation switch
- Custom calendar items, support the way of combining widgets and drawing with canvas
- Customize the WeekBar at the top
- You can add custom extra data to an Item for various additional functions. Like implementing a progress bar style calendar
use
Add dependencies to pubspec.yaml:
flutter_custom_calendar:
git:
url: https://github.com/LXD312569496/flutter_custom_calendar.git
Copy the code
With the introduction of flutter_CUSTOM_calendar, you can use the CalendarViewWidget and configure the CalendarController.
import 'package:flutter_custom_calendar/flutter_custom_calendar.dart';
CalendarViewWidget({@required this.calendarController, this.boxDecoration});
Copy the code
- BoxDecoration is used to configure the overall background
- Use the CalendarController to configure some data, and you can use the CalendarController to perform operations or event listening, such as scrolling to the next month, retrieving the currently selected items, and so on.
Configuration CalendarController
Below are some of the attributes in CalendarController that support custom configuration. If no value is specified, the default value will be used. (The Configuration is now done in the Controller, and the configured data will be divided into the Configuration class.)
The meaning of configuration includes three aspects.
- One is to display the relevant data needed for the calendar,
- One is the configuration of a custom UI that displays the calendar,
- One is to configure calendar listening events.
// Constructor CalendarController({int selectMode = Constants.MODE_SINGLE_SELECT, int showMode = Constants.MODE_SHOW_ONLY_MONTH, bool expandStatus =true,
DayWidgetBuilder dayWidgetBuilder = defaultCustomDayWidget,
WeekBarItemWidgetBuilder weekBarItemWidgetBuilder = defaultWeekBarWidget,
int minYear = 1971,
int maxYear = 2055,
int minYearMonth = 1,
int maxYearMonth = 12,
int nowYear = -1,
int nowMonth = -1,
int minSelectYear = 1971,
int minSelectMonth = 1,
int minSelectDay = 1,
int maxSelectYear = 2055,
int maxSelectMonth = 12,
int maxSelectDay = 30,
Set<DateTime> selectedDateTimeList = EMPTY_SET,
DateModel selectDateModel,
int maxMultiSelectCount = 9999,
double verticalSpacing = 10,
bool enableExpand = true,
Map<DateModel, Object> extraDataMap = EMPTY_MAP})
Copy the code
Data configuration
attribute | meaning | The default value |
---|---|---|
selectMode | Select mode: single or multiple options | The default is radio static const int MODE_SINGLE_SELECT = 1; static const int MODE_MULTI_SELECT = 2; |
showMode | Display mode | The default is to show only the monthly view static const int MODE_SHOW_ONLY_MONTH=1; // Only monthly views are supported static const int MODE_SHOW_ONLY_WEEK=2; // Only the weekly view is supported static const int MODE_SHOW_WEEK_AND_MONTH=3; // Support switching between monthly and weekly views |
minYear | The minimum year displayed on the calendar | 1971 |
maxYear | The maximum year displayed on the calendar | 2055 |
minYearMonth | The month of the smallest year displayed on the calendar | 1 |
maxYearMonth | The month of the maximum year displayed on the calendar | 12 |
nowYear | The calendar displays the current year | – 1 |
nowMonth | Calendar displays the current month | – 1 |
minSelectYear | The minimum year you can select | 1971 |
minSelectMonth | Month of the smallest year you can select | 1 |
minSelectDay | The date of the smallest month you can choose | 1 |
maxSelectYear | Maximum year you can select | 2055 |
maxSelectMonth | Month of the maximum year you can select | 12 |
maxSelectDay | The date of the maximum month you can choose | 30, note: cannot exceed the total number of days in the corresponding month |
selectedDateList | The date selected for multiple selections | Default is null Set, Set selectedDateList = new Set() |
selectDateModel | Current option for radio selection | The default is empty |
maxMultiSelectCount | Multiple choices, maximum number of choices | hhh |
extraDataMap | Customize additional data | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
Configuration related to UI drawing
attribute | meaning | The default value |
---|---|---|
weekBarItemWidgetBuilder | Create the weekbar at the top | The default styles |
dayWidgetBuilder | Create calendar Item | The default styles |
verticalSpacing | The vertical spacing between calendar items | The default 10 |
boxDecoration | Overall background setting | |
itemSize | The side length of each item | The default is screen width /7 |
Configuration of event listening
methods | meaning | The default value |
---|---|---|
void addMonthChangeListener(OnMonthChange listener) | Month switch event | |
void addOnCalendarSelectListener(OnCalendarSelect listener) | I’m gonna go ahead and select the event | |
void addOnMultiSelectOutOfRangeListener(OnMultiSelectOutOfRange listener) | Multiple selection exceeds the specified range | |
void addOnMultiSelectOutOfSizeListener(OnMultiSelectOutOfSize listener) | The number of multiple selections exceeds the limit | |
void addExpandChangeListener(ValueChanged expandChange) | Listen for the calendar to expand and shrink |
Use controller to control calendar switching, support configuration animation
methods | meaning | The default value |
---|---|---|
Future previousPage() | Sliding to the previous page will automatically slide to the previous month or week based on the current expansion status. Returns false if it is already on the first page without the previous one, or true in other cases | |
Future nextPage() | Sliding to the next page will automatically slide to the next month or week, depending on the current state of expansion. Returns false if there is no next page on the last page, true otherwise | |
void moveToCalendar(int year, int month, int day, {bool needAnimation = false,Duration duration = const Duration(milliseconds: 500),Curve curve = Curves.ease}) | To specified date | |
void moveToNextYear() | Switch to the next year | |
void moveToPreviousYear() | Switch to the previous year | |
void moveToNextMonth() | Switch to the next month | |
void moveToPreviousMonth() | Switch to the previous month | |
void toggleExpandStatus() | Switching state |
Use the Controller to get some data information about the calendar
methods | meaning | The default value |
---|---|---|
DateTime getCurrentMonth() | Gets the current month | |
Set getMultiSelectCalendar() | Gets the selected date, multiple options | |
DateModel getSingleSelectCalendar() | Gets the selected date, single |
How do I customize the UI
This includes custom weekbars, custom calendar items, and DefaultXXXWidget.
Just inherit the corresponding Base class, implement the corresponding method, and then just implement the corresponding Builder method when configuring the Controller.
// Support custom drawing DayWidgetBuilder; // Create calendar item WeekBarItemWidgetBuilder WeekBarItemWidgetBuilder; // Create the weekbar at the topCopy the code
Custom WeekBar
Inherit BaseWeekBar and override getWeekBarItem(index). You can implement it however you want, just return a Widget.
class DefaultWeekBar extends BaseWeekBar { const DefaultWeekBar({Key key}) : super(key: key); @override Widget getWeekBarItem(int index) {/** * Custom Widget */returnnew Container( height: 40, alignment: Alignment.center, child: new Text( Constants.WEEK_LIST[index], style: topWeekTextStyle, ), ); }}Copy the code
Custom calendar Item:
Two methods are provided: one is to create a widget by combining widgets, and the other is to draw items by customization using Canvas. Finally, you just need to configure in the CalendarController’s construction parameters.
- Inherit the BaseCombineDayWidget, override getNormalWidget(DateModel DateModel) and getSelectedWidget(DateModel DateModel), and return the corresponding widget.
class DefaultCombineDayWidget extends BaseCombineDayWidget { DefaultCombineDayWidget(DateModel dateModel) : super(dateModel); @override Widget getNormalWidget(DateModel DateModel) {// Implement default UI} @override Widget getSelectedWidget(DateModel) DateModel) {// Draw the selected UI}}Copy the code
- Inherit the BaseCustomDayWidget and override the drawNormal and drawSelected methods to draw the Item on the Canvas.
class DefaultCustomDayWidget extends BaseCustomDayWidget { DefaultCustomDayWidget(DateModel dateModel) : super(dateModel); @override void drawNormal(DateModel DateModel, Canvas Canvas, Size Size) {override void drawNormal(DateModel, Canvas Canvas, Size Size) { canvas, size); } @override void drawSelected(DateModel dateModel, Canvas canvas, // Draw the selected UI defaultDrawSelected(dateModel, canvas, Size); }}Copy the code
Customize additional data extraData according to actual scenarios
Customize progress bar data for each item
< dateModel, int> progressMap = {datemodel.fromdatetime (temp.add(Duration(days: 1))): 0, DateModel.fromDateTime(temp.add(Duration(days: 2))): 20, DateModel.fromDateTime(temp.add(Duration(days: 3))): 40, DateModel.fromDateTime(temp.add(Duration(days: 4))): 60, DateModel.fromDateTime(temp.add(Duration(days: 5))): 80, DateModel.fromDateTime(temp.add(Duration(days: 6))): 100, }; // Add extraDataMap to CalendarController(extraDataMap: Int progress = datemodel.extradata; progressMap = datemodel.extradata;Copy the code
Customize various tags
// External processing of each dateModel tag Map< dateModel, String> customExtraData = { DateModel.fromDateTime(DateTime.now().add(Duration(days: -1))):"False",
DateModel.fromDateTime(DateTime.now().add(Duration(days: -2))): "Swim",
DateModel.fromDateTime(DateTime.now().add(Duration(days: -3))): "Things",
DateModel.fromDateTime(DateTime.now().add(Duration(days: -4))): "Class",
DateModel.fromDateTime(DateTime.now().add(Duration(days: -5))): "False",
DateModel.fromDateTime(DateTime.now().add(Duration(days: -6))): "Swim",
DateModel.fromDateTime(DateTime.now().add(Duration(days: 2))): "Swim",
DateModel.fromDateTime(DateTime.now().add(Duration(days: 3))): "Things",
DateModel.fromDateTime(DateTime.now().add(Duration(days: 4))): "Class",
DateModel.fromDateTime(DateTime.now().add(Duration(days: 5))): "False",
DateModel.fromDateTime(DateTime.now().add(Duration(days: 6))): "Swim",
DateModel.fromDateTime(DateTime.now().add(Duration(days: 7))): "Things",
DateModel.fromDateTime(DateTime.now().add(Duration(days: 8))): "Class"}; // Add extraDataMap to CalendarController(extraDataMap: // When drawing the DayWidget, you can get the desired data directly from the dateModel extraData object. String data = datemodel. extraData;Copy the code
DateModel entity class
The entity class DateModel for dates used in the calendar has the following attributes. When you customize a DayWidget, you can draw the UI based on its properties.
attribute | meaning | type | The default value |
---|---|---|---|
year | year | int | |
month | in | int | |
day | The date of | int | The default is 1 |
lunarYear | Chinese New Year | int | |
lunarMonth | The lunar month | int | |
lunarDay | According to the lunar calendar date | int | |
lunarString | Lunar string | String | |
solarTerm | 24 solar terms | String | |
gregorianFestival | gregorianFestival | String | |
traditionFestival | Traditional Lunar Festivals | String | |
isCurrentDay | Is it today | bool | false |
isLeapYear | Is it a leap year | bool | false |
isWeekend | Is it the weekend | bool | false |
isInRange | Whether it is within the range, for example, it can implement the function of setting gray outside a certain range | bool | false |
isSelected | Is selected to implement some tag or selection function | bool | false |
extraData | Custom additional data | Object | The default is empty |
methods | meaning |
---|---|
DateTime getDateTime() | Convert DateModel to DateTime |
DateModel fromDateTime(DateTime dateTime) | Create the corresponding model based on DateTime and initialize the information of lunar and traditional festivals |
bool operator ==(Object other) | Override the == method to determine if two dateModel are the same day |