├── CHANGELOG.md ├── test └── flutter_event_calendar_test.dart ├── example ├── ios │ ├── Runner │ │ ├── Runner-Bridging-Header.h │ │ ├── Assets.xcassets │ │ │ ├── LaunchImage.imageset │ │ │ │ ├── LaunchImage.png │ │ │ │ ├── LaunchImage@2x.png │ │ │ │ ├── LaunchImage@3x.png │ │ │ │ ├── README.md │ │ │ │ └── Contents.json │ │ │ └── AppIcon.appiconset │ │ │ │ ├── Icon-App-20x20@1x.png │ │ │ │ ├── Icon-App-20x20@2x.png │ │ │ │ ├── Icon-App-20x20@3x.png │ │ │ │ ├── Icon-App-29x29@1x.png │ │ │ │ ├── Icon-App-29x29@2x.png │ │ │ │ ├── Icon-App-29x29@3x.png │ │ │ │ ├── Icon-App-40x40@1x.png │ │ │ │ ├── Icon-App-40x40@2x.png │ │ │ │ ├── Icon-App-40x40@3x.png │ │ │ │ ├── Icon-App-60x60@2x.png │ │ │ │ ├── Icon-App-60x60@3x.png │ │ │ │ ├── Icon-App-76x76@1x.png │ │ │ │ ├── Icon-App-76x76@2x.png │ │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ │ ├── Icon-App-83.5x83.5@2x.png │ │ │ │ └── Contents.json │ │ ├── AppDelegate.swift │ │ ├── Base.lproj │ │ │ ├── Main.storyboard │ │ │ └── LaunchScreen.storyboard │ │ └── Info.plist │ ├── Flutter │ │ ├── Debug.xcconfig │ │ ├── Release.xcconfig │ │ └── AppFrameworkInfo.plist │ ├── Runner.xcodeproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── WorkspaceSettings.xcsettings │ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── WorkspaceSettings.xcsettings │ │ │ └── IDEWorkspaceChecks.plist │ ├── .gitignore │ └── Podfile ├── android │ ├── gradle.properties │ ├── app │ │ ├── src │ │ │ ├── main │ │ │ │ ├── res │ │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── drawable │ │ │ │ │ │ └── launch_background.xml │ │ │ │ │ └── values │ │ │ │ │ │ └── styles.xml │ │ │ │ ├── kotlin │ │ │ │ │ └── ir │ │ │ │ │ │ └── faridfr │ │ │ │ │ │ └── flutter_event_calendar_example │ │ │ │ │ │ └── MainActivity.kt │ │ │ │ └── AndroidManifest.xml │ │ │ ├── debug │ │ │ │ └── AndroidManifest.xml │ │ │ └── profile │ │ │ │ └── AndroidManifest.xml │ │ └── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ ├── .gitignore │ ├── settings.gradle │ └── build.gradle ├── assets │ ├── fonts │ │ ├── IRANSansMobile_Black.ttf │ │ └── DancingScript_VariableFont_wght.ttf │ ├── back.svg │ ├── language_icon.svg │ ├── color_filter.svg │ └── calendar.svg ├── lib │ ├── models │ │ ├── calendar_color_model.dart │ │ ├── expanded_item_model.dart │ │ └── calendar_event_model.dart │ ├── main.dart │ ├── injection.dart │ └── widgets │ │ ├── setting │ │ ├── setting.dart │ │ ├── date_picker_item.dart │ │ ├── radio_button_list.dart │ │ ├── item_setting.dart │ │ ├── expanded_card_setting.dart │ │ ├── header_special_days.dart │ │ ├── options.dart │ │ ├── calendar_options.dart │ │ ├── header_options.dart │ │ └── date_picker.dart │ │ ├── event_calendar │ │ ├── home_page.dart │ │ └── event_calendar.dart │ │ ├── color │ │ ├── calendar_color_item.dart │ │ └── color_picker_row.dart │ │ └── code_preview │ │ └── code_preview.dart ├── .metadata ├── README.md ├── .gitignore └── pubspec.yaml ├── assets ├── eventCalendar.gif ├── event_calendar_options.png └── flutter_event_calendar.png ├── SECURITY.md ├── lib ├── src │ ├── models │ │ ├── style │ │ │ ├── selected_day_options.dart │ │ │ ├── select_year_options.dart │ │ │ ├── select_month_options.dart │ │ │ ├── event_options.dart │ │ │ ├── headers_options.dart │ │ │ └── day_options.dart │ │ ├── event.dart │ │ ├── calendar_options.dart │ │ └── datetime.dart │ ├── utils │ │ ├── calendar_types.dart │ │ └── style_provider.dart │ ├── widgets │ │ ├── event_card.dart │ │ ├── select_year.dart │ │ ├── events.dart │ │ ├── select_day.dart │ │ ├── select_month.dart │ │ ├── day.dart │ │ ├── calendar_daily.dart │ │ └── header.dart │ ├── providers │ │ ├── instance_provider.dart │ │ └── calendars │ │ │ ├── calendar_provider.dart │ │ │ ├── gregorian_calendar.dart │ │ │ └── jalali_calendar.dart │ ├── dictionaries │ │ ├── dictionary.dart │ │ ├── fa.dart │ │ ├── en.dart │ │ ├── pt.dart │ │ └── de.dart │ └── handlers │ │ ├── event_selector.dart │ │ ├── calendar_monthly_utils.dart │ │ ├── translator.dart │ │ ├── calendar_utils.dart │ │ └── event_calendar.dart └── flutter_event_calendar.dart ├── .metadata ├── pubspec.yaml ├── .github ├── PULL_REQUEST_TEMPLATE.md └── ISSUE_TEMPLATE │ ├── feature_request.yaml │ └── bug_report.yaml ├── LICENSE ├── .vscode └── launch.json ├── .gitignore ├── pubspec.lock ├── CODE_OF_CONDUCT.md └── README.md /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [1.0.0] - Version 1.0.0 released -------------------------------------------------------------------------------- /test/flutter_event_calendar_test.dart: -------------------------------------------------------------------------------- 1 | void main() { 2 | // todo 3 | } 4 | -------------------------------------------------------------------------------- /example/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /assets/eventCalendar.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/novaday-co/flutter_event_calendar/HEAD/assets/eventCalendar.gif -------------------------------------------------------------------------------- /assets/event_calendar_options.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/novaday-co/flutter_event_calendar/HEAD/assets/event_calendar_options.png -------------------------------------------------------------------------------- /assets/flutter_event_calendar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/novaday-co/flutter_event_calendar/HEAD/assets/flutter_event_calendar.png -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.enableR8=true 3 | android.useAndroidX=true 4 | android.enableJetifier=true 5 | -------------------------------------------------------------------------------- /example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Reporting a Vulnerability 4 | 5 | For reporting a vulnerability you can send an email to froozan[at]yahoo.com 6 | -------------------------------------------------------------------------------- /example/assets/fonts/IRANSansMobile_Black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/novaday-co/flutter_event_calendar/HEAD/example/assets/fonts/IRANSansMobile_Black.ttf -------------------------------------------------------------------------------- /example/assets/fonts/DancingScript_VariableFont_wght.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/novaday-co/flutter_event_calendar/HEAD/example/assets/fonts/DancingScript_VariableFont_wght.ttf -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/novaday-co/flutter_event_calendar/HEAD/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/novaday-co/flutter_event_calendar/HEAD/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/novaday-co/flutter_event_calendar/HEAD/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/novaday-co/flutter_event_calendar/HEAD/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/novaday-co/flutter_event_calendar/HEAD/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/novaday-co/flutter_event_calendar/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/novaday-co/flutter_event_calendar/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/novaday-co/flutter_event_calendar/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/novaday-co/flutter_event_calendar/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/novaday-co/flutter_event_calendar/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/novaday-co/flutter_event_calendar/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/novaday-co/flutter_event_calendar/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/novaday-co/flutter_event_calendar/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/novaday-co/flutter_event_calendar/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/novaday-co/flutter_event_calendar/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/novaday-co/flutter_event_calendar/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/novaday-co/flutter_event_calendar/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/novaday-co/flutter_event_calendar/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/novaday-co/flutter_event_calendar/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/novaday-co/flutter_event_calendar/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/novaday-co/flutter_event_calendar/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/novaday-co/flutter_event_calendar/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/novaday-co/flutter_event_calendar/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /lib/src/models/style/selected_day_options.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class DayOptions{ 4 | String font; 5 | Color? selectedColor; 6 | 7 | DayOptions({this.font = '', this.selectedColor}); 8 | } 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/app/src/main/kotlin/ir/faridfr/flutter_event_calendar_example/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package ir.faridfr.flutter_event_calendar_example 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /lib/src/models/style/select_year_options.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class YearOptions{ 4 | String font; 5 | Color? selectedColor; 6 | Color? backgroundColor; 7 | 8 | YearOptions({this.font = '', this.selectedColor,this.backgroundColor}); 9 | } -------------------------------------------------------------------------------- /lib/src/models/style/select_month_options.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class MonthOptions{ 4 | String font; 5 | Color? selectedColor; 6 | Color? backgroundColor; 7 | 8 | MonthOptions({this.font = '', this.selectedColor,this.backgroundColor}); 9 | } -------------------------------------------------------------------------------- /lib/src/utils/calendar_types.dart: -------------------------------------------------------------------------------- 1 | enum CalendarType { JALALI, GREGORIAN } 2 | enum ViewType { DAILY, MONTHLY } 3 | enum MonthStringTypes { FULL, SHORT } 4 | enum WeekDayStringTypes { FULL, SHORT } 5 | enum PartFormat { MONTH, DAY, YEAR } 6 | enum DayEventCounterViewType { DOT, LABEL } 7 | -------------------------------------------------------------------------------- /example/lib/models/calendar_color_model.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class CalendarColorModel { 4 | String title; 5 | Color color; 6 | Widget body; 7 | CalendarColorModel( 8 | {required this.title, required this.color, required this.body}); 9 | } 10 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip 7 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 216dee60c0cc9449f0b29bcf922974d612263e24 8 | channel: stable 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 216dee60c0cc9449f0b29bcf922974d612263e24 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /example/assets/back.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /example/lib/models/expanded_item_model.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class ExpandedItemModel { 4 | const ExpandedItemModel( 5 | {required this.title, 6 | required this.body, 7 | required this.icon, 8 | required this.definition}); 9 | final String title; 10 | final String icon; 11 | final Widget body; 12 | final String definition; 13 | } 14 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /lib/flutter_event_calendar.dart: -------------------------------------------------------------------------------- 1 | library flutter_event_calendar; 2 | 3 | export 'src/handlers/event_calendar.dart'; 4 | export 'src/models/calendar_options.dart'; 5 | export 'src/models/datetime.dart'; 6 | export 'src/models/event.dart'; 7 | export 'src/models/style/day_options.dart'; 8 | export 'src/models/style/event_options.dart'; 9 | export 'src/models/style/headers_options.dart'; 10 | export 'src/utils/calendar_types.dart'; 11 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 4 | def properties = new Properties() 5 | 6 | assert localPropertiesFile.exists() 7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 8 | 9 | def flutterSdkPath = properties.getProperty("flutter.sdk") 10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 12 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_event_calendar 2 | description: Gregorian and Jalali Event calendar for flutter with options for change style 3 | version: 1.0.0 4 | homepage: https://github.com/novaday-co/flutter_event_calendar 5 | 6 | environment: 7 | sdk: ">=2.12.0 <3.0.0" 8 | flutter: ">=1.17.0" 9 | 10 | dependencies: 11 | shamsi_date: ^0.15.0 12 | scoped_model: ^2.0.0 13 | flutter: 14 | sdk: flutter 15 | collection: ^1.16.0 16 | 17 | dev_dependencies: 18 | flutter_test: 19 | sdk: flutter 20 | 21 | flutter: 22 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_event_calendar_example/injection.dart'; 3 | import 'package:flutter_event_calendar_example/widgets/event_calendar/home_page.dart'; 4 | 5 | 6 | void main() { 7 | setUp(); 8 | runApp(MyApp()); 9 | } 10 | 11 | class MyApp extends StatelessWidget { 12 | const MyApp({ 13 | Key? key, 14 | }) : super(key: key); 15 | 16 | 17 | 18 | 19 | @override 20 | Widget build(BuildContext context) { 21 | return MaterialApp( 22 | home: HomePage(), 23 | ); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /lib/src/models/event.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import '../../flutter_event_calendar.dart'; 3 | 4 | class Event { 5 | late int listIndex; 6 | late Widget child; 7 | late CalendarDateTime dateTime; 8 | late Function? onTap; 9 | late Function? onLongPress; 10 | 11 | Event({ 12 | required this.child, 13 | required this.dateTime, 14 | onTap(int listIndex)?, 15 | onLongPress, 16 | }) { 17 | this.onTap = onTap; 18 | this.onLongPress = onLongPress ?? 19 | (int listIndex) { 20 | print('LongPress ' + listIndex.toString()); 21 | }; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /lib/src/widgets/event_card.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../models/event.dart'; 4 | 5 | class EventCard extends StatelessWidget { 6 | Event fullCalendarEvent; 7 | 8 | EventCard({required this.fullCalendarEvent}); 9 | 10 | @override 11 | Widget build(BuildContext context) { 12 | return GestureDetector( 13 | onTap: (() { 14 | fullCalendarEvent.onTap?.call(fullCalendarEvent.listIndex); 15 | }), 16 | onLongPress: (() { 17 | fullCalendarEvent.onLongPress?.call(fullCalendarEvent.listIndex); 18 | }), 19 | child: fullCalendarEvent.child, 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # flutter_event_calendar_example 2 | 3 | Example for Flutter Event Calendar package 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) 13 | 14 | For help getting started with Flutter, view our 15 | [online documentation](https://flutter.dev/docs), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /example/ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/app.flx 22 | Flutter/app.zip 23 | Flutter/flutter_assets/ 24 | Flutter/flutter_export_environment.sh 25 | ServiceDefinitions.json 26 | Runner/GeneratedPluginRegistrant.* 27 | 28 | # Exceptions to above rules. 29 | !default.mode1v3 30 | !default.mode2v3 31 | !default.pbxuser 32 | !default.perspectivev3 33 | -------------------------------------------------------------------------------- /lib/src/providers/instance_provider.dart: -------------------------------------------------------------------------------- 1 | import '../../flutter_event_calendar.dart'; 2 | import 'calendars/calendar_provider.dart'; 3 | import 'calendars/gregorian_calendar.dart'; 4 | import 'calendars/jalali_calendar.dart'; 5 | 6 | CalendarProvider createInstance(CalendarType cType) { 7 | final Map _factories = { 8 | CalendarType.JALALI: JalaliCalendar(), 9 | CalendarType.GREGORIAN: GregorianCalendar() 10 | }; 11 | if (!_factories.keys.contains(cType)) { 12 | throw Exception( 13 | "Cannot create instance of calendar, check available calendar types or create your own calendar that implements BaseCalendarProvider"); 14 | } 15 | 16 | return _factories[cType]!; 17 | } 18 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.6.10' 3 | repositories { 4 | google() 5 | jcenter() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:3.5.0' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | jcenter() 18 | } 19 | } 20 | 21 | rootProject.buildDir = '../build' 22 | subprojects { 23 | project.buildDir = "${rootProject.buildDir}/${project.name}" 24 | } 25 | subprojects { 26 | project.evaluationDependsOn(':app') 27 | } 28 | 29 | task clean(type: Delete) { 30 | delete rootProject.buildDir 31 | } 32 | -------------------------------------------------------------------------------- /lib/src/models/style/event_options.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:scoped_model/scoped_model.dart'; 3 | 4 | class EventOptions extends Model { 5 | String? emptyText; 6 | Color emptyTextColor; 7 | IconData emptyIcon; 8 | Color emptyIconColor; 9 | bool Function()? showLoadingForEvent; 10 | Widget Function()? loadingWidget; 11 | 12 | EventOptions({ 13 | this.emptyText, 14 | this.showLoadingForEvent, 15 | this.loadingWidget, 16 | this.emptyTextColor = const Color(0xffe5e5e5), 17 | this.emptyIcon = Icons.reorder, 18 | this.emptyIconColor = const Color(0xffebebeb), 19 | }); 20 | 21 | static EventOptions of(BuildContext context) => 22 | ScopedModel.of(context); 23 | } 24 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | ### Please confirm this pull request meets the following requirements: 3 | 4 | - [ ] I tested my code and it is running perfectly 5 | - [ ] I updated `README.md` and `example\lib\main.dart` due to the changes 6 | 7 | ### Which change are you proposing? 8 | 9 | - [ ] Suggesting edits to an existing style or feature 10 | - [ ] Curating a new feature 11 | - [ ] Something that does not neatly fit into the binary options above 12 | 13 | --- 14 | 15 | > Please replace this line with an explanation of why you think these changes should be made. 16 | 17 | --- 18 | 19 | **Please note: we will close your PR without comment if you do not check the boxes above and provide ALL requested information.** -------------------------------------------------------------------------------- /example/lib/models/calendar_event_model.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_event_calendar/flutter_event_calendar.dart'; 2 | import 'package:equatable/equatable.dart'; 3 | 4 | class CalendarEventModel extends Equatable { 5 | String calendarLanguage; 6 | CalendarType calendarType; 7 | CalendarOptions calendarOptions; 8 | HeaderOptions headerOptions; 9 | DayOptions dayOptions; 10 | List specialDays; 11 | CalendarEventModel( 12 | {required this.calendarLanguage, 13 | required this.calendarType, 14 | required this.calendarOptions, 15 | required this.headerOptions, 16 | required this.dayOptions, 17 | required this.specialDays}); 18 | 19 | @override 20 | List get props => [specialDays]; 21 | } 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yaml: -------------------------------------------------------------------------------- 1 | name: 🚀🆕 Feature Request 2 | description: Suggest an feature / idea for this project 3 | title: "[Feature Request / Suggestion]: " 4 | labels: ["enhancement"] 5 | assignees: 6 | - faridfr 7 | body: 8 | - type: markdown 9 | attributes: 10 | value: | 11 | We appreciate your feedback on how to improve this project. Please be sure to include as much details & any resources if possible! 12 | - type: textarea 13 | id: Suggestion 14 | attributes: 15 | label: Suggestion / Feature Request 16 | description: Describe the feature(s) you would like to see added. 17 | placeholder: Tell us your suggestion 18 | value: "Your suggestion here" 19 | validations: 20 | required: true 21 | 22 | -------------------------------------------------------------------------------- /example/assets/language_icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /lib/src/models/style/headers_options.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import '../../../flutter_event_calendar.dart'; 3 | import 'package:scoped_model/scoped_model.dart'; 4 | 5 | class HeaderOptions extends Model { 6 | WeekDayStringTypes weekDayStringType; 7 | MonthStringTypes monthStringType; 8 | Color headerTextColor; 9 | Color navigationColor; 10 | Color resetDateColor; 11 | Color calendarIconColor; 12 | 13 | HeaderOptions( 14 | {this.weekDayStringType = WeekDayStringTypes.FULL, 15 | this.monthStringType = MonthStringTypes.SHORT, 16 | this.headerTextColor = Colors.black, 17 | this.resetDateColor = Colors.black, 18 | this.navigationColor = Colors.black, 19 | this.calendarIconColor = Colors.black, 20 | }); 21 | 22 | static HeaderOptions of(BuildContext context) => ScopedModel.of(context); 23 | } 24 | -------------------------------------------------------------------------------- /lib/src/providers/calendars/calendar_provider.dart: -------------------------------------------------------------------------------- 1 | import '../../../flutter_event_calendar.dart'; 2 | 3 | abstract class CalendarProvider { 4 | bool isRTL(); 5 | 6 | Map getMonthDays(WeekDayStringTypes type, int index); 7 | 8 | Map getMonthDaysShort(int index); 9 | 10 | CalendarDateTime getNextMonthDateTime(); 11 | 12 | CalendarDateTime getPreviousMonthDateTime(); 13 | 14 | CalendarDateTime getNextDayDateTime(); 15 | 16 | CalendarDateTime getPreviousDayDateTime(); 17 | 18 | CalendarDateTime getDateTime(); 19 | 20 | String getFormattedDate({DateTime? customDate}); 21 | 22 | CalendarDateTime goToMonth(index); 23 | 24 | CalendarDateTime goToDay(index); 25 | 26 | CalendarDateTime goToYear(int index); 27 | 28 | int getDateTimePart(PartFormat format); 29 | 30 | List getYears(); 31 | List getDayAmount(); 32 | CalendarType getCalendarType(); 33 | } 34 | -------------------------------------------------------------------------------- /lib/src/models/calendar_options.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import '../../flutter_event_calendar.dart'; 3 | import 'package:scoped_model/scoped_model.dart'; 4 | 5 | class CalendarOptions extends Model { 6 | bool toggleViewType; 7 | ViewType viewType; 8 | String font; 9 | Color? headerMonthBackColor; 10 | Color? headerMonthShadowColor; 11 | double? headerMonthElevation; 12 | ShapeBorder? headerMonthShape; 13 | Color? bottomSheetBackColor; 14 | 15 | CalendarOptions( 16 | {this.toggleViewType = false, 17 | this.viewType = ViewType.MONTHLY, 18 | this.headerMonthBackColor, 19 | this.headerMonthShadowColor, 20 | this.headerMonthElevation, 21 | this.headerMonthShape, 22 | this.font = '', 23 | this.bottomSheetBackColor=Colors.white}); 24 | 25 | static CalendarOptions of(BuildContext context) => ScopedModel.of(context); 26 | } 27 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | 43 | # Exceptions to above rules. 44 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 45 | -------------------------------------------------------------------------------- /example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 9.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /lib/src/dictionaries/dictionary.dart: -------------------------------------------------------------------------------- 1 | import 'en.dart'; 2 | import 'fa.dart'; 3 | import 'pt.dart'; 4 | import 'de.dart'; 5 | 6 | Map fullMonthNames = { 7 | ...Fa.fullMonthNames, 8 | ...En.fullMonthNames, 9 | ...Pt.fullMonthNames, 10 | ...De.fullMonthNames, 11 | }; 12 | 13 | Map shortMonthNames = { 14 | ...Fa.shortMonthNames, 15 | ...En.shortMonthNames, 16 | ...Pt.shortMonthNames, 17 | ...De.shortMonthNames, 18 | }; 19 | 20 | Map fullDayNames = { 21 | ...Fa.fullDayNames, 22 | ...En.fullDayNames, 23 | ...Pt.fullDayNames, 24 | ...De.fullDayNames, 25 | }; 26 | 27 | Map shortDayNames = { 28 | ...Fa.shortDayNames, 29 | ...En.shortDayNames, 30 | ...Pt.shortDayNames, 31 | ...De.shortDayNames, 32 | }; 33 | 34 | Map titles = { 35 | ...Fa.titles, 36 | ...En.titles, 37 | ...Pt.titles, 38 | ...De.titles, 39 | }; 40 | 41 | Map directionIsRTL = { 42 | ...Fa.directionIsRTL, 43 | ...En.directionIsRTL, 44 | ...Pt.directionIsRTL, 45 | ...De.directionIsRTL, 46 | }; 47 | -------------------------------------------------------------------------------- /example/lib/injection.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:flutter_event_calendar/flutter_event_calendar.dart'; 4 | import 'package:get_it/get_it.dart'; 5 | 6 | import 'models/calendar_event_model.dart'; 7 | 8 | final getit = GetIt.instance; 9 | 10 | setUp() { 11 | getit.registerLazySingleton( 12 | () => HeaderOptions(monthStringType: MonthStringTypes.SHORT)); 13 | getit.registerLazySingleton( 14 | () => CalendarOptions(toggleViewType: true), 15 | ); 16 | getit.registerLazySingleton(() => DayOptions()); 17 | getit.registerLazySingleton( 18 | () => CalendarEventModel( 19 | calendarLanguage: "en", 20 | calendarType: CalendarType.GREGORIAN, 21 | headerOptions: getit(), 22 | calendarOptions: getit(), 23 | dayOptions: getit(), 24 | specialDays: [], 25 | ), 26 | ); 27 | getit.registerLazySingleton>( 28 | () => StreamController.broadcast()); 29 | } 30 | -------------------------------------------------------------------------------- /example/assets/color_filter.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /lib/src/handlers/event_selector.dart: -------------------------------------------------------------------------------- 1 | import '../../flutter_event_calendar.dart'; 2 | 3 | class EventSelector { 4 | updateEvents() { 5 | EventCalendar.selectedEvents = []; 6 | 7 | var i = 0; 8 | for (var item in EventCalendar.events) { 9 | var eventDateTimeParts = item.dateTime; 10 | var calendarDateTimeParts = EventCalendar.dateTime!; 11 | if (eventDateTimeParts.isDateEqual(calendarDateTimeParts)) { 12 | item.listIndex = i; 13 | EventCalendar.selectedEvents.add(item); 14 | } 15 | 16 | i++; 17 | } 18 | 19 | return EventCalendar.selectedEvents; 20 | } 21 | 22 | List getEventsByDayMonthYear(CalendarDateTime date) { 23 | EventCalendar.selectedEvents = []; 24 | var i = 0; 25 | for (var item in EventCalendar.events) { 26 | var eventDateTimeParts = item.dateTime; 27 | if (eventDateTimeParts.isDateEqual(date)) { 28 | item.listIndex = i; 29 | EventCalendar.selectedEvents.add(item); 30 | } 31 | i++; 32 | } 33 | 34 | return EventCalendar.selectedEvents; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_event_calendar_example 2 | description: Example for Flutter Event Calendar package 3 | 4 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev 5 | 6 | version: 1.0.0+1 7 | 8 | environment: 9 | sdk: ">=2.12.0 <3.0.0" 10 | 11 | dependencies: 12 | 13 | flutter_event_calendar: 14 | path: ../ 15 | flutter: 16 | sdk: flutter 17 | cupertino_icons: ^0.1.3 18 | flutter_svg: ^1.1.4 19 | get_it: ^7.2.0 20 | flutter_colorpicker: ^1.0.3 21 | equatable: ^2.0.5 22 | get_storage: ^2.0.3 23 | expandable: ^5.0.1 24 | widget_with_codeview: ^2.0.1+2 25 | hive: ^2.2.3 26 | flutter_syntax_view: ^4.0.0 27 | clipboard: ^0.1.3 28 | 29 | dev_dependencies: 30 | flutter_test: 31 | sdk: flutter 32 | 33 | flutter: 34 | fonts: 35 | - family: Dancing 36 | fonts: 37 | - asset: assets/fonts/DancingScript_VariableFont_wght.ttf 38 | 39 | - family: IRanSans 40 | fonts: 41 | - asset: assets/fonts/IRANSansMobile_Black.ttf 42 | assets: 43 | - assets/ 44 | 45 | 46 | uses-material-design: true 47 | -------------------------------------------------------------------------------- /example/lib/widgets/setting/setting.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_event_calendar_example/widgets/setting/options.dart'; 3 | 4 | import 'calendar_options.dart'; 5 | import 'header_options.dart'; 6 | 7 | class Setting extends StatefulWidget { 8 | Setting({ 9 | Key? key, 10 | }) : super(key: key); 11 | 12 | @override 13 | State createState() => _SettingState(); 14 | } 15 | 16 | class _SettingState extends State { 17 | @override 18 | void initState() { 19 | super.initState(); 20 | } 21 | 22 | @override 23 | Widget build(BuildContext context) { 24 | return Scaffold( 25 | backgroundColor: Color(0xffF5F5F5), 26 | body: SafeArea( 27 | child: SingleChildScrollView( 28 | child: Container( 29 | margin: EdgeInsets.symmetric(horizontal: 16), 30 | child: Column( 31 | children: [ 32 | Options(), 33 | CalendarOptions(), 34 | HeaderOptions(), 35 | ], 36 | ), 37 | ), 38 | ), 39 | ), 40 | ); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2020 Farid Froozan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yaml: -------------------------------------------------------------------------------- 1 | name: 🐞 Bug Report 2 | description: File a bug report 3 | title: "[Bug]: " 4 | labels: ["bug"] 5 | assignees: 6 | - AmirJabbari 7 | - faridfr 8 | body: 9 | - type: markdown 10 | attributes: 11 | value: | 12 | Thanks for taking the time to fill out this bug report! 13 | - type: input 14 | id: contact 15 | attributes: 16 | label: Contact Details 17 | description: How can we get in touch with you if we need more info? 18 | placeholder: ex. email@example.com 19 | validations: 20 | required: false 21 | - type: textarea 22 | id: what-happened 23 | attributes: 24 | label: What happened? 25 | description: Describe the issue here. 26 | placeholder: Tell us what you see! 27 | value: "A bug happened!" 28 | validations: 29 | required: true 30 | - type: dropdown 31 | id: operating-systems 32 | attributes: 33 | label: What type of Device are you seeing the problem on? 34 | multiple: true 35 | options: 36 | - Android 37 | - IOS 38 | - Mac 39 | - Web 40 | validations: 41 | required: true 42 | -------------------------------------------------------------------------------- /example/lib/widgets/setting/date_picker_item.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_event_calendar/flutter_event_calendar.dart'; 3 | import 'package:flutter_event_calendar/src/utils/calendar_types.dart'; 4 | 5 | class DataPickerItem extends StatefulWidget { 6 | DataPickerItem( 7 | {Key? key, 8 | required this.selectDate, 9 | required this.nameSelectDate, 10 | required this.date}) 11 | : super(key: key); 12 | Widget selectDate; 13 | final PartFormat nameSelectDate; 14 | int date; 15 | 16 | @override 17 | State createState() => _DataPickerItemState(); 18 | } 19 | 20 | class _DataPickerItemState extends State { 21 | @override 22 | Widget build(BuildContext context) { 23 | return Card( 24 | child: TextButton( 25 | onPressed: () { 26 | showModalBottomSheet( 27 | backgroundColor: Colors.transparent, 28 | context: context, 29 | builder: (BuildContext mmm) { 30 | return widget.selectDate; 31 | }, 32 | ); 33 | }, 34 | child: Text(widget.nameSelectDate.name)), 35 | ); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "flutter_event_calendar_2", 6 | "request": "launch", 7 | "type": "dart" 8 | }, 9 | { 10 | "name": "flutter_event_calendar_2 (profile mode)", 11 | "request": "launch", 12 | "type": "dart", 13 | "flutterMode": "profile" 14 | }, 15 | { 16 | "name": "flutter_event_calendar_2 (release mode)", 17 | "request": "launch", 18 | "type": "dart", 19 | "flutterMode": "release" 20 | }, 21 | { 22 | "name": "example", 23 | "cwd": "example", 24 | "request": "launch", 25 | "type": "dart" 26 | }, 27 | { 28 | "name": "example (profile mode)", 29 | "cwd": "example", 30 | "request": "launch", 31 | "type": "dart", 32 | "flutterMode": "profile" 33 | }, 34 | { 35 | "name": "example (release mode)", 36 | "cwd": "example", 37 | "request": "launch", 38 | "type": "dart", 39 | "flutterMode": "release" 40 | } 41 | ] 42 | } -------------------------------------------------------------------------------- /example/assets/calendar.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /example/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '11.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def flutter_root 14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) 15 | unless File.exist?(generated_xcode_build_settings_path) 16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" 17 | end 18 | 19 | File.foreach(generated_xcode_build_settings_path) do |line| 20 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 21 | return matches[1].strip if matches 22 | end 23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" 24 | end 25 | 26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 27 | 28 | flutter_ios_podfile_setup 29 | 30 | target 'Runner' do 31 | use_frameworks! 32 | use_modular_headers! 33 | 34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) 35 | end 36 | 37 | post_install do |installer| 38 | installer.pods_project.targets.each do |target| 39 | flutter_additional_ios_build_settings(target) 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /lib/src/models/style/day_options.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import '../../../flutter_event_calendar.dart'; 3 | import 'package:scoped_model/scoped_model.dart'; 4 | 5 | class DayOptions extends Model { 6 | Color weekDaySelectedColor; 7 | Color weekDayUnselectedColor; 8 | bool showWeekDay; 9 | bool compactMode; 10 | Color selectedBackgroundColor; 11 | Color unselectedBackgroundColor; 12 | Color selectedTextColor; 13 | Color disabledTextColor; 14 | Color unselectedTextColor; 15 | Color eventCounterColor; 16 | DayEventCounterViewType eventCounterViewType; 17 | Color eventCounterTextColor; 18 | bool disableFadeEffect; 19 | bool disableDaysBeforeNow; 20 | double dayFontSize; 21 | 22 | DayOptions({ 23 | this.weekDaySelectedColor = Colors.red, 24 | this.weekDayUnselectedColor = Colors.black38, 25 | this.selectedBackgroundColor = const Color(0xff3AC3E2), 26 | this.unselectedBackgroundColor = Colors.transparent, 27 | this.selectedTextColor = Colors.white, 28 | this.showWeekDay = true, 29 | this.compactMode = false, 30 | this.disableDaysBeforeNow = false, 31 | this.disableFadeEffect = false, 32 | this.disabledTextColor = Colors.grey, 33 | this.unselectedTextColor = Colors.black, 34 | this.eventCounterColor = Colors.red, 35 | this.eventCounterViewType = DayEventCounterViewType.LABEL, 36 | this.eventCounterTextColor = Colors.white, 37 | this.dayFontSize = 12, 38 | }); 39 | 40 | static DayOptions of(BuildContext context) => ScopedModel.of(context); 41 | } 42 | -------------------------------------------------------------------------------- /example/lib/widgets/setting/radio_button_list.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class RadioButtonList extends StatefulWidget { 4 | RadioButtonList( 5 | {Key? key, 6 | required this.onChanged, 7 | required this.listItems, 8 | required this.initValue}) 9 | : super(key: key); 10 | 11 | Function(String keyName) onChanged; 12 | List listItems; 13 | final String initValue; 14 | 15 | @override 16 | State createState() => _RadioButtonListState(); 17 | } 18 | 19 | class _RadioButtonListState extends State { 20 | late String groubValueKey; 21 | @override 22 | void initState() { 23 | groubValueKey = widget.initValue; 24 | super.initState(); 25 | } 26 | 27 | @override 28 | Widget build(BuildContext context) { 29 | return Container( 30 | child: Column( 31 | children: [ 32 | ListView.builder( 33 | itemCount: widget.listItems.length, 34 | shrinkWrap: true, 35 | itemBuilder: (BuildContext context, int index) { 36 | return RadioListTile( 37 | title: Text(widget.listItems[index]), 38 | value: widget.listItems[index], 39 | groupValue: groubValueKey, 40 | onChanged: (value) { 41 | groubValueKey = value as String; 42 | widget.onChanged(value); 43 | setState(() {}); 44 | }, 45 | ); 46 | }, 47 | ), 48 | ], 49 | ), 50 | ); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /lib/src/handlers/calendar_monthly_utils.dart: -------------------------------------------------------------------------------- 1 | import '../../flutter_event_calendar.dart'; 2 | import 'calendar_utils.dart'; 3 | 4 | class CalendarMonthlyUtils extends CalendarUtils { 5 | static getYear(int month) { 6 | final year = CalendarUtils.getPartByInt(format: PartFormat.YEAR); 7 | return year; 8 | } 9 | 10 | static getMonth(int month) { 11 | if (month > 12) 12 | return 1; 13 | else if (month < 1) return 1; 14 | return month; 15 | } 16 | 17 | static int getFirstDayOfMonth(List dayNames, HeaderOptions headersStyle) { 18 | final currentMonth = CalendarUtils.getPartByInt(format: PartFormat.MONTH); 19 | final monthDays = CalendarUtils.getMonthDays(headersStyle.weekDayStringType, currentMonth); 20 | return dayNames.indexOf(monthDays[1]); 21 | } 22 | 23 | static String getDayNameOfMonth(HeaderOptions headersStyle, int currMonth, int index) { 24 | final dayName = EventCalendar.calendarProvider.getMonthDays(headersStyle.weekDayStringType, currMonth)[index]; 25 | return dayName; 26 | } 27 | 28 | static int getLastDayOfMonth(HeaderOptions headersStyle) { 29 | final currentMonth = CalendarUtils.getPartByInt(format: PartFormat.MONTH); 30 | return CalendarUtils.getDays(headersStyle.weekDayStringType, currentMonth).keys.last; 31 | } 32 | 33 | static int getLastMonthLastDay(HeaderOptions headersStyle) { 34 | final cMonth = CalendarUtils.getPartByInt(format: PartFormat.MONTH); 35 | if (cMonth - 1 < 1) { 36 | return -1; 37 | } 38 | return CalendarUtils.getDays(headersStyle.weekDayStringType, cMonth - 1).keys.last; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /lib/src/handlers/translator.dart: -------------------------------------------------------------------------------- 1 | import '../../flutter_event_calendar.dart'; 2 | import '../dictionaries/dictionary.dart'; 3 | 4 | class Translator { 5 | static String getPartTranslate(HeaderOptions options, format, index) { 6 | switch (format) { 7 | case PartFormat.MONTH: 8 | return _getMonthName(options.monthStringType, index); 9 | default: 10 | return ''; 11 | } 12 | } 13 | 14 | static String _getMonthName(MonthStringTypes type, index) { 15 | switch (type) { 16 | case MonthStringTypes.SHORT: 17 | return getShortMonthNames()[index]; 18 | case MonthStringTypes.FULL: 19 | return getFullMonthNames()[index]; 20 | } 21 | } 22 | 23 | static String getTranslation(String word) => titles[EventCalendar.calendarLanguage][word]; 24 | 25 | static List getNameOfDay(WeekDayStringTypes type) { 26 | switch (type) { 27 | case WeekDayStringTypes.SHORT: 28 | return getShortNameOfDays(); 29 | case WeekDayStringTypes.FULL: 30 | return getFullNameOfDays(); 31 | } 32 | } 33 | 34 | static Map getMonthDaysShort(int monthIndex) => EventCalendar.calendarProvider.getMonthDaysShort(monthIndex); 35 | 36 | static List getShortNameOfDays() => shortDayNames[EventCalendar.calendarLanguage][EventCalendar.calendarType]; 37 | 38 | static List getFullNameOfDays() => fullDayNames[EventCalendar.calendarLanguage][EventCalendar.calendarType]; 39 | 40 | static List getFullMonthNames() => fullMonthNames[EventCalendar.calendarLanguage][EventCalendar.calendarType]; 41 | 42 | static List getShortMonthNames() => 43 | shortMonthNames[EventCalendar.calendarLanguage][EventCalendar.calendarType]; 44 | 45 | static bool isRTL() => directionIsRTL[EventCalendar.calendarLanguage]; 46 | } 47 | -------------------------------------------------------------------------------- /example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | flutter_event_calendar_example 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | CADisableMinimumFrameDurationOnPhone 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /lib/src/utils/style_provider.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_event_calendar/flutter_event_calendar.dart'; 3 | import 'package:flutter_event_calendar/src/handlers/calendar_utils.dart'; 4 | import 'package:flutter_event_calendar/src/models/datetime.dart'; 5 | 6 | class StyleProvider { 7 | static BoxDecoration? getSpecialDayDecoration(CalendarDateTime? specialDay, curYear, int currMonth, day) { 8 | BoxDecoration? decoration; 9 | final isStartRange = CalendarUtils.isStartOfRange(specialDay, curYear, currMonth, day); 10 | final isEndRange = CalendarUtils.isEndOfRange(specialDay, curYear, currMonth, day); 11 | final isInRange = CalendarUtils.isInRange(specialDay, curYear, currMonth, day); 12 | 13 | if (isEndRange && isStartRange) { 14 | decoration = BoxDecoration(color: specialDay?.color, borderRadius: BorderRadius.circular(8)); 15 | } else if (isStartRange) { 16 | decoration = BoxDecoration( 17 | color: specialDay?.color, 18 | borderRadius: _getStartRadiusByLocale(), 19 | ); 20 | } else if (isEndRange) { 21 | decoration = BoxDecoration( 22 | color: specialDay?.color, 23 | borderRadius: _getEndRadiusByLocale(), 24 | ); 25 | } else if (isInRange) { 26 | decoration = BoxDecoration(color: specialDay?.color); 27 | } 28 | return decoration; 29 | } 30 | 31 | static bool _isRTL() => EventCalendar.calendarProvider.isRTL(); 32 | 33 | static _getStartRadiusByLocale() { 34 | return _isRTL() 35 | ? BorderRadius.horizontal(right: Radius.circular(8)) 36 | : BorderRadius.horizontal(left: Radius.circular(8)); 37 | } 38 | 39 | static _getEndRadiusByLocale() { 40 | return _isRTL() 41 | ? BorderRadius.horizontal(left: Radius.circular(8)) 42 | : BorderRadius.horizontal(right: Radius.circular(8)); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.lock 6 | *.swp 7 | .DS_Store 8 | .atom/ 9 | .buildlog/ 10 | .history 11 | .svn/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # The .vscode folder contains launch configuration and tasks you configure in 20 | # VS Code which you may wish to be included in version control, so this line 21 | # is commented out by default. 22 | #.vscode/ 23 | 24 | # Flutter/Dart/Pub related 25 | **/doc/api/ 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | build/ 33 | 34 | # Android related 35 | **/android/**/gradle-wrapper.jar 36 | **/android/.gradle 37 | **/android/captures/ 38 | **/android/gradlew 39 | **/android/gradlew.bat 40 | **/android/local.properties 41 | **/android/**/GeneratedPluginRegistrant.java 42 | 43 | # iOS/XCode related 44 | **/ios/**/*.mode1v3 45 | **/ios/**/*.mode2v3 46 | **/ios/**/*.moved-aside 47 | **/ios/**/*.pbxuser 48 | **/ios/**/*.perspectivev3 49 | **/ios/**/*sync/ 50 | **/ios/**/.sconsign.dblite 51 | **/ios/**/.tags* 52 | **/ios/**/.vagrant/ 53 | **/ios/**/DerivedData/ 54 | **/ios/**/Icon? 55 | **/ios/**/Pods/ 56 | **/ios/**/.symlinks/ 57 | **/ios/**/profile 58 | **/ios/**/xcuserdata 59 | **/ios/.generated/ 60 | **/ios/Flutter/App.framework 61 | **/ios/Flutter/Flutter.framework 62 | **/ios/Flutter/Flutter.podspec 63 | **/ios/Flutter/Generated.xcconfig 64 | **/ios/Flutter/app.flx 65 | **/ios/Flutter/app.zip 66 | **/ios/Flutter/flutter_assets/ 67 | **/ios/Flutter/flutter_export_environment.sh 68 | **/ios/ServiceDefinitions.json 69 | **/ios/Runner/GeneratedPluginRegistrant.* 70 | 71 | # Exceptions to above rules. 72 | !**/ios/**/default.mode1v3 73 | !**/ios/**/default.mode2v3 74 | !**/ios/**/default.pbxuser 75 | !**/ios/**/default.perspectivev3 76 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 77 | -------------------------------------------------------------------------------- /lib/src/dictionaries/fa.dart: -------------------------------------------------------------------------------- 1 | import '../../flutter_event_calendar.dart'; 2 | 3 | class Fa { 4 | static Map fullMonthNames = const { 5 | 'fa': { 6 | CalendarType.JALALI: [ 7 | 'فروردین', 8 | 'اردیبهشت', 9 | 'خرداد', 10 | 'تیر', 11 | 'مرداد', 12 | 'شهریور', 13 | 'مهر', 14 | 'آبان', 15 | 'آذر', 16 | 'دی', 17 | 'بهمن', 18 | 'اسفند' 19 | ], 20 | CalendarType.GREGORIAN: [ 21 | 'ژانویه', 22 | 'فوریه', 23 | 'مارس', 24 | 'آوریل', 25 | 'مه', 26 | 'ژوئن', 27 | 'ژوئیه', 28 | 'اوت', 29 | 'سپتامبر', 30 | 'اکتبر', 31 | 'نوامبر', 32 | 'دسامبر' 33 | ] 34 | } 35 | }; 36 | static Map shortMonthNames = const { 37 | 'fa': { 38 | CalendarType.JALALI: ['فرو', 'ارد', 'خرد', 'تیر', 'مرد', 'شهر', 'مهر', 'آبا', 'آذر', 'دی', 'بهم', 'اسف'], 39 | CalendarType.GREGORIAN: ['ژان', 'قور', 'مار', 'آور', 'مه', 'ژوئ', 'ژوئی', 'اوت', 'سپت', 'اکت', 'نوا', 'دسا'], 40 | } 41 | }; 42 | static Map fullDayNames = const { 43 | 'fa': { 44 | CalendarType.JALALI: ['شنبه', 'یکشنبه', 'دوشنبه', 'سه شنبه', 'چهارشنبه', 'پنج شنبه', 'جمعه'], 45 | CalendarType.GREGORIAN: ['یکشنبه', 'دوشنبه', 'سه شنبه', 'چهارشنبه', 'پنجشنبه', 'جمعه', 'شنبه'], 46 | } 47 | }; 48 | static Map shortDayNames = const { 49 | 'fa': { 50 | CalendarType.JALALI: ['ش', 'ی', 'د', 'س', 'چ', 'پ', 'ج'], 51 | CalendarType.GREGORIAN: ['ی', 'د', 'س', 'چ', 'پ', 'ج', 'ش'] 52 | } 53 | }; 54 | static Map titles = const { 55 | 'fa': { 56 | 'empty': 'خالی', 57 | 'month_selector': 'یک ماه را انتخاب کنید', 58 | 'year_selector': 'یک سال را انتخاب کنید', 59 | 'day_selector':'یک روز را انتخاب کنید' 60 | } 61 | }; 62 | 63 | static Map directionIsRTL = {'fa': true}; 64 | } 65 | -------------------------------------------------------------------------------- /example/lib/widgets/event_calendar/home_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_event_calendar_example/widgets/event_calendar/event_calendar.dart'; 3 | import 'package:flutter_event_calendar_example/widgets/setting/setting.dart'; 4 | import 'package:flutter_event_calendar_example/widgets/code_preview/code_preview.dart'; 5 | class HomePage extends StatefulWidget { 6 | const HomePage({ 7 | Key? key, 8 | }) : super(key: key); 9 | 10 | 11 | @override 12 | State createState() => _HomePageState(); 13 | } 14 | 15 | class _HomePageState extends State { 16 | int _selectedIndex = 0; 17 | static List _pageList = [ 18 | EventCalendarPage(), 19 | CodePreview(), 20 | Setting() 21 | ]; 22 | 23 | void _onItemTapped(int index) { 24 | setState(() { 25 | _selectedIndex = index; 26 | }); 27 | } 28 | 29 | @override 30 | Widget build(BuildContext context) { 31 | return Scaffold( 32 | appBar: AppBar( 33 | title: const Text('Flutter Event Calendar'), 34 | ), 35 | body: Center( 36 | child: _pageList.elementAt(_selectedIndex), 37 | ), 38 | bottomNavigationBar: BottomNavigationBar( 39 | 40 | items: const [ 41 | BottomNavigationBarItem( 42 | backgroundColor: Colors.blue, 43 | icon: Icon(Icons.calendar_month), 44 | label: 'preview', 45 | ), 46 | BottomNavigationBarItem( 47 | icon: Icon(Icons.code), 48 | label: 'code', 49 | ), 50 | BottomNavigationBarItem( 51 | backgroundColor: Colors.blue, 52 | icon: Icon(Icons.settings), 53 | label: 'setting', 54 | ), 55 | ], 56 | currentIndex: _selectedIndex, 57 | selectedItemColor: Colors.blue, 58 | onTap: _onItemTapped, 59 | ), 60 | ); 61 | } 62 | } 63 | 64 | -------------------------------------------------------------------------------- /lib/src/dictionaries/en.dart: -------------------------------------------------------------------------------- 1 | import '../../flutter_event_calendar.dart'; 2 | 3 | class En { 4 | static Map fullMonthNames = const { 5 | 'en': { 6 | CalendarType.JALALI: [ 7 | 'Farvardin', 8 | 'Ordibehesht', 9 | 'Khordad', 10 | 'Tir', 11 | 'Mordad', 12 | 'Shahrivar', 13 | 'Mehr', 14 | 'Aban', 15 | 'Azar', 16 | 'Dey', 17 | 'Bahman', 18 | 'Esfand' 19 | ], 20 | CalendarType.GREGORIAN: [ 21 | 'January', 22 | 'February', 23 | 'March', 24 | 'April', 25 | 'May', 26 | 'June', 27 | 'July', 28 | 'August', 29 | 'September', 30 | 'October', 31 | 'November', 32 | 'December' 33 | ] 34 | } 35 | }; 36 | static Map shortMonthNames = const { 37 | 'en': { 38 | CalendarType.JALALI: ['Far', 'Ord', 'Kho', 'Tir', 'Mor', 'Sha', 'Mehr', 'Aban', 'Azar', 'Dey', 'Bah', 'Esf'], 39 | CalendarType.GREGORIAN: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] 40 | } 41 | }; 42 | 43 | static Map fullDayNames = const { 44 | 'en': { 45 | CalendarType.JALALI: [ 46 | 'Saturday', 47 | 'Sunday', 48 | 'Monday', 49 | 'Tuesday', 50 | 'Wednesday', 51 | 'Thursday', 52 | 'Friday', 53 | ], 54 | CalendarType.GREGORIAN: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'] 55 | } 56 | }; 57 | static Map shortDayNames = const { 58 | 'en': { 59 | CalendarType.JALALI: ['Sa', 'Su', 'Mo', 'Tu', 'We', 'Th', 'Fr'], 60 | CalendarType.GREGORIAN: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'] 61 | } 62 | }; 63 | static Map titles = const { 64 | 'en': { 65 | 'empty': 'Empty', 66 | 'month_selector': 'Choose a month', 67 | 'year_selector': 'Choose a year', 68 | 'day_selector':'choose a day' 69 | } 70 | }; 71 | 72 | static Map directionIsRTL = {'en': false}; 73 | } 74 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | android { 29 | compileSdkVersion 33 30 | 31 | sourceSets { 32 | main.java.srcDirs += 'src/main/kotlin' 33 | } 34 | 35 | lintOptions { 36 | disable 'InvalidPackage' 37 | } 38 | 39 | defaultConfig { 40 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 41 | applicationId "ir.faridfr.flutter_event_calendar_example" 42 | minSdkVersion 21 43 | targetSdkVersion 33 44 | versionCode flutterVersionCode.toInteger() 45 | versionName flutterVersionName 46 | } 47 | 48 | buildTypes { 49 | release { 50 | // TODO: Add your own signing config for the release build. 51 | // Signing with the debug keys for now, so `flutter run --release` works. 52 | signingConfig signingConfigs.debug 53 | } 54 | } 55 | } 56 | 57 | flutter { 58 | source '../..' 59 | } 60 | 61 | dependencies { 62 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 63 | } 64 | -------------------------------------------------------------------------------- /example/lib/widgets/event_calendar/event_calendar.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'dart:async'; 3 | import 'package:flutter_event_calendar/flutter_event_calendar.dart'; 4 | import 'package:flutter_event_calendar_example/injection.dart'; 5 | import 'package:flutter_event_calendar_example/models/calendar_event_model.dart'; 6 | 7 | class EventCalendarPage extends StatefulWidget { 8 | const EventCalendarPage({Key? key}) : super(key: key); 9 | 10 | @override 11 | State createState() => _EventCalendarPageState(); 12 | } 13 | 14 | class _EventCalendarPageState extends State { 15 | StreamController streamController = 16 | getit>(); 17 | CalendarEventModel calendarEventModel = getit(); 18 | @override 19 | void initState() { 20 | streamController.stream.listen((event) { 21 | calendarEventModel = event; 22 | }); 23 | super.initState(); 24 | } 25 | @override 26 | Widget build(BuildContext context) { 27 | return EventCalendar( 28 | specialDays:calendarEventModel.specialDays, 29 | showLoadingForEvent: true, 30 | calendarType: calendarEventModel.calendarType, 31 | calendarLanguage: calendarEventModel.calendarLanguage, 32 | calendarOptions: CalendarOptions( 33 | viewType: calendarEventModel.calendarOptions.viewType, 34 | headerMonthBackColor: 35 | calendarEventModel.calendarOptions.headerMonthBackColor, 36 | toggleViewType: 37 | calendarEventModel.calendarOptions.toggleViewType, 38 | font: calendarEventModel.calendarOptions.font), 39 | dayOptions: DayOptions( 40 | selectedBackgroundColor: 41 | calendarEventModel.dayOptions.selectedBackgroundColor), 42 | headerOptions: HeaderOptions( 43 | headerTextColor: calendarEventModel.headerOptions.headerTextColor, 44 | navigationColor: calendarEventModel.headerOptions.navigationColor, 45 | monthStringType: calendarEventModel.headerOptions.monthStringType, 46 | weekDayStringType: 47 | calendarEventModel.headerOptions.weekDayStringType, 48 | ), 49 | ); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /lib/src/dictionaries/pt.dart: -------------------------------------------------------------------------------- 1 | import '../../flutter_event_calendar.dart'; 2 | 3 | class Pt { 4 | static Map fullMonthNames = const { 5 | 'pt': { 6 | CalendarType.JALALI: [ 7 | 'Farvardin', 8 | 'Ordibehesht', 9 | 'Khordad', 10 | 'Tir', 11 | 'Mordad', 12 | 'Shahrivar', 13 | 'Mehr', 14 | 'Aban', 15 | 'Azar', 16 | 'Dey', 17 | 'Bahman', 18 | 'Esfand' 19 | ], 20 | CalendarType.GREGORIAN: [ 21 | 'Janeiro', 22 | 'Fevereiro', 23 | 'Março', 24 | 'Abril', 25 | 'Maio', 26 | 'Junho', 27 | 'Julho', 28 | 'Agosto', 29 | 'Setembro', 30 | 'Outubro', 31 | 'Novembro', 32 | 'Dezembro' 33 | ] 34 | } 35 | }; 36 | static Map shortMonthNames = const { 37 | 'pt': { 38 | CalendarType.JALALI: [ 39 | 'Far', 40 | 'Ord', 41 | 'Kho', 42 | 'Tir', 43 | 'Mor', 44 | 'Sha', 45 | 'Mehr', 46 | 'Aban', 47 | 'Azar', 48 | 'Dey', 49 | 'Bah', 50 | 'Esf' 51 | ], 52 | CalendarType.GREGORIAN: [ 53 | 'Jan', 54 | 'Fev', 55 | 'Mar', 56 | 'Abr', 57 | 'Maio', 58 | 'Jun', 59 | 'Jul', 60 | 'Ago', 61 | 'Set', 62 | 'Out', 63 | 'Nov', 64 | 'Dez' 65 | ] 66 | } 67 | }; 68 | 69 | static Map fullDayNames = const { 70 | 'pt': { 71 | CalendarType.JALALI: [ 72 | 'Sábado', 73 | 'Domingo', 74 | 'Segunda', 75 | 'Terça', 76 | 'Quarta', 77 | 'Quinta', 78 | 'Sexta', 79 | ], 80 | CalendarType.GREGORIAN: [ 81 | 'Domingo', 82 | 'Segunda', 83 | 'Terça', 84 | 'Quarta', 85 | 'Quinta', 86 | 'Sexta', 87 | 'Sábado' 88 | ] 89 | } 90 | }; 91 | static Map shortDayNames = const { 92 | 'pt': { 93 | CalendarType.JALALI: ['Sab', 'Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex'], 94 | CalendarType.GREGORIAN: ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sab'] 95 | } 96 | }; 97 | static Map titles = const { 98 | 'pt': { 99 | 'empty': 'Vazio', 100 | 'month_selector': 'Escolha um mês', 101 | 'year_selector': 'Escolha um ano', 102 | } 103 | }; 104 | 105 | static Map directionIsRTL = {'pt': false}; 106 | } 107 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /example/lib/widgets/setting/item_setting.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_event_calendar_example/models/expanded_item_model.dart'; 3 | import 'package:flutter_event_calendar_example/widgets/setting/expanded_card_setting.dart'; 4 | 5 | class ItemSetting extends StatefulWidget { 6 | ItemSetting( 7 | {Key? key, required this.expandeditemModelList, required this.title}) 8 | : super(key: key); 9 | List expandeditemModelList; 10 | String title; 11 | @override 12 | State createState() => _ItemSettingState(); 13 | } 14 | 15 | class _ItemSettingState extends State { 16 | @override 17 | Widget build(BuildContext context) { 18 | return Column( 19 | children: [ 20 | SizedBox( 21 | height: 30, 22 | ), 23 | Row( 24 | children: [ 25 | Expanded( 26 | child: Text( 27 | widget.title, 28 | style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20), 29 | ), 30 | ), 31 | ], 32 | ), 33 | SizedBox( 34 | height: 15, 35 | ), 36 | ListView.builder( 37 | physics: NeverScrollableScrollPhysics(), 38 | itemCount: widget.expandeditemModelList.length, 39 | shrinkWrap: true, 40 | itemBuilder: (BuildContext context, int index) { 41 | return Column( 42 | children: [ 43 | Container( 44 | margin: EdgeInsets.symmetric(vertical: 10), 45 | child: ExpandedWidget( 46 | items: widget.expandeditemModelList, 47 | index: index, 48 | ), 49 | ), 50 | Row( 51 | mainAxisAlignment: MainAxisAlignment.start, 52 | children: [ 53 | SizedBox( 54 | width: 15, 55 | ), 56 | Expanded( 57 | child: Container( 58 | margin: EdgeInsets.only(bottom: 15), 59 | child: Text( 60 | widget.expandeditemModelList[index].definition, 61 | style: TextStyle(fontSize: 12), 62 | textAlign: TextAlign.start, 63 | ), 64 | )), 65 | ], 66 | ), 67 | ], 68 | ); 69 | }, 70 | ), 71 | ], 72 | ); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /lib/src/dictionaries/de.dart: -------------------------------------------------------------------------------- 1 | import '../../flutter_event_calendar.dart'; 2 | 3 | class De { 4 | static Map fullMonthNames = const { 5 | 'de': { 6 | CalendarType.JALALI: [ 7 | 'Farvardin', 8 | 'Ordibehesht', 9 | 'Khordad', 10 | 'Tir', 11 | 'Mordad', 12 | 'Shahrivar', 13 | 'Mehr', 14 | 'Aban', 15 | 'Azar', 16 | 'Dey', 17 | 'Bahman', 18 | 'Esfand' 19 | ], 20 | CalendarType.GREGORIAN: [ 21 | 'Januar', 22 | 'Februar', 23 | 'März', 24 | 'April', 25 | 'Mai', 26 | 'Juni', 27 | 'Juli', 28 | 'August', 29 | 'September', 30 | 'Oktober', 31 | 'November', 32 | 'Dezember' 33 | ] 34 | } 35 | }; 36 | static Map shortMonthNames = const { 37 | 'de': { 38 | CalendarType.JALALI: [ 39 | 'Far', 40 | 'Ord', 41 | 'Kho', 42 | 'Tir', 43 | 'Mor', 44 | 'Sha', 45 | 'Mehr', 46 | 'Aban', 47 | 'Azar', 48 | 'Dey', 49 | 'Bah', 50 | 'Esf' 51 | ], 52 | CalendarType.GREGORIAN: [ 53 | 'Jan', 54 | 'Feb', 55 | 'Mär', 56 | 'Apr', 57 | 'Mai', 58 | 'Jun', 59 | 'Jul', 60 | 'Aug', 61 | 'Sep', 62 | 'Okt', 63 | 'Nov', 64 | 'Dez' 65 | ] 66 | } 67 | }; 68 | 69 | static Map fullDayNames = const { 70 | 'de': { 71 | CalendarType.JALALI: [ 72 | 'Saturday', 73 | 'Sunday', 74 | 'Monday', 75 | 'Tuesday', 76 | 'Wednesday', 77 | 'Thursday', 78 | 'Friday', 79 | ], 80 | CalendarType.GREGORIAN: [ 81 | 'Sonntag', 82 | 'Montag', 83 | 'Dienstag', 84 | 'Mittwoch', 85 | 'Donnerstag', 86 | 'Freitag', 87 | 'Samstag' 88 | ] 89 | } 90 | }; 91 | static Map shortDayNames = const { 92 | 'de': { 93 | CalendarType.JALALI: ['Sa', 'Su', 'Mo', 'Tu', 'We', 'Th', 'Fr'], 94 | CalendarType.GREGORIAN: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'] 95 | } 96 | }; 97 | static Map titles = const { 98 | 'de': { 99 | 'empty': 'Keine Termine geplant.', 100 | 'month_selector': 'Einen Monat auswählen.', 101 | 'year_selector': 'Ein Jahr auswählen.', 102 | 'day_selector': 'Einen Tag auswählen.' 103 | } 104 | }; 105 | 106 | static Map directionIsRTL = {'de': false}; 107 | } 108 | -------------------------------------------------------------------------------- /example/lib/widgets/color/calendar_color_item.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_event_calendar_example/injection.dart'; 4 | import 'package:flutter_event_calendar_example/models/calendar_event_model.dart'; 5 | import 'package:flutter_event_calendar_example/widgets/color/color_picker_row.dart'; 6 | 7 | class ColorPickerList extends StatefulWidget { 8 | const ColorPickerList({Key? key}) : super(key: key); 9 | 10 | @override 11 | State createState() => _ColorPickerListState(); 12 | } 13 | 14 | late StreamController streamController; 15 | late CalendarEventModel calendarEventModel; 16 | late List settingColorItems; 17 | 18 | class _ColorPickerListState extends State { 19 | @override 20 | void initState() { 21 | streamController = getit>(); 22 | calendarEventModel = getit(); 23 | settingColorItems = [ 24 | ColorPickerRow( 25 | title: "background", 26 | currentColor: calendarEventModel.calendarOptions.headerMonthBackColor, 27 | onChanged: (colorSelected) { 28 | calendarEventModel.calendarOptions.headerMonthBackColor = 29 | colorSelected; 30 | streamController.sink.add(calendarEventModel); 31 | }), 32 | ColorPickerRow( 33 | title: "selected day", 34 | currentColor: calendarEventModel.dayOptions.selectedBackgroundColor, 35 | onChanged: (colorSelected) { 36 | calendarEventModel.dayOptions.selectedBackgroundColor = 37 | colorSelected; 38 | streamController.sink.add(calendarEventModel); 39 | }), 40 | ColorPickerRow( 41 | title: "navigation", 42 | currentColor: calendarEventModel.headerOptions.navigationColor, 43 | onChanged: (colorSelected) { 44 | calendarEventModel.headerOptions.navigationColor = colorSelected; 45 | streamController.sink.add(calendarEventModel); 46 | }), 47 | ColorPickerRow( 48 | title: "headerText", 49 | currentColor: calendarEventModel.headerOptions.headerTextColor, 50 | onChanged: (colorSelected) { 51 | calendarEventModel.headerOptions.headerTextColor = colorSelected; 52 | streamController.sink.add(calendarEventModel); 53 | }), 54 | ]; 55 | super.initState(); 56 | } 57 | 58 | @override 59 | Widget build(BuildContext context) { 60 | return ListView.builder( 61 | itemCount: settingColorItems.length, 62 | shrinkWrap: true, 63 | itemBuilder: (BuildContext context, int index) { 64 | return settingColorItems[index]; 65 | }, 66 | ); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 8 | 9 | 13 | 21 | 25 | 29 | 34 | 38 | 39 | 40 | 41 | 42 | 43 | 45 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /example/lib/widgets/setting/expanded_card_setting.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:expandable/expandable.dart'; 3 | import 'package:flutter_event_calendar_example/models/expanded_item_model.dart'; 4 | import 'package:flutter_svg/flutter_svg.dart'; 5 | 6 | class ExpandedWidget extends StatelessWidget { 7 | ExpandedWidget({Key? key, required this.items, required this.index}) 8 | : super(key: key); 9 | final List items; 10 | final int index; 11 | @override 12 | Widget build(BuildContext context) { 13 | return ExpandableNotifier( 14 | child: ScrollOnExpand( 15 | child: Card( 16 | elevation: 0, 17 | shape: RoundedRectangleBorder( 18 | borderRadius: BorderRadius.circular(15.0), 19 | ), 20 | child: Column( 21 | children: [ 22 | ExpandablePanel( 23 | theme: const ExpandableThemeData( 24 | headerAlignment: ExpandablePanelHeaderAlignment.center, 25 | tapBodyToExpand: true, 26 | tapBodyToCollapse: false, 27 | hasIcon: false, 28 | ), 29 | header: Container( 30 | padding: EdgeInsets.symmetric(vertical: 10, horizontal: 5), 31 | alignment: Alignment.centerLeft, 32 | child: Row( 33 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 34 | children: [ 35 | Row( 36 | children: [ 37 | SizedBox( 38 | width: 15, 39 | ), 40 | SvgPicture.asset(items[index].icon), 41 | SizedBox( 42 | width: 15, 43 | ), 44 | Text( 45 | items[index].title, 46 | style: TextStyle(fontWeight: FontWeight.bold), 47 | ), 48 | ], 49 | ), 50 | ExpandableIcon( 51 | theme: const ExpandableThemeData( 52 | expandIcon: Icons.keyboard_arrow_down_outlined, 53 | collapseIcon: Icons.keyboard_arrow_up, 54 | iconColor: Colors.grey, 55 | iconSize: 18.0, 56 | iconRotationAngle: 3.14 / 2, 57 | iconPadding: EdgeInsets.only(right: 5), 58 | hasIcon: false, 59 | ), 60 | ), 61 | ], 62 | ), 63 | ), 64 | collapsed: Container(), 65 | expanded: items[index].body, 66 | ), 67 | ], 68 | ), 69 | ), 70 | )); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /example/lib/widgets/color/color_picker_row.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_colorpicker/flutter_colorpicker.dart'; 3 | 4 | class ColorPickerRow extends StatefulWidget { 5 | ColorPickerRow( 6 | {Key? key, 7 | required this.onChanged, 8 | required this.title, 9 | required this.currentColor}) 10 | : super(key: key); 11 | final Function(Color color) onChanged; 12 | final String title; 13 | Color? currentColor; 14 | 15 | @override 16 | State createState() => _ColorPickerRowState(); 17 | } 18 | 19 | class _ColorPickerRowState extends State { 20 | Color? pickerColor = Color(0xff443a49); 21 | 22 | void changeColor(Color color) { 23 | setState(() => pickerColor = color); 24 | } 25 | 26 | showColorPickerDialog() { 27 | return showDialog( 28 | barrierDismissible: false, 29 | context: context, 30 | builder: (BuildContext context) { 31 | return AlertDialog( 32 | title: Text('Pick a color!'), 33 | content: SingleChildScrollView( 34 | child: ColorPicker( 35 | pickerColor: pickerColor ?? Colors.amberAccent, 36 | onColorChanged: changeColor, 37 | ), 38 | ), 39 | actions: [ 40 | ElevatedButton( 41 | style: ElevatedButton.styleFrom( 42 | shape: const CircleBorder(), 43 | ), 44 | child: const Icon(Icons.palette_outlined), 45 | onPressed: () { 46 | widget.onChanged(pickerColor!); 47 | Navigator.of(context).pop(); 48 | }, 49 | ), 50 | ], 51 | ); 52 | }); 53 | } 54 | 55 | @override 56 | void initState() { 57 | pickerColor = widget.currentColor; 58 | super.initState(); 59 | } 60 | 61 | @override 62 | Widget build(BuildContext context) { 63 | return Container( 64 | margin: EdgeInsets.symmetric(horizontal: 8, vertical: 10), 65 | height: 30, 66 | child: Row( 67 | mainAxisAlignment: MainAxisAlignment.start, 68 | children: [ 69 | Container( 70 | width: 100, 71 | child: Text( 72 | widget.title, 73 | style: TextStyle( 74 | fontWeight: FontWeight.bold, 75 | ), 76 | ), 77 | ), 78 | SizedBox( 79 | width: 10, 80 | ), 81 | Expanded( 82 | child: InkWell( 83 | onTap: showColorPickerDialog, 84 | child: Card( 85 | margin: EdgeInsets.only( 86 | right: 8, 87 | ), 88 | color: pickerColor, 89 | child: Container())), 90 | ) 91 | ], 92 | )); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /lib/src/models/datetime.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import '../../flutter_event_calendar.dart'; 3 | 4 | class CalendarDateTime { 5 | int year; 6 | int month; 7 | int day; 8 | int? toMonth; 9 | int? toDay; 10 | int? hour; 11 | int? minute; 12 | int? second; 13 | bool isEnableDay; 14 | Color? color; 15 | CalendarType calendarType; 16 | 17 | CalendarDateTime( 18 | {required this.year, 19 | required this.month, 20 | required this.day, 21 | required this.calendarType, 22 | this.isEnableDay = true, 23 | this.toMonth, 24 | this.toDay, 25 | this.hour, 26 | this.minute, 27 | this.second, 28 | this.color}); 29 | 30 | //supported format 1400-9-12 20:00(:50) 31 | static CalendarDateTime? parseDateTime(String dateTime, CalendarType calendarType) { 32 | final splitter = dateTime.split(" "); 33 | final datePart = splitter[0].split("-"); 34 | final timePart = splitter[1].split(":"); 35 | 36 | try { 37 | return CalendarDateTime( 38 | year: int.parse(datePart[0]), 39 | month: int.parse(datePart[1]), 40 | day: int.parse(datePart[2]), 41 | hour: int.parse(timePart[0]), 42 | minute: int.parse(timePart[1]), 43 | second: timePart.length == 3 ? double.parse(timePart[2]).toInt() : 0, 44 | calendarType: calendarType); 45 | } on Exception catch (e) { 46 | print("${e.toString()}"); 47 | return null; 48 | } 49 | } 50 | 51 | //supported format 1400-9-12 52 | static CalendarDateTime? parseDate(String date, CalendarType calendarType) { 53 | final datePart = date.split("-"); 54 | 55 | try { 56 | return CalendarDateTime( 57 | year: int.parse(datePart[0]), 58 | month: int.parse(datePart[1]), 59 | day: int.parse(datePart[2]), 60 | calendarType: calendarType); 61 | } on Exception catch (e) { 62 | print("${e.toString()}"); 63 | return null; 64 | } 65 | } 66 | 67 | bool isDateEqual(CalendarDateTime dateTime) { 68 | return year == dateTime.year && month == dateTime.month && day == dateTime.day; 69 | } 70 | 71 | bool isDateEqualByInt(int year, int month, int day) { 72 | return this.year == year && this.month == month && this.day == day; 73 | } 74 | 75 | bool isDateTimeEqual(CalendarDateTime dateTime) { 76 | return year == dateTime.year && 77 | month == dateTime.month && 78 | day == dateTime.day && 79 | hour == dateTime.hour && 80 | minute == dateTime.minute; 81 | } 82 | 83 | @override 84 | String toString() { 85 | final fMonth = month < 10 ? "0$month" : "$month"; 86 | final fDay = day < 10 ? "0$day" : "$day"; 87 | if (hour != null && minute != null) { 88 | return "$year-$fMonth-$fDay $hour:$minute${second != null ? ':$second' : ''}"; 89 | } else { 90 | return "$year-$fMonth-$fDay"; 91 | } 92 | } 93 | 94 | String getDate() { 95 | final fMonth = month < 10 ? "0$month" : "$month"; 96 | final fDay = day < 10 ? "0$day" : "$day"; 97 | return "$year-$fMonth-$fDay"; 98 | } 99 | 100 | DateTime toDateTime() { 101 | return DateTime(year, month, day); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 69 | 71 | 77 | 78 | 79 | 80 | 82 | 83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /example/lib/widgets/setting/header_special_days.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_event_calendar/src/models/style/select_month_options.dart'; 3 | import 'package:flutter_event_calendar/src/models/style/select_year_options.dart'; 4 | import 'package:flutter_event_calendar/src/models/style/selected_day_options.dart'; 5 | import 'package:flutter_event_calendar/src/utils/calendar_types.dart'; 6 | import 'package:flutter_event_calendar/src/widgets/select_month.dart'; 7 | import 'package:flutter_event_calendar/src/widgets/select_year.dart'; 8 | import 'package:flutter_event_calendar/src/widgets/select_day.dart'; 9 | import 'package:flutter_event_calendar_example/widgets/setting/date_picker_item.dart'; 10 | import 'package:flutter_event_calendar/src/models/datetime.dart'; 11 | 12 | class HeaderSpecialDays extends StatefulWidget { 13 | HeaderSpecialDays( 14 | {Key? key, required this.speacialDate, required this.calendarDateTime}) 15 | : super(key: key); 16 | Function(CalendarDateTime calendarDateTime) speacialDate; 17 | 18 | CalendarDateTime calendarDateTime; 19 | @override 20 | State createState() => _HeaderSpecialDaysState(); 21 | } 22 | 23 | class _HeaderSpecialDaysState extends State { 24 | @override 25 | void initState() { 26 | super.initState(); 27 | } 28 | 29 | @override 30 | Widget build(BuildContext context) { 31 | //listbuilder generator 32 | List selectBottomSheetDate = [ 33 | DataPickerItem( 34 | date: widget.calendarDateTime.day, 35 | selectDate: SelectDay( 36 | onHeaderChanged: (int selectedDay) { 37 | setState(() { 38 | widget.calendarDateTime.day = selectedDay; 39 | }); 40 | widget.speacialDate(widget.calendarDateTime); 41 | }, 42 | dayStyle: DayOptions(selectedColor: Colors.blue), 43 | ), 44 | nameSelectDate: PartFormat.DAY, 45 | ), 46 | DataPickerItem( 47 | date: widget.calendarDateTime.month, 48 | selectDate: SelectMonth( 49 | onHeaderChanged: (int selectedMonth) { 50 | setState(() { 51 | widget.calendarDateTime.month = selectedMonth; 52 | widget.speacialDate(widget.calendarDateTime); 53 | }); 54 | }, 55 | monthStyle: MonthOptions(selectedColor: Colors.blue), 56 | ), 57 | nameSelectDate: PartFormat.MONTH, 58 | ), 59 | DataPickerItem( 60 | date: widget.calendarDateTime.year, 61 | selectDate: SelectYear( 62 | onHeaderChanged: (int selectedYear) { 63 | setState(() { 64 | widget.calendarDateTime.year = selectedYear; 65 | widget.speacialDate(widget.calendarDateTime); 66 | }); 67 | }, 68 | yearStyle: YearOptions(selectedColor: Colors.blue), 69 | ), 70 | nameSelectDate: PartFormat.YEAR, 71 | ), 72 | ]; 73 | 74 | return GridView.count( 75 | childAspectRatio: 1.3, 76 | physics: NeverScrollableScrollPhysics(), 77 | shrinkWrap: true, 78 | crossAxisCount: 3, 79 | children: List.generate(selectBottomSheetDate.length, (index) { 80 | return Column( 81 | children: [ 82 | selectBottomSheetDate[index], 83 | Container( 84 | padding: EdgeInsets.only(top: 10), 85 | child: Text(selectBottomSheetDate[index].date == 0 86 | ? '_ _ _' 87 | : selectBottomSheetDate[index].date.toString())), 88 | ], 89 | ); 90 | })); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /lib/src/widgets/select_year.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import '../../flutter_event_calendar.dart'; 3 | import '../handlers/calendar_utils.dart'; 4 | import '../handlers/translator.dart'; 5 | import '../models/style/select_year_options.dart'; 6 | 7 | class SelectYear extends StatelessWidget { 8 | late List years; 9 | 10 | Function(int year) onHeaderChanged; 11 | 12 | YearOptions? yearStyle; 13 | 14 | SelectYear({required this.onHeaderChanged, this.yearStyle}); 15 | 16 | ScrollController _scrollController = ScrollController(); 17 | 18 | late VoidCallback scrollToPositionCallback; 19 | 20 | final int selectedYear = CalendarUtils.getPartByInt(format: PartFormat.YEAR); 21 | 22 | late BoxDecoration selectedDecoration; 23 | 24 | @override 25 | Widget build(BuildContext context) { 26 | animateToCurrentYear(); 27 | 28 | years = CalendarUtils.getYears(); 29 | 30 | selectedDecoration = BoxDecoration( 31 | color: yearStyle?.selectedColor, 32 | borderRadius: BorderRadius.circular(8), 33 | ); 34 | 35 | return Container( 36 | decoration: BoxDecoration( 37 | borderRadius: const BorderRadius.only( 38 | topLeft: Radius.circular(26), topRight: Radius.circular(26)), 39 | color: yearStyle?.backgroundColor, 40 | ), 41 | height: 380, 42 | child: Padding( 43 | padding: const EdgeInsets.all(30), 44 | child: Column( 45 | mainAxisSize: MainAxisSize.max, 46 | children: [ 47 | Text( 48 | '${Translator.getTranslation('year_selector')}', 49 | style: TextStyle( 50 | fontSize: 25, 51 | fontWeight: FontWeight.w500, 52 | fontFamily: yearStyle?.font, 53 | ), 54 | ), 55 | const SizedBox( 56 | height: 20, 57 | ), 58 | Expanded( 59 | child: Material( 60 | color: Colors.transparent, 61 | child: GridView.builder( 62 | controller: _scrollController, 63 | itemCount: years.length, 64 | gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( 65 | crossAxisCount: 3, mainAxisExtent: 50), 66 | itemBuilder: (context, index) => 67 | yearWidgetMaker(years[index], context)), 68 | ), 69 | ), 70 | ], 71 | ), 72 | ), 73 | ); 74 | } 75 | 76 | Widget yearWidgetMaker(year, context) { 77 | return InkWell( 78 | onTap: (() { 79 | Navigator.pop(context); 80 | onHeaderChanged.call(year); 81 | }), 82 | child: Center( 83 | child: Container( 84 | padding: EdgeInsets.all(8), 85 | decoration: year == selectedYear ? selectedDecoration : null, 86 | child: Text( 87 | '$year', 88 | style: TextStyle( 89 | fontSize: 16, 90 | color: year == selectedYear ? Colors.white : null, 91 | fontFamily: yearStyle?.font, 92 | ), 93 | ), 94 | ), 95 | ), 96 | ); 97 | } 98 | 99 | double findSelectedYearOffset() { 100 | final size = _scrollController.position.maxScrollExtent / (years.length / 3); 101 | return size * (years.indexOf(selectedYear)) / 3; 102 | } 103 | 104 | void animateToCurrentYear() { 105 | WidgetsBinding.instance.addPostFrameCallback((timeStamp) { 106 | if (_scrollController.hasClients) 107 | _scrollController.animateTo(findSelectedYearOffset(), 108 | duration: Duration(milliseconds: 500), curve: Curves.ease); 109 | }); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /example/lib/widgets/setting/options.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_event_calendar/flutter_event_calendar.dart'; 4 | import 'package:flutter_event_calendar_example/injection.dart'; 5 | import 'package:flutter_event_calendar_example/models/calendar_event_model.dart'; 6 | import 'package:flutter_event_calendar_example/models/expanded_item_model.dart'; 7 | import 'package:flutter_event_calendar_example/widgets/setting/date_picker.dart'; 8 | import 'package:flutter_event_calendar_example/widgets/setting/item_setting.dart'; 9 | import 'package:flutter_event_calendar_example/widgets/setting/radio_button_list.dart'; 10 | 11 | class Options extends StatefulWidget { 12 | Options( 13 | {Key? key, this.onMonthChanged, this.onYearChanged, this.onDayChanged}) 14 | : super(key: key); 15 | CalendarChangeCallback? onMonthChanged; 16 | CalendarChangeCallback? onYearChanged; 17 | CalendarChangeCallback? onDayChanged; 18 | @override 19 | State createState() => _OptionsState(); 20 | } 21 | 22 | class _OptionsState extends State { 23 | late StreamController streamController; 24 | late CalendarEventModel calendarEventModel; 25 | late List languageList; 26 | late List OptionsList; 27 | late List calendarTypeList; 28 | @override 29 | void initState() { 30 | streamController = getit>(); 31 | calendarEventModel = getit(); 32 | calendarTypeList = [CalendarType.JALALI.name, CalendarType.GREGORIAN.name]; 33 | languageList = ['fa', 'en','pt']; 34 | OptionsList = [ 35 | ExpandedItemModel( 36 | icon: 'assets/language_icon.svg', 37 | title: "Special Days", 38 | body: DatePicker( 39 | onDayChanged: () { 40 | widget.onDayChanged?.call(EventCalendar.dateTime!); 41 | setState(() {}); 42 | }, 43 | onYearChanged: () { 44 | widget.onMonthChanged?.call(EventCalendar.dateTime!); 45 | setState(() {}); 46 | }, 47 | onMonthChanged: () { 48 | widget.onMonthChanged?.call(EventCalendar.dateTime!); 49 | setState(() {}); 50 | }, 51 | ), 52 | definition: "SpecialDays: lets you set special days"), 53 | ExpandedItemModel( 54 | icon: 'assets/language_icon.svg', 55 | title: "Calendar Language", 56 | body: RadioButtonList( 57 | initValue: calendarEventModel.calendarLanguage, 58 | listItems: languageList, 59 | onChanged: (dynamic keyName) { 60 | calendarEventModel.calendarLanguage = keyName; 61 | streamController.sink.add(calendarEventModel); 62 | }, 63 | ), 64 | definition: 65 | "CalendarLanguage: helps you to customize calendar's Language"), 66 | ExpandedItemModel( 67 | icon: 'assets/language_icon.svg', 68 | title: "Calendar Type", 69 | body: RadioButtonList( 70 | initValue: calendarEventModel.calendarType.name, 71 | listItems: calendarTypeList, 72 | onChanged: (dynamic keyName) { 73 | calendarEventModel.calendarType = CalendarType.values 74 | .firstWhere((element) => element.name == keyName); 75 | streamController.sink.add(calendarEventModel); 76 | }, 77 | ), 78 | definition: 79 | "CalendarType: helps you to switch between Gregoria Calendar and Solar Calendar"), 80 | ]; 81 | super.initState(); 82 | } 83 | 84 | @override 85 | Widget build(BuildContext context) { 86 | return ItemSetting(title: "Options", expandeditemModelList: OptionsList); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /lib/src/widgets/events.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/material.dart'; 3 | import '../handlers/calendar_utils.dart'; 4 | import '../handlers/event_calendar.dart'; 5 | import '../handlers/event_selector.dart'; 6 | import '../handlers/translator.dart'; 7 | import '../models/calendar_options.dart'; 8 | import '../models/style/event_options.dart'; 9 | import 'event_card.dart'; 10 | 11 | class Events extends StatelessWidget { 12 | Function onEventsChanged; 13 | late EventOptions eventStyle; 14 | 15 | Events({required this.onEventsChanged}); 16 | 17 | @override 18 | Widget build(BuildContext context) { 19 | eventStyle = EventOptions.of(context); 20 | List events = eventCardsMaker(context); 21 | return Expanded( 22 | child: Padding( 23 | padding: EdgeInsets.all(5), 24 | child: GestureDetector( 25 | onPanEnd: ((details) { 26 | Velocity vc = details.velocity; 27 | String clearVc; 28 | clearVc = vc.toString().replaceAll('(', ''); 29 | clearVc = clearVc.toString().replaceAll(')', ''); 30 | clearVc = clearVc.toString().replaceAll('Velocity', ''); 31 | if (double.parse(clearVc.toString().split(',')[0]) > 0) { 32 | // left 33 | switch (EventCalendar.calendarProvider.isRTL()) { 34 | case true: 35 | CalendarUtils.nextDay(); 36 | break; 37 | case false: 38 | CalendarUtils.previousDay(); 39 | break; 40 | } 41 | onEventsChanged.call(); 42 | } else { 43 | // right 44 | switch (EventCalendar.calendarProvider.isRTL()) { 45 | case true: 46 | CalendarUtils.previousDay(); 47 | break; 48 | case false: 49 | CalendarUtils.nextDay(); 50 | break; 51 | } 52 | onEventsChanged.call(); 53 | } 54 | }), 55 | child: eventStyle.showLoadingForEvent?.call() == true 56 | ? eventStyle.loadingWidget!.call() 57 | : events.isEmpty 58 | ? emptyView(context) 59 | : ListView( 60 | padding: EdgeInsets.zero, 61 | scrollDirection: Axis.vertical, 62 | children: events, 63 | ), 64 | ), 65 | ), 66 | ); 67 | } 68 | 69 | List eventCardsMaker(BuildContext context) { 70 | var selectedEvents = EventSelector().updateEvents(); 71 | List eventCards = []; 72 | for (var item in selectedEvents) { 73 | eventCards.add( 74 | EventCard( 75 | fullCalendarEvent: item, 76 | ), 77 | ); 78 | } 79 | 80 | return eventCards; 81 | } 82 | Widget emptyView(BuildContext context){ 83 | return Container( 84 | color: Colors.transparent, 85 | width: double.infinity, 86 | height: double.infinity, 87 | child: Center( 88 | child: Column( 89 | mainAxisSize: MainAxisSize.min, 90 | children: [ 91 | Icon( 92 | eventStyle.emptyIcon, 93 | size: 95, 94 | color: eventStyle.emptyIconColor, 95 | ), 96 | Text( 97 | eventStyle.emptyText ?? 98 | Translator.getTranslation('empty'), 99 | style: TextStyle( 100 | color: eventStyle.emptyTextColor, 101 | fontSize: 25, 102 | fontFamily: CalendarOptions.of(context).font, 103 | ), 104 | ), 105 | ], 106 | ), 107 | ), 108 | ); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /lib/src/widgets/select_day.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import 'package:flutter_event_calendar/src/handlers/calendar_utils.dart'; 4 | import 'package:flutter_event_calendar/src/handlers/translator.dart'; 5 | import 'package:flutter_event_calendar/src/models/style/selected_day_options.dart'; 6 | import 'package:flutter_event_calendar/src/utils/calendar_types.dart'; 7 | 8 | class SelectDay extends StatelessWidget { 9 | late List days; 10 | 11 | Function(int day) onHeaderChanged; 12 | 13 | DayOptions? dayStyle; 14 | 15 | SelectDay({required this.onHeaderChanged, this.dayStyle}); 16 | 17 | ScrollController _scrollController = ScrollController(); 18 | 19 | late VoidCallback scrollToPositionCallback; 20 | 21 | final int selectedDay = CalendarUtils.getPartByInt(format: PartFormat.DAY); 22 | 23 | late BoxDecoration selectedDecoration; 24 | 25 | @override 26 | Widget build(BuildContext context) { 27 | animateToCurrentDay(); 28 | 29 | days = CalendarUtils.getDaysAmount(); 30 | 31 | selectedDecoration = BoxDecoration( 32 | color: dayStyle?.selectedColor, 33 | borderRadius: BorderRadius.circular(8), 34 | ); 35 | 36 | return Container( 37 | decoration: BoxDecoration( 38 | borderRadius: BorderRadius.only( 39 | topLeft: Radius.circular(26), topRight: Radius.circular(26)), 40 | color: Colors.white, 41 | ), 42 | height: 380, 43 | child: Padding( 44 | padding: EdgeInsets.all(30), 45 | child: Column( 46 | mainAxisSize: MainAxisSize.max, 47 | children: [ 48 | Text( 49 | '${Translator.getTranslation('day_selector')}', 50 | style: TextStyle( 51 | fontSize: 25, 52 | fontWeight: FontWeight.w500, 53 | // fontFamily:dayStyle?.font, 54 | ), 55 | ), 56 | SizedBox( 57 | height: 20, 58 | ), 59 | Expanded( 60 | child: Material( 61 | color: Colors.transparent, 62 | child: GridView.builder( 63 | controller: _scrollController, 64 | itemCount: days.length, 65 | gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( 66 | crossAxisCount: 3, mainAxisExtent: 50), 67 | itemBuilder: (context, index) => 68 | dayWidgetMaker(days[index], context)), 69 | ), 70 | ), 71 | ], 72 | ), 73 | ), 74 | ); 75 | } 76 | 77 | Widget dayWidgetMaker(day, context) { 78 | return InkWell( 79 | onTap: (() { 80 | Navigator.pop(context); 81 | onHeaderChanged.call(day); 82 | 83 | }), 84 | child: Center( 85 | child: Container( 86 | padding: EdgeInsets.all(8), 87 | decoration: day == selectedDay ? selectedDecoration : null, 88 | child: Text( 89 | '$day', 90 | style: TextStyle( 91 | fontSize: 16, 92 | color: day == selectedDay ? Colors.white : null, 93 | // fontFamily: DayStyle?.font, 94 | ), 95 | ), 96 | ), 97 | ), 98 | ); 99 | } 100 | 101 | double findSelectedDayOffset() { 102 | final size = 103 | _scrollController.position.maxScrollExtent / (days.length / 3); 104 | return size * (days.indexOf(selectedDay)) / 3; 105 | } 106 | 107 | void animateToCurrentDay() { 108 | WidgetsBinding.instance.addPostFrameCallback((timeStamp) { 109 | if (_scrollController.hasClients) 110 | _scrollController.animateTo(findSelectedDayOffset(), 111 | duration: Duration(milliseconds: 500), curve: Curves.ease); 112 | }); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /example/lib/widgets/code_preview/code_preview.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | import 'package:flutter_event_calendar_example/injection.dart'; 6 | import 'package:flutter_event_calendar_example/models/calendar_event_model.dart'; 7 | import 'package:flutter_syntax_view/flutter_syntax_view.dart'; 8 | import 'package:clipboard/clipboard.dart'; 9 | 10 | class CodePreview extends StatefulWidget { 11 | @override 12 | State createState() => CodePreviewState(); 13 | } 14 | 15 | class CodePreviewState extends State { 16 | StreamController streamController = 17 | getit>(); 18 | CalendarEventModel calendarEventModel = getit(); 19 | late String code; 20 | @override 21 | void initState() { 22 | streamController.stream.listen((event) { 23 | calendarEventModel = event; 24 | }); 25 | super.initState(); 26 | 27 | code = """ 28 | EventCalendar( 29 | specialDays:${calendarEventModel.specialDays}, 30 | calendarType: ${calendarEventModel.calendarType}, 31 | calendarLanguage: ${calendarEventModel.calendarLanguage} , 32 | calendarOptions: CalendarOptions( 33 | viewType: ${calendarEventModel.calendarOptions.viewType}, 34 | headerMonthBackColor: 35 | ${calendarEventModel.calendarOptions.headerMonthBackColor}, 36 | toggleViewType: 37 | ${calendarEventModel.calendarOptions.toggleViewType}, 38 | font: ${calendarEventModel.calendarOptions.font}), 39 | dayOptions: DayOptions(selectedBackgroundColor:${calendarEventModel.dayOptions.selectedBackgroundColor}), 40 | headerOptions: HeaderOptions( 41 | headerTextColor:${calendarEventModel.headerOptions.headerTextColor}, 42 | navigationColor:${calendarEventModel.headerOptions.navigationColor}, 43 | monthStringType: 44 | ${calendarEventModel.headerOptions.monthStringType}, 45 | weekDayStringType: ${calendarEventModel.headerOptions.weekDayStringType}, 46 | ), 47 | ), 48 | """; 49 | } 50 | 51 | SyntaxView syntaxViewTheme() { 52 | return SyntaxView( 53 | code: code, 54 | syntax: Syntax.DART, 55 | syntaxTheme: SyntaxTheme.vscodeLight(), 56 | fontSize: 12.0, 57 | withZoom: true, 58 | withLinesCount: true, 59 | expanded: true); 60 | } 61 | 62 | void copyCodePreview() { 63 | FlutterClipboard.copy(code) 64 | .then((value) => ScaffoldMessenger.of(context).showSnackBar(SnackBar( 65 | content: Text("Copied"), 66 | backgroundColor: Colors.grey, 67 | duration: const Duration(seconds: 1), 68 | ))); 69 | } 70 | 71 | @override 72 | Widget build(BuildContext context) { 73 | SyntaxView syntaxView = syntaxViewTheme(); 74 | 75 | return Scaffold( 76 | body: Stack( 77 | alignment: AlignmentDirectional.topEnd, 78 | children: [ 79 | Container( 80 | margin: EdgeInsets.only(bottom: 10, left: 10), 81 | height: MediaQuery.of(context).size.height, 82 | child: syntaxView, 83 | ), 84 | Container( 85 | margin: EdgeInsets.symmetric(horizontal: 5, vertical: 5), 86 | child: ElevatedButton( 87 | style: ElevatedButton.styleFrom( 88 | shape: const CircleBorder(), 89 | ), 90 | child: const Icon(Icons.copy), 91 | onPressed: () { 92 | copyCodePreview(); 93 | }, 94 | ), 95 | ), 96 | ], 97 | )); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "2.9.0" 11 | boolean_selector: 12 | dependency: transitive 13 | description: 14 | name: boolean_selector 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "2.1.0" 18 | characters: 19 | dependency: transitive 20 | description: 21 | name: characters 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "1.2.1" 25 | clock: 26 | dependency: transitive 27 | description: 28 | name: clock 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "1.1.1" 32 | collection: 33 | dependency: transitive 34 | description: 35 | name: collection 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "1.16.0" 39 | fake_async: 40 | dependency: transitive 41 | description: 42 | name: fake_async 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "1.3.1" 46 | flutter: 47 | dependency: "direct main" 48 | description: flutter 49 | source: sdk 50 | version: "0.0.0" 51 | flutter_test: 52 | dependency: "direct dev" 53 | description: flutter 54 | source: sdk 55 | version: "0.0.0" 56 | matcher: 57 | dependency: transitive 58 | description: 59 | name: matcher 60 | url: "https://pub.dartlang.org" 61 | source: hosted 62 | version: "0.12.12" 63 | material_color_utilities: 64 | dependency: transitive 65 | description: 66 | name: material_color_utilities 67 | url: "https://pub.dartlang.org" 68 | source: hosted 69 | version: "0.1.5" 70 | meta: 71 | dependency: transitive 72 | description: 73 | name: meta 74 | url: "https://pub.dartlang.org" 75 | source: hosted 76 | version: "1.8.0" 77 | path: 78 | dependency: transitive 79 | description: 80 | name: path 81 | url: "https://pub.dartlang.org" 82 | source: hosted 83 | version: "1.8.2" 84 | scoped_model: 85 | dependency: "direct main" 86 | description: 87 | name: scoped_model 88 | url: "https://pub.dartlang.org" 89 | source: hosted 90 | version: "2.0.0" 91 | shamsi_date: 92 | dependency: "direct main" 93 | description: 94 | name: shamsi_date 95 | url: "https://pub.dartlang.org" 96 | source: hosted 97 | version: "0.15.0" 98 | sky_engine: 99 | dependency: transitive 100 | description: flutter 101 | source: sdk 102 | version: "0.0.99" 103 | source_span: 104 | dependency: transitive 105 | description: 106 | name: source_span 107 | url: "https://pub.dartlang.org" 108 | source: hosted 109 | version: "1.9.0" 110 | stack_trace: 111 | dependency: transitive 112 | description: 113 | name: stack_trace 114 | url: "https://pub.dartlang.org" 115 | source: hosted 116 | version: "1.10.0" 117 | stream_channel: 118 | dependency: transitive 119 | description: 120 | name: stream_channel 121 | url: "https://pub.dartlang.org" 122 | source: hosted 123 | version: "2.1.0" 124 | string_scanner: 125 | dependency: transitive 126 | description: 127 | name: string_scanner 128 | url: "https://pub.dartlang.org" 129 | source: hosted 130 | version: "1.1.1" 131 | term_glyph: 132 | dependency: transitive 133 | description: 134 | name: term_glyph 135 | url: "https://pub.dartlang.org" 136 | source: hosted 137 | version: "1.2.1" 138 | test_api: 139 | dependency: transitive 140 | description: 141 | name: test_api 142 | url: "https://pub.dartlang.org" 143 | source: hosted 144 | version: "0.4.12" 145 | vector_math: 146 | dependency: transitive 147 | description: 148 | name: vector_math 149 | url: "https://pub.dartlang.org" 150 | source: hosted 151 | version: "2.1.2" 152 | sdks: 153 | dart: ">=2.17.0-0 <3.0.0" 154 | flutter: ">=1.24.0-1.0.pre" 155 | -------------------------------------------------------------------------------- /lib/src/widgets/select_month.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../../flutter_event_calendar.dart'; 4 | import '../handlers/calendar_utils.dart'; 5 | import '../handlers/translator.dart'; 6 | import '../models/style/select_month_options.dart'; 7 | 8 | class SelectMonth extends StatelessWidget { 9 | late List months; 10 | 11 | Function(int selectedMonth) onHeaderChanged; 12 | 13 | MonthOptions? monthStyle; 14 | 15 | SelectMonth({required this.onHeaderChanged, this.monthStyle}); 16 | 17 | late BoxDecoration selectedDecoration; 18 | 19 | final int currentMonth = CalendarUtils.getPartByInt(format: PartFormat.MONTH); 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | selectedDecoration = BoxDecoration( 24 | color: monthStyle?.selectedColor, 25 | borderRadius: BorderRadius.circular(8), 26 | ); 27 | 28 | return Container( 29 | decoration: BoxDecoration( 30 | borderRadius: const BorderRadius.only( 31 | topLeft: Radius.circular(26), topRight: Radius.circular(26)), 32 | color: monthStyle?.backgroundColor, 33 | ), 34 | height: 380, 35 | child: Padding( 36 | padding: const EdgeInsets.all(30), 37 | child: Column( 38 | mainAxisSize: MainAxisSize.max, 39 | children: [ 40 | Text( 41 | '${Translator.getTranslation('month_selector')}', 42 | style: TextStyle( 43 | fontSize: 25, 44 | fontWeight: FontWeight.w500, 45 | fontFamily: monthStyle?.font, 46 | ), 47 | ), 48 | const SizedBox( 49 | height: 20, 50 | ), 51 | Expanded( 52 | child: SingleChildScrollView( 53 | child: Column( 54 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 55 | children: [ 56 | Table( 57 | border: const TableBorder( 58 | horizontalInside: 59 | BorderSide(color: Colors.black12, width: 0.2), 60 | verticalInside: 61 | BorderSide(color: Colors.black12, width: 0.2), 62 | ), 63 | children: monthsWidgetMaker(context), 64 | ) 65 | ], 66 | ), 67 | ), 68 | ) 69 | ], 70 | ), 71 | ), 72 | ); 73 | } 74 | 75 | List monthsWidgetMaker(context) { 76 | months = Translator.getFullMonthNames(); 77 | 78 | List _buildRowCells(int rowIndex) { 79 | List widgets = []; 80 | for (var j = 0; j < 3; j++) { 81 | final int mMonth = (rowIndex * 3) + j + 1; 82 | widgets.add( 83 | TableCell( 84 | verticalAlignment: TableCellVerticalAlignment.middle, 85 | child: Material( 86 | color: Colors.transparent, 87 | child: InkWell( 88 | onTap: (() { 89 | Navigator.pop(context); 90 | onHeaderChanged.call(mMonth); 91 | }), 92 | child: Container( 93 | padding: EdgeInsets.all(15), 94 | decoration: mMonth == currentMonth ? selectedDecoration : null, 95 | child: Center( 96 | child: FittedBox( 97 | fit: BoxFit.fitWidth, 98 | child: Text( 99 | months[(rowIndex * 3) + j].toString(), 100 | style: TextStyle( 101 | fontSize: 16, 102 | color: mMonth == currentMonth ? Colors.white : null, 103 | fontFamily: monthStyle?.font, 104 | ), 105 | maxLines: 1, 106 | ), 107 | )), 108 | ), 109 | ), 110 | ), 111 | ), 112 | ); 113 | } 114 | return widgets; 115 | } 116 | 117 | List monthsWidget = []; 118 | for (var i = 0; i < 4; i++) { 119 | monthsWidget.add(TableRow(children: _buildRowCells(i))); 120 | } 121 | 122 | return monthsWidget; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /example/lib/widgets/setting/calendar_options.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_event_calendar/flutter_event_calendar.dart'; 4 | import 'package:flutter_event_calendar_example/injection.dart'; 5 | import 'package:flutter_event_calendar_example/models/calendar_event_model.dart'; 6 | import 'package:flutter_event_calendar_example/models/expanded_item_model.dart'; 7 | import 'package:flutter_event_calendar_example/widgets/color/color_picker_row.dart'; 8 | import 'package:flutter_event_calendar_example/widgets/setting/item_setting.dart'; 9 | import 'package:flutter_event_calendar_example/widgets/setting/radio_button_list.dart'; 10 | 11 | class CalendarOptions extends StatefulWidget { 12 | CalendarOptions({ 13 | Key? key, 14 | }) : super(key: key); 15 | 16 | @override 17 | State createState() => _CalendarOptionsState(); 18 | } 19 | 20 | class _CalendarOptionsState extends State { 21 | late StreamController streamController; 22 | late List fontList; 23 | late List toggleViewTypeList; 24 | late List viewTypeList; 25 | CalendarEventModel calendarEventModel = getit(); 26 | late List settingItemsCalendarOptions; 27 | @override 28 | void initState() { 29 | streamController = getit>(); 30 | fontList = ['Dancing', 'IRanSans', 'Default']; 31 | toggleViewTypeList = ['true', 'false']; 32 | viewTypeList = ['DAILY', 'MONTHLY']; 33 | settingItemsCalendarOptions = [ 34 | ExpandedItemModel( 35 | icon: 'assets/language_icon.svg', 36 | title: "View Type", 37 | body: RadioButtonList( 38 | initValue: calendarEventModel.calendarOptions.viewType.name, 39 | listItems: viewTypeList, 40 | onChanged: (keyName) { 41 | calendarEventModel.calendarOptions.viewType = ViewType.values 42 | .firstWhere((element) => element.name == keyName); 43 | streamController.sink.add(calendarEventModel); 44 | }, 45 | ), 46 | definition: 47 | "View Type:Change the Calendar view type to Daily or Monthly "), 48 | ExpandedItemModel( 49 | icon: 'assets/calendar.svg', 50 | title: "ToggleView Type", 51 | body: RadioButtonList( 52 | initValue: 53 | calendarEventModel.calendarOptions.toggleViewType.toString(), 54 | listItems: toggleViewTypeList, 55 | onChanged: (keyName) { 56 | calendarEventModel.calendarOptions.toggleViewType = 57 | keyName.toLowerCase() == 'true'; 58 | streamController.sink.add(calendarEventModel); 59 | }), 60 | definition: 61 | "ToggleView:It adds an icon that clicking on it helps to switch between Monthly and Daily"), 62 | ExpandedItemModel( 63 | icon: 'assets/calendar.svg', 64 | title: "Font", 65 | body: RadioButtonList( 66 | initValue: calendarEventModel.calendarOptions.font == '' 67 | ? 'Default' 68 | : calendarEventModel.calendarOptions.font, 69 | listItems: fontList, 70 | onChanged: (keyName) { 71 | calendarEventModel.calendarOptions.font = keyName; 72 | streamController.sink.add(calendarEventModel); 73 | }), 74 | definition: "Font: permits calendar font customization."), 75 | ExpandedItemModel( 76 | icon: 'assets/color_filter.svg', 77 | title: 'Calendar Color', 78 | body: ColorPickerRow( 79 | title: "background", 80 | currentColor: 81 | calendarEventModel.calendarOptions.headerMonthBackColor, 82 | onChanged: (colorSelected) { 83 | calendarEventModel.calendarOptions.headerMonthBackColor = 84 | colorSelected; 85 | streamController.sink.add(calendarEventModel); 86 | }), 87 | definition: "Calendar Color: The color of the Calendar's background") 88 | ]; 89 | super.initState(); 90 | } 91 | 92 | @override 93 | Widget build(BuildContext context) { 94 | return ItemSetting( 95 | title: "Calendar Options", 96 | expandeditemModelList: settingItemsCalendarOptions); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /lib/src/handlers/calendar_utils.dart: -------------------------------------------------------------------------------- 1 | import 'package:collection/collection.dart'; 2 | 3 | import '../../flutter_event_calendar.dart'; 4 | import 'translator.dart'; 5 | 6 | class CalendarUtils { 7 | static goToYear(index) { 8 | EventCalendar.dateTime = EventCalendar.calendarProvider.goToYear(index); 9 | } 10 | 11 | static goToMonth(index) { 12 | EventCalendar.dateTime = EventCalendar.calendarProvider.goToMonth(index); 13 | } 14 | 15 | static goToDay(index) { 16 | EventCalendar.dateTime = EventCalendar.calendarProvider.goToDay(index); 17 | } 18 | 19 | static nextDay() { 20 | EventCalendar.dateTime = 21 | EventCalendar.calendarProvider.getNextDayDateTime(); 22 | } 23 | 24 | static previousDay() { 25 | EventCalendar.dateTime = 26 | EventCalendar.calendarProvider.getPreviousDayDateTime(); 27 | } 28 | 29 | static nextMonth() { 30 | EventCalendar.dateTime = 31 | EventCalendar.calendarProvider.getNextMonthDateTime(); 32 | } 33 | 34 | static previousMonth() { 35 | EventCalendar.dateTime = 36 | EventCalendar.calendarProvider.getPreviousMonthDateTime(); 37 | } 38 | 39 | static List getYears() => EventCalendar.calendarProvider.getYears(); 40 | static List getDaysAmount() => EventCalendar.calendarProvider.getDayAmount(); 41 | 42 | static Map getDays(WeekDayStringTypes type, int monthIndex) { 43 | return EventCalendar.calendarProvider.getMonthDays(type, monthIndex); 44 | 45 | 46 | } 47 | 48 | static Map getMonthDays(WeekDayStringTypes type, int monthIndex) => 49 | EventCalendar.calendarProvider.getMonthDays(type, monthIndex); 50 | 51 | static getPartByString( 52 | {required PartFormat format, required HeaderOptions options}) { 53 | return Translator.getPartTranslate(options, format, 54 | EventCalendar.calendarProvider.getDateTimePart(format) - 1); 55 | } 56 | 57 | static getPartByInt({required PartFormat format}) { 58 | return EventCalendar.calendarProvider.getDateTimePart(format); 59 | } 60 | 61 | static CalendarDateTime? getFromSpecialDay( 62 | List specialDays, int year, int month, int day) { 63 | return specialDays.firstWhereOrNull((element) => _isRange(element) 64 | ? isInRange(element, year, month, day) 65 | : element.isDateEqualByInt(year, month, day)); 66 | } 67 | 68 | static _isRange(CalendarDateTime element) => 69 | element.toMonth != null || element.toDay != null; 70 | 71 | static isEndOfRange(CalendarDateTime? element, int year, int month, int day) { 72 | if (element?.year != year) return false; 73 | if (element?.toMonth == null) { 74 | if (element?.toDay == null) return element?.day == day; 75 | return element?.toDay == day; 76 | } else if (element?.toMonth == month) { 77 | if (element?.toDay == null) return element?.day == day; 78 | return element?.toDay == day; 79 | } 80 | return false; 81 | } 82 | 83 | static isStartOfRange( 84 | CalendarDateTime? element, int year, int month, int day) => 85 | element?.year == year && element?.month == month && element?.day == day; 86 | 87 | static isInRange( 88 | CalendarDateTime? selectedDatetime, int year, int month, int day) { 89 | if (selectedDatetime?.year != year) return false; 90 | if (selectedDatetime?.month != null && selectedDatetime!.month > month) 91 | return false; 92 | if (selectedDatetime?.toMonth != null && selectedDatetime!.toMonth! < month) 93 | return false; 94 | if (selectedDatetime?.day != null && 95 | selectedDatetime!.month == month && 96 | selectedDatetime.day > day) return false; 97 | 98 | if (selectedDatetime?.toMonth != null) { 99 | if (selectedDatetime!.toDay != null && 100 | selectedDatetime.toMonth == month && 101 | selectedDatetime.toDay! < day) return false; 102 | } else { 103 | if (selectedDatetime!.toDay != null && 104 | (selectedDatetime.month != month || selectedDatetime.toDay! < day)) 105 | return false; 106 | } 107 | return true; 108 | } 109 | 110 | static isBeforeThanToday(int currentYear, int currentMonth, int currentDay) { 111 | CalendarDateTime now = EventCalendar.calendarProvider.getDateTime(); 112 | DateTime currentDateTime = DateTime(currentYear, currentMonth, currentDay); 113 | return currentDateTime.difference(now.toDateTime()).isNegative; 114 | } 115 | 116 | static CalendarType getCalendarType() { 117 | return EventCalendar.calendarProvider.getCalendarType(); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /example/lib/widgets/setting/header_options.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_event_calendar/flutter_event_calendar.dart'; 4 | import 'package:flutter_event_calendar_example/injection.dart'; 5 | import 'package:flutter_event_calendar_example/models/calendar_event_model.dart'; 6 | import 'package:flutter_event_calendar_example/models/expanded_item_model.dart'; 7 | import 'package:flutter_event_calendar_example/widgets/color/color_picker_row.dart'; 8 | import 'package:flutter_event_calendar_example/widgets/setting/item_setting.dart'; 9 | import 'package:flutter_event_calendar_example/widgets/setting/radio_button_list.dart'; 10 | 11 | class HeaderOptions extends StatefulWidget { 12 | HeaderOptions({ 13 | Key? key, 14 | }) : super(key: key); 15 | 16 | @override 17 | State createState() => _HeaderOptionsState(); 18 | } 19 | 20 | class _HeaderOptionsState extends State { 21 | late StreamController streamController; 22 | 23 | CalendarEventModel calendarEventModel = getit(); 24 | late List calendarMonthTypeList; 25 | late List calendarWeekDayTypeList; 26 | late List settingItemsHeaderOptions; 27 | @override 28 | void initState() { 29 | streamController = getit>(); 30 | calendarMonthTypeList = [ 31 | MonthStringTypes.SHORT.name, 32 | MonthStringTypes.FULL.name 33 | ]; 34 | calendarWeekDayTypeList = [ 35 | WeekDayStringTypes.SHORT.name, 36 | WeekDayStringTypes.FULL.name 37 | ]; 38 | settingItemsHeaderOptions = [ 39 | ExpandedItemModel( 40 | icon: 'assets/calendar.svg', 41 | title: "WeekDay Type", 42 | body: RadioButtonList( 43 | initValue: 44 | calendarEventModel.headerOptions.weekDayStringType.name, 45 | listItems: calendarWeekDayTypeList, 46 | onChanged: (keyName) { 47 | calendarEventModel.headerOptions.weekDayStringType = 48 | WeekDayStringTypes.values 49 | .firstWhere((element) => element.name == keyName); 50 | streamController.sink.add(calendarEventModel); 51 | setState(() {}); 52 | }), 53 | definition: "WeekDayType:abbreviate days of the week"), 54 | ExpandedItemModel( 55 | icon: 'assets/calendar.svg', 56 | title: "Month Type", 57 | body: RadioButtonList( 58 | initValue: calendarEventModel.headerOptions.monthStringType.name, 59 | listItems: calendarMonthTypeList, 60 | onChanged: (keyName) { 61 | calendarEventModel.headerOptions.monthStringType = 62 | MonthStringTypes.values 63 | .firstWhere((element) => element.name == keyName); 64 | streamController.sink.add(calendarEventModel); 65 | setState(() {}); 66 | }), 67 | definition: "Monthtype:abbreviate months of the year"), 68 | ExpandedItemModel( 69 | icon: 'assets/calendar.svg', 70 | title: "navigationColor", 71 | body: ColorPickerRow( 72 | title: "navigation", 73 | currentColor: calendarEventModel.headerOptions.navigationColor, 74 | onChanged: (colorSelected) { 75 | calendarEventModel.headerOptions.navigationColor = 76 | colorSelected; 77 | streamController.sink.add(calendarEventModel); 78 | setState(() {}); 79 | }), 80 | definition: "navigationColor:The color of Header navigation icons"), 81 | ExpandedItemModel( 82 | icon: 'assets/calendar.svg', 83 | title: "headerTextColor", 84 | body: ColorPickerRow( 85 | title: "headerText", 86 | currentColor: calendarEventModel.headerOptions.headerTextColor, 87 | onChanged: (dynamic colorSelected) { 88 | calendarEventModel.headerOptions.headerTextColor = 89 | colorSelected; 90 | streamController.sink.add(calendarEventModel); 91 | setState(() {}); 92 | }), 93 | definition: "headerTextColor:The color of Header Text"), 94 | ]; 95 | super.initState(); 96 | } 97 | 98 | @override 99 | Widget build(BuildContext context) { 100 | return ItemSetting( 101 | title: "Header Options", 102 | expandeditemModelList: settingItemsHeaderOptions, 103 | ); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /lib/src/providers/calendars/gregorian_calendar.dart: -------------------------------------------------------------------------------- 1 | import '../../../flutter_event_calendar.dart'; 2 | import '../../handlers/translator.dart'; 3 | import 'calendar_provider.dart'; 4 | 5 | class GregorianCalendar extends CalendarProvider { 6 | @override 7 | CalendarDateTime getDateTime() { 8 | return CalendarDateTime.parseDateTime(DateTime.now().toString(), getCalendarType())!; 9 | } 10 | 11 | @override 12 | CalendarDateTime getNextMonthDateTime() { 13 | final date = _getSelectedDate(); 14 | return CalendarDateTime.parseDateTime(DateTime(date.year, date.month + 1, 1).toString(), getCalendarType())!; 15 | } 16 | 17 | @override 18 | CalendarDateTime getPreviousMonthDateTime() { 19 | final date = _getSelectedDate(); 20 | return CalendarDateTime.parseDateTime(DateTime(date.year, date.month - 1, 1).toString(), getCalendarType())!; 21 | } 22 | 23 | @override 24 | CalendarDateTime getPreviousDayDateTime() { 25 | final date = _getSelectedDate(); 26 | return CalendarDateTime(year: date.year, month: date.month, day: date.day - 1, calendarType: getCalendarType()); 27 | } 28 | 29 | @override 30 | CalendarDateTime getNextDayDateTime() { 31 | final date = _getSelectedDate(); 32 | return CalendarDateTime(year: date.year, month: date.month, day: date.day + 1, calendarType: getCalendarType()); 33 | } 34 | 35 | @override 36 | bool isRTL() => Translator.isRTL(); 37 | 38 | @override 39 | Map getMonthDays(WeekDayStringTypes type, int index) { 40 | Map days = {}; 41 | CalendarDateTime now = _getSelectedDate(); 42 | int monthLength = DateTime(now.year, index + 1, 0).day; 43 | DateTime firstDayOfMonth = DateTime(now.year, index, 1); 44 | int dayIndex = firstDayOfMonth.weekday; 45 | 46 | switch (type) { 47 | case WeekDayStringTypes.FULL: 48 | for (var i = 1; i <= monthLength; i++) { 49 | days[i] = Translator.getFullNameOfDays()[dayIndex % 7]; 50 | dayIndex++; 51 | } 52 | break; 53 | case WeekDayStringTypes.SHORT: 54 | for (var i = 1; i <= monthLength; i++) { 55 | days[i] = Translator.getShortNameOfDays()[dayIndex % 7]; 56 | dayIndex++; 57 | } 58 | break; 59 | } 60 | return days; 61 | } 62 | 63 | @override 64 | Map getMonthDaysShort(int index) { 65 | Map days = {}; 66 | CalendarDateTime now = _getSelectedDate(); 67 | int monthLength = DateTime(now.year, index + 1, 0).day; 68 | DateTime firstDayOfMonth = DateTime(now.year, index, 1); 69 | int dayIndex = firstDayOfMonth.weekday; 70 | for (var i = 1; i <= monthLength; i++) { 71 | days[i] = Translator.getShortNameOfDays()[dayIndex % 7]; 72 | dayIndex++; 73 | } 74 | return days; 75 | } 76 | 77 | @override 78 | List getYears() { 79 | int year = _getSelectedDate().year; 80 | List years = []; 81 | for (var i = -100; i <= 50; i++) years.add(year + i); 82 | return years; 83 | } 84 | @override 85 | List getDayAmount() { 86 | int month=_getSelectedDate().month; 87 | int daysinCurrentMonth=getMonthDays(WeekDayStringTypes.FULL, month).length; 88 | List days=[]; 89 | for (var i = 1; i <= daysinCurrentMonth; i++) days.add(i); 90 | return days; 91 | } 92 | CalendarDateTime _getSelectedDate() { 93 | return EventCalendar.dateTime!; 94 | } 95 | 96 | @override 97 | CalendarDateTime goToDay(index) { 98 | dynamic date = _getSelectedDate(); 99 | return CalendarDateTime(year: date.year, month: date.month, day: index, calendarType: getCalendarType()); 100 | } 101 | 102 | @override 103 | CalendarDateTime goToMonth(index) { 104 | dynamic date = _getSelectedDate(); 105 | return CalendarDateTime(year: date.year, month: index, day: 1, calendarType: getCalendarType()); 106 | } 107 | 108 | @override 109 | CalendarDateTime goToYear(index) { 110 | dynamic date = _getSelectedDate(); 111 | return CalendarDateTime(year: index, month: date.month, day: 1, calendarType: getCalendarType()); 112 | } 113 | 114 | @override 115 | int getDateTimePart(PartFormat format) { 116 | CalendarDateTime date = _getSelectedDate(); 117 | switch (format) { 118 | case PartFormat.YEAR: 119 | return date.year; 120 | case PartFormat.MONTH: 121 | return date.month; 122 | case PartFormat.DAY: 123 | return date.day; 124 | } 125 | } 126 | 127 | @override 128 | String getFormattedDate({DateTime? customDate}) { 129 | CalendarDateTime? dateTime; 130 | if (customDate != null) { 131 | dateTime = CalendarDateTime.parseDateTime(customDate.toString(), getCalendarType()); 132 | } else { 133 | dateTime = _getSelectedDate(); 134 | } 135 | return "${dateTime!.day} ${Translator.getFullMonthNames()[dateTime.month - 1]} ${dateTime.year}"; 136 | } 137 | 138 | @override 139 | CalendarType getCalendarType() { 140 | return CalendarType.GREGORIAN; 141 | } 142 | 143 | 144 | } 145 | -------------------------------------------------------------------------------- /example/lib/widgets/setting/date_picker.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter_event_calendar/flutter_event_calendar.dart'; 5 | import 'package:flutter_event_calendar/src/handlers/calendar_utils.dart'; 6 | import 'package:flutter_event_calendar_example/injection.dart'; 7 | import 'package:flutter_event_calendar_example/models/calendar_event_model.dart'; 8 | import 'package:flutter_event_calendar_example/widgets/setting/header_special_days.dart'; 9 | 10 | class DatePicker extends StatefulWidget { 11 | DatePicker( 12 | {Key? key, 13 | required this.onMonthChanged, 14 | required this.onYearChanged, 15 | required this.onDayChanged}) 16 | : super(key: key); 17 | Function onMonthChanged; 18 | Function onYearChanged; 19 | Function onDayChanged; 20 | 21 | @override 22 | State createState() => _DatePickerState(); 23 | } 24 | 25 | class _DatePickerState extends State { 26 | late StreamController streamController; 27 | 28 | bool existElement = false; 29 | bool emptyField = false; 30 | int day = 0; 31 | int month = 0; 32 | int year = 0; 33 | late CalendarEventModel calendarEventModel; 34 | late List specialDayList; 35 | 36 | @override 37 | void initState() { 38 | calendarEventModel = getit(); 39 | specialDayList = calendarEventModel.specialDays; 40 | super.initState(); 41 | } 42 | 43 | @override 44 | Widget build(BuildContext context) { 45 | streamController = getit>(); 46 | CalendarDateTime calendarDateTime = CalendarDateTime( 47 | year: year, 48 | month: month, 49 | day: day, 50 | calendarType: CalendarUtils.getCalendarType(), 51 | color: Colors.green); 52 | 53 | return Column( 54 | children: [ 55 | HeaderSpecialDays( 56 | calendarDateTime: calendarDateTime, 57 | speacialDate: (CalendarDateTime calendarDateTimee) { 58 | year = calendarDateTimee.year; 59 | day = calendarDateTimee.day; 60 | month = calendarDateTimee.month; 61 | calendarDateTime = calendarDateTimee; 62 | }, 63 | ), 64 | Container( 65 | margin: EdgeInsets.symmetric(horizontal: 20, vertical: 5), 66 | child: TextButton( 67 | style: ElevatedButton.styleFrom( 68 | primary: Colors.blue, 69 | minimumSize: const Size.fromHeight(10), 70 | ), 71 | onPressed: () { 72 | existElement = searchForDuplicateDate( 73 | specialDayList, calendarDateTime, context); 74 | emptyField = showToastNotchooseDate(calendarDateTime, context); 75 | if (!existElement && !emptyField) { 76 | streamController.sink.add(calendarEventModel); 77 | setState(() { 78 | specialDayList.add(calendarDateTime); 79 | }); 80 | } 81 | }, 82 | child: Text( 83 | "Add", 84 | style: TextStyle(color: Colors.white), 85 | ), 86 | ), 87 | ), 88 | specialDayList.length > 0 89 | ? ListView.separated( 90 | itemCount: specialDayList.length, 91 | shrinkWrap: true, 92 | itemBuilder: (BuildContext context, int index) { 93 | return Row( 94 | mainAxisAlignment: MainAxisAlignment.spaceAround, 95 | children: [ 96 | Text(specialDayList[index].day.toString()), 97 | Text(specialDayList[index].month.toString()), 98 | Text(specialDayList[index].year.toString()), 99 | IconButton( 100 | onPressed: () { 101 | setState(() { 102 | specialDayList.removeAt(index); 103 | }); 104 | }, 105 | icon: Icon(Icons.delete)) 106 | ], 107 | ); 108 | }, 109 | separatorBuilder: (BuildContext context, int index) => 110 | Divider(), 111 | ) 112 | : SizedBox() 113 | ], 114 | ); 115 | } 116 | } 117 | 118 | bool searchForDuplicateDate(List array, 119 | CalendarDateTime calendarDateTime, BuildContext context) { 120 | for (int i = 0; i < array.length; i++) { 121 | if (array[i].year == calendarDateTime.year && 122 | array[i].month == calendarDateTime.month && 123 | array[i].day == calendarDateTime.day) { 124 | ScaffoldMessenger.of(context).showSnackBar(SnackBar( 125 | content: Text("this date already exist"), 126 | duration: const Duration(seconds: 1), 127 | )); 128 | return true; 129 | } 130 | } 131 | return false; 132 | } 133 | 134 | bool showToastNotchooseDate( 135 | CalendarDateTime calendarDateTime, BuildContext context) { 136 | if (calendarDateTime.year == 0 || 137 | calendarDateTime.month == 0 || 138 | calendarDateTime.day == 0) { 139 | ScaffoldMessenger.of(context).showSnackBar(SnackBar( 140 | content: Text("please enter a valid date "), 141 | duration: const Duration(seconds: 1), 142 | )); 143 | return true; 144 | } 145 | return false; 146 | } 147 | -------------------------------------------------------------------------------- /lib/src/providers/calendars/jalali_calendar.dart: -------------------------------------------------------------------------------- 1 | import 'package:shamsi_date/shamsi_date.dart'; 2 | 3 | import '../../../flutter_event_calendar.dart'; 4 | import '../../handlers/translator.dart'; 5 | import 'calendar_provider.dart'; 6 | 7 | class JalaliCalendar extends CalendarProvider { 8 | @override 9 | CalendarDateTime getDateTime() { 10 | final f = Jalali.now().formatter; 11 | 12 | return CalendarDateTime( 13 | year: int.parse(f.yyyy), month: int.parse(f.mm), day: int.parse(f.dd), calendarType: getCalendarType()); 14 | } 15 | 16 | @override 17 | CalendarDateTime getNextMonthDateTime() { 18 | final date = _getSelectedDate(); 19 | final newDate = date.withDay(1).addMonths(1); 20 | final f = newDate.formatter; 21 | return CalendarDateTime(year: int.parse(f.y), month: int.parse(f.mm), day: 01, calendarType: getCalendarType()); 22 | } 23 | 24 | @override 25 | CalendarDateTime getPreviousMonthDateTime() { 26 | final date = _getSelectedDate(); 27 | dynamic newDate = date.withDay(1).addMonths(-1); 28 | final f = newDate.formatter; 29 | return CalendarDateTime(year: int.parse(f.y), month: int.parse(f.mm), day: 01, calendarType: getCalendarType()); 30 | } 31 | 32 | @override 33 | CalendarDateTime getPreviousDayDateTime() { 34 | dynamic date = _getSelectedDate(); 35 | dynamic newDate = date.addDays(-1); 36 | final f = newDate.formatter; 37 | return CalendarDateTime( 38 | year: int.parse(f.y), month: int.parse(f.mm), day: int.parse(f.dd), calendarType: getCalendarType()); 39 | } 40 | 41 | @override 42 | CalendarDateTime getNextDayDateTime() { 43 | dynamic date = _getSelectedDate(); 44 | dynamic newDate = date.addDays(1); 45 | final f = newDate.formatter; 46 | return CalendarDateTime( 47 | year: int.parse(f.y), month: int.parse(f.mm), day: int.parse(f.dd), calendarType: getCalendarType()); 48 | } 49 | 50 | @override 51 | bool isRTL() => Translator.isRTL(); 52 | 53 | @override 54 | Map getMonthDays(WeekDayStringTypes type, int index) { 55 | Map days = {}; 56 | Jalali firstDayOfMonth = _getSelectedDate().withMonth(index).withDay(1); 57 | int dayIndex = firstDayOfMonth.weekDay - 1; 58 | switch (type) { 59 | case WeekDayStringTypes.FULL: 60 | for (var i = 1; i <= firstDayOfMonth.monthLength; i++) { 61 | days[i] = Translator.getFullNameOfDays()[dayIndex % 7]; 62 | dayIndex++; 63 | } 64 | break; 65 | case WeekDayStringTypes.SHORT: 66 | for (var i = 1; i <= firstDayOfMonth.monthLength; i++) { 67 | days[i] = Translator.getShortNameOfDays()[dayIndex % 7]; 68 | dayIndex++; 69 | } 70 | break; 71 | } 72 | return days; 73 | } 74 | 75 | @override 76 | List getYears() { 77 | int year = _getSelectedDate().year; 78 | List years = []; 79 | for (var i = -100; i <= 50; i++) years.add(year + i); 80 | return years; 81 | } 82 | @override 83 | List getDayAmount() { 84 | int month=_getSelectedDate().month; 85 | int daysInCurrentMonth=getMonthDays(WeekDayStringTypes.FULL, month).length; 86 | List days=[]; 87 | for (var i = 1; i <= daysInCurrentMonth; i++) days.add(i); 88 | return days; 89 | } 90 | Jalali _getSelectedDate() { 91 | Jalali jv = Jalali( 92 | EventCalendar.dateTime!.year, 93 | EventCalendar.dateTime!.month, 94 | EventCalendar.dateTime!.day, 95 | ); 96 | return jv; 97 | } 98 | 99 | @override 100 | CalendarDateTime goToDay(index) { 101 | dynamic date = _getSelectedDate(); 102 | final f = date.formatter; 103 | return CalendarDateTime(year: int.parse(f.y), month: int.parse(f.mm), day: index, calendarType: getCalendarType()); 104 | } 105 | 106 | @override 107 | CalendarDateTime goToMonth(index) { 108 | dynamic date = _getSelectedDate(); 109 | final f = date.formatter; 110 | return CalendarDateTime(year: int.parse(f.y), month: index, day: 01, calendarType: getCalendarType()); 111 | } 112 | 113 | @override 114 | CalendarDateTime goToYear(index) { 115 | dynamic date = _getSelectedDate(); 116 | final f = date.formatter; 117 | return CalendarDateTime(year: index, month: int.parse(f.mm), day: 01, calendarType: getCalendarType()); 118 | } 119 | 120 | @override 121 | int getDateTimePart(PartFormat format) { 122 | Jalali date = _getSelectedDate(); 123 | switch (format) { 124 | case PartFormat.YEAR: 125 | return date.year; 126 | case PartFormat.MONTH: 127 | return date.month; 128 | case PartFormat.DAY: 129 | return date.day; 130 | } 131 | } 132 | 133 | @override 134 | Map getMonthDaysShort(int index) { 135 | Map days = {}; 136 | Jalali firstDayOfMonth = _getSelectedDate().withMonth(index).withDay(1); 137 | int dayIndex = firstDayOfMonth.weekDay - 1; 138 | for (var i = 1; i <= firstDayOfMonth.monthLength; i++) { 139 | days[i] = Translator.getShortNameOfDays()[dayIndex % 7]; 140 | dayIndex++; 141 | 142 | } 143 | return days; 144 | } 145 | 146 | @override 147 | String getFormattedDate({DateTime? customDate}) { 148 | Jalali? dateTime; 149 | if (customDate != null) { 150 | dateTime = Jalali.fromDateTime(customDate); 151 | } else { 152 | dateTime = _getSelectedDate(); 153 | } 154 | return "${dateTime.day} ${Translator.getFullMonthNames()[dateTime.month - 1]} ${dateTime.year}"; 155 | } 156 | 157 | @override 158 | CalendarType getCalendarType() { 159 | return CalendarType.JALALI; 160 | } 161 | 162 | 163 | } 164 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | email. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /lib/src/widgets/day.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | import '../../flutter_event_calendar.dart'; 6 | 7 | class Day extends StatelessWidget { 8 | String weekDay; 9 | Function? onCalendarChanged; 10 | List dayEvents; 11 | int day; 12 | DayOptions? dayOptions; 13 | CalendarOptions? calendarOptions; 14 | DayStyle? dayStyle; 15 | late double opacity; 16 | 17 | Day( 18 | {required this.day, 19 | required this.weekDay, 20 | required this.dayEvents, 21 | this.dayOptions, 22 | this.dayStyle, 23 | this.onCalendarChanged, 24 | this.calendarOptions}) 25 | : super() { 26 | dayOptions ??= DayOptions(); 27 | dayStyle ??= const DayStyle(); 28 | calendarOptions ??= CalendarOptions(); 29 | } 30 | 31 | late Widget child; 32 | 33 | late Color textColor; 34 | 35 | @override 36 | Widget build(BuildContext context) { 37 | dayOptions = DayOptions.of(context); 38 | calendarOptions = CalendarOptions.of(context); 39 | opacity = _shouldHaveTransparentColor() ? 0.5 : 1; 40 | 41 | textColor = dayStyle!.useDisabledEffect 42 | ? dayOptions!.disabledTextColor 43 | : dayStyle!.selected 44 | ? dayOptions!.selectedTextColor 45 | : dayOptions!.unselectedTextColor; 46 | 47 | child = InkWell( 48 | onTap: (() { 49 | if (dayStyle!.enabled) onCalendarChanged?.call(); 50 | }), 51 | child: Column( 52 | crossAxisAlignment: CrossAxisAlignment.center, 53 | mainAxisAlignment: MainAxisAlignment.center, 54 | mainAxisSize: MainAxisSize.max, 55 | children: [ 56 | if (DayOptions.of(context).showWeekDay && 57 | CalendarOptions.of(context).viewType == ViewType.DAILY) ...[ 58 | FittedBox( 59 | child: Text( 60 | '$weekDay', 61 | maxLines: 1, 62 | overflow: TextOverflow.ellipsis, 63 | style: TextStyle( 64 | color: _getTitleColor(), 65 | fontFamily: CalendarOptions.of(context).font, 66 | ), 67 | ), 68 | ), 69 | ], 70 | AnimatedContainer( 71 | duration: Duration(milliseconds: 500), 72 | curve: Curves.ease, 73 | padding: dayStyle!.compactMode 74 | ? EdgeInsets.zero 75 | : (EdgeInsets.all(HeaderOptions.of(context).weekDayStringType == 76 | WeekDayStringTypes.FULL 77 | ? 4 78 | : 0)), 79 | decoration: BoxDecoration( 80 | color: dayStyle!.selected 81 | ? dayOptions!.selectedBackgroundColor 82 | : dayOptions!.unselectedBackgroundColor, 83 | shape: BoxShape.circle), 84 | constraints: BoxConstraints( 85 | minWidth: double.infinity, minHeight: dayStyle!.compactMode ? 35 : 40), 86 | child: Stack( 87 | fit: StackFit.passthrough, 88 | children: [ 89 | Align( 90 | alignment: Alignment.center, 91 | child: Text( 92 | '$day', 93 | style: TextStyle( 94 | color: textColor, 95 | fontFamily: CalendarOptions.of(context).font, 96 | ), 97 | ), 98 | ), 99 | dayOptions!.eventCounterViewType == DayEventCounterViewType.DOT 100 | ? Align( 101 | alignment: Alignment.bottomCenter, 102 | child: dotMaker(context), 103 | ) 104 | : Positioned( 105 | right: 0, 106 | bottom: 0, 107 | child: labelMaker(context), 108 | ), 109 | ], 110 | ), 111 | ), 112 | ], 113 | ), 114 | ); 115 | // } 116 | return Opacity( 117 | opacity: opacity, 118 | child: Container( 119 | padding: EdgeInsets.all(dayStyle!.compactMode ? 0 : CalendarOptions.of(context).viewType==ViewType.DAILY?10:0), 120 | decoration: dayStyle?.decoration, 121 | width: dayStyle!.compactMode 122 | ? 45 123 | : (HeaderOptions.of(context).weekDayStringType == 124 | WeekDayStringTypes.FULL 125 | ? 80 126 | : 60), 127 | child: child, 128 | ), 129 | ); 130 | } 131 | 132 | dotMaker(BuildContext context) { 133 | List widgets = []; 134 | 135 | final maxDot = min(dayEvents.length, 3); 136 | for (int i = 0; i < maxDot; i++) { 137 | widgets.add( 138 | Container( 139 | margin: EdgeInsets.only( 140 | bottom: HeaderOptions.of(context).weekDayStringType == 141 | WeekDayStringTypes.SHORT 142 | ? (dayStyle!.compactMode ? 4 : 8) 143 | : 4), 144 | width: 5, 145 | height: 5, 146 | decoration: BoxDecoration( 147 | shape: BoxShape.circle, 148 | color: dayOptions!.eventCounterColor, 149 | ), 150 | ), 151 | ); 152 | if (i != maxDot - 1) { 153 | widgets.add( 154 | const SizedBox( 155 | width: 2, 156 | ), 157 | ); 158 | } 159 | } 160 | return Row( 161 | mainAxisSize: MainAxisSize.min, 162 | children: widgets, 163 | ); 164 | } 165 | 166 | labelMaker(BuildContext context) { 167 | if (dayEvents.isEmpty) return Container(); 168 | return Container( 169 | width: dayStyle!.compactMode ? 15 : 18, 170 | height: dayStyle!.compactMode ? 15 : 18, 171 | alignment: Alignment.center, 172 | decoration: BoxDecoration( 173 | shape: BoxShape.circle, 174 | color: dayOptions!.eventCounterColor, 175 | ), 176 | child: Text( 177 | "${dayEvents.length >= 10 ? '+9' : dayEvents.length}", 178 | style: TextStyle( 179 | fontSize: 12, 180 | fontFamily: CalendarOptions.of(context).font, 181 | color: dayStyle!.useUnselectedEffect 182 | ? dayOptions!.eventCounterTextColor.withOpacity(opacity) 183 | : dayOptions!.eventCounterTextColor), 184 | ), 185 | ); 186 | } 187 | 188 | _getTitleColor() { 189 | return dayStyle!.selected ? dayOptions!.weekDaySelectedColor : dayOptions!.weekDayUnselectedColor; 190 | } 191 | 192 | _shouldHaveTransparentColor() { 193 | return !dayStyle!.enabled || dayStyle!.useUnselectedEffect; 194 | } 195 | } 196 | 197 | class DayStyle { 198 | final bool compactMode; 199 | final bool useUnselectedEffect; 200 | final bool enabled; 201 | final bool selected; 202 | final bool useDisabledEffect; 203 | final BoxDecoration? decoration; 204 | 205 | const DayStyle({ 206 | this.compactMode = false, 207 | this.useUnselectedEffect = false, 208 | this.enabled = false, 209 | this.selected = false, 210 | this.decoration = const BoxDecoration(), 211 | this.useDisabledEffect = false, 212 | }); 213 | } 214 | -------------------------------------------------------------------------------- /lib/src/widgets/calendar_daily.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | import '../../flutter_event_calendar.dart'; 4 | import '../handlers/calendar_utils.dart'; 5 | 6 | import '../handlers/event_selector.dart'; 7 | 8 | import '../utils/style_provider.dart'; 9 | import 'day.dart'; 10 | 11 | class CalendarDaily extends StatelessWidget { 12 | Function? onCalendarChanged; 13 | var dayIndex; 14 | late ScrollController animatedTo; 15 | EventSelector selector = EventSelector(); 16 | List specialDays; 17 | 18 | CalendarDaily({this.onCalendarChanged, required this.specialDays}) : super() { 19 | dayIndex = CalendarUtils.getPartByInt(format: PartFormat.DAY); 20 | } 21 | 22 | @override 23 | Widget build(BuildContext context) { 24 | animatedTo = ScrollController( 25 | initialScrollOffset: (DayOptions.of(context).compactMode 26 | ? 40.0 27 | : (HeaderOptions.of(context).weekDayStringType == 28 | WeekDayStringTypes.FULL 29 | ? 80.0 30 | : 60.0)) * 31 | (dayIndex - 1)); 32 | 33 | executeAsync(context); 34 | // Yearly , Monthly , Weekly and Daily calendar 35 | return Container( 36 | height: DayOptions.of(context).showWeekDay 37 | ? DayOptions.of(context).compactMode 38 | ? 70 39 | : 100 40 | : 70, 41 | child: Stack( 42 | children: [ 43 | ListView( 44 | shrinkWrap: true, 45 | reverse: EventCalendar.calendarProvider.isRTL(), 46 | controller: animatedTo, 47 | scrollDirection: Axis.horizontal, 48 | children: daysMaker(context), 49 | ), 50 | DayOptions.of(context).disableFadeEffect 51 | ? const SizedBox() 52 | : Align( 53 | alignment: Alignment.centerLeft, 54 | child: IgnorePointer( 55 | child: Container( 56 | width: 70, 57 | decoration: const BoxDecoration( 58 | gradient: LinearGradient( 59 | begin: Alignment.centerLeft, 60 | end: Alignment.centerRight, 61 | colors: [Color(0xffffffff), Color(0x0affffff)], 62 | tileMode: TileMode.clamp, 63 | ), 64 | ), 65 | ), 66 | ), 67 | ), 68 | DayOptions.of(context).disableFadeEffect 69 | ? const SizedBox() 70 | : Align( 71 | alignment: Alignment.centerRight, 72 | child: IgnorePointer( 73 | child: Container( 74 | width: 70, 75 | decoration: const BoxDecoration( 76 | gradient: LinearGradient( 77 | begin: Alignment.centerRight, 78 | end: Alignment.centerLeft, 79 | colors: [Color(0xffffffff), Color(0x0affffff)], 80 | tileMode: TileMode.clamp, 81 | ), 82 | ), 83 | ), 84 | ), 85 | ), 86 | ], 87 | ), 88 | ); 89 | } 90 | 91 | List daysMaker(BuildContext context) { 92 | int currentMonth = CalendarUtils.getPartByInt(format: PartFormat.MONTH); 93 | int currentYear = CalendarUtils.getPartByInt(format: PartFormat.YEAR); 94 | 95 | final headersStyle = HeaderOptions.of(context); 96 | 97 | List days = [ 98 | SizedBox( 99 | width: DayOptions.of(context).compactMode 100 | ? 40 101 | : headersStyle.weekDayStringType == WeekDayStringTypes.FULL 102 | ? 80 103 | : 60) 104 | ]; 105 | 106 | int day = dayIndex; 107 | CalendarUtils.getDays(headersStyle.weekDayStringType, currentMonth) 108 | .forEach((index, weekDay) { 109 | final CalendarDateTime? specialDay = CalendarUtils.getFromSpecialDay( 110 | specialDays, currentYear, currentMonth, index); 111 | 112 | BoxDecoration? decoration = StyleProvider.getSpecialDayDecoration( 113 | specialDay, currentYear, currentMonth, index); 114 | 115 | var selected = index == day; 116 | 117 | bool isBeforeToday = 118 | CalendarUtils.isBeforeThanToday(currentYear, currentMonth, index); 119 | 120 | days.add(Day( 121 | day: index, 122 | dayEvents: selector.getEventsByDayMonthYear( 123 | CalendarDateTime( 124 | year: currentYear, 125 | month: currentMonth, 126 | day: index, 127 | calendarType: CalendarUtils.getCalendarType()), 128 | ), 129 | dayStyle: DayStyle( 130 | compactMode: DayOptions.of(context).compactMode, 131 | decoration: decoration, 132 | enabled: (specialDay?.isEnableDay ?? true), 133 | selected: selected, 134 | useUnselectedEffect: false, 135 | useDisabledEffect: DayOptions.of(context).disableDaysBeforeNow 136 | ? isBeforeToday 137 | : false, 138 | ), 139 | weekDay: weekDay, 140 | onCalendarChanged: () { 141 | CalendarUtils.goToDay(index); 142 | onCalendarChanged?.call(); 143 | }, 144 | )); 145 | }); 146 | 147 | days.add( 148 | SizedBox( 149 | width: DayOptions.of(context).compactMode 150 | ? 40 151 | : headersStyle.weekDayStringType == WeekDayStringTypes.FULL 152 | ? 80 153 | : 60, 154 | ), 155 | ); 156 | 157 | return days; 158 | } 159 | 160 | BoxDecoration? _getDecoration( 161 | CalendarDateTime? specialDay, curYear, int currMonth, day) { 162 | BoxDecoration? decoration; 163 | final isStartRange = 164 | CalendarUtils.isStartOfRange(specialDay, curYear, currMonth, day); 165 | final isEndRange = 166 | CalendarUtils.isEndOfRange(specialDay, curYear, currMonth, day); 167 | final isInRange = 168 | CalendarUtils.isInRange(specialDay, curYear, currMonth, day); 169 | 170 | if (isEndRange && isStartRange) { 171 | decoration = BoxDecoration( 172 | color: specialDay?.color, borderRadius: BorderRadius.circular(8)); 173 | } else if (isStartRange) { 174 | decoration = BoxDecoration( 175 | color: specialDay?.color, 176 | borderRadius: 177 | const BorderRadius.horizontal(right: Radius.circular(8))); 178 | } else if (isEndRange) { 179 | decoration = BoxDecoration( 180 | color: specialDay?.color, 181 | borderRadius: 182 | const BorderRadius.horizontal(left: Radius.circular(8))); 183 | } else if (isInRange) { 184 | decoration = BoxDecoration(color: specialDay?.color); 185 | } 186 | return decoration; 187 | } 188 | 189 | void executeAsync(context) async { 190 | WidgetsBinding.instance.addPostFrameCallback((timeStamp) { 191 | if (animatedTo.hasClients) { 192 | final animateOffset = (DayOptions.of(context).compactMode 193 | ? 40.0 194 | : (HeaderOptions.of(context).weekDayStringType == 195 | WeekDayStringTypes.FULL 196 | ? 80.0 197 | : 60.0)) * 198 | (dayIndex - 1); 199 | animatedTo.animateTo(animateOffset, 200 | duration: const Duration(milliseconds: 700), 201 | curve: Curves.decelerate); 202 | } 203 | }); 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /lib/src/handlers/event_calendar.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_event_calendar/flutter_event_calendar.dart'; 3 | import 'package:flutter_event_calendar/src/providers/calendars/calendar_provider.dart'; 4 | import 'package:flutter_event_calendar/src/providers/instance_provider.dart'; 5 | import 'package:flutter_event_calendar/src/widgets/calendar_daily.dart'; 6 | import 'package:flutter_event_calendar/src/widgets/calendar_monthly.dart'; 7 | import 'package:flutter_event_calendar/src/widgets/events.dart'; 8 | import 'package:flutter_event_calendar/src/widgets/header.dart'; 9 | import 'package:scoped_model/scoped_model.dart'; 10 | import 'calendar_utils.dart'; 11 | 12 | typedef CalendarChangeCallback = Function(CalendarDateTime); 13 | 14 | class EventCalendar extends StatefulWidget { 15 | static late CalendarProvider calendarProvider; 16 | static late CalendarDateTime? dateTime; 17 | static late List events; 18 | static List selectedEvents = []; 19 | 20 | // static late HeaderMonthStringTypes headerMonthStringType; 21 | // static late HeaderWeekDayStringTypes headerWeekDayStringType; 22 | static late String calendarLanguage; 23 | static late CalendarType calendarType; 24 | 25 | CalendarChangeCallback? onChangeDateTime; 26 | CalendarChangeCallback? onMonthChanged; 27 | CalendarChangeCallback? onYearChanged; 28 | CalendarChangeCallback? onDateTimeReset; 29 | ViewTypeChangeCallback? onChangeViewType; 30 | VoidCallback? onInit; 31 | 32 | List specialDays; 33 | 34 | CalendarOptions? calendarOptions; 35 | 36 | DayOptions? dayOptions; 37 | 38 | EventOptions? eventOptions; 39 | 40 | bool showLoadingForEvent; 41 | 42 | HeaderOptions? headerOptions; 43 | 44 | Widget? Function(CalendarDateTime)? middleWidget; 45 | 46 | bool showEvents; 47 | 48 | EventCalendar({ 49 | GlobalKey? key, 50 | List? events, 51 | CalendarDateTime? dateTime, 52 | this.middleWidget, 53 | this.calendarOptions, 54 | this.dayOptions, 55 | this.eventOptions, 56 | this.headerOptions, 57 | this.showLoadingForEvent = false, 58 | this.specialDays = const [], 59 | this.onChangeDateTime, 60 | this.onMonthChanged, 61 | this.onDateTimeReset, 62 | this.onInit, 63 | this.onYearChanged, 64 | this.onChangeViewType, 65 | required calendarType, 66 | calendarLanguage, 67 | this.showEvents = true 68 | }) : super(key: key) { 69 | calendarOptions ??= CalendarOptions(); 70 | headerOptions ??= HeaderOptions(); 71 | eventOptions ??= EventOptions(); 72 | dayOptions ??= DayOptions(); 73 | 74 | EventCalendar.calendarType = calendarType ?? CalendarType.GREGORIAN; 75 | 76 | EventCalendar.calendarProvider = createInstance(calendarType); 77 | 78 | if (key?.currentContext == null || calendarType != EventCalendar.calendarType) { 79 | EventCalendar.dateTime = dateTime ?? calendarProvider.getDateTime(); 80 | } 81 | EventCalendar.calendarType = calendarType ?? CalendarType.GREGORIAN; 82 | EventCalendar.calendarLanguage = calendarLanguage ?? 'en'; 83 | EventCalendar.events = events ?? []; 84 | } 85 | 86 | static void init({ 87 | required CalendarType calendarType, 88 | CalendarDateTime? dateTime, 89 | String? calendarLanguage, 90 | }) { 91 | EventCalendar.calendarProvider = createInstance(calendarType); 92 | EventCalendar.dateTime = 93 | dateTime ?? EventCalendar.calendarProvider.getDateTime(); 94 | EventCalendar.calendarType = calendarType; 95 | EventCalendar.calendarLanguage = calendarLanguage ?? 'en'; 96 | } 97 | 98 | @override 99 | _EventCalendarState createState() => _EventCalendarState(); 100 | } 101 | 102 | class _EventCalendarState extends State { 103 | @override 104 | void initState() { 105 | widget.onInit?.call(); 106 | super.initState(); 107 | } 108 | 109 | @override 110 | Widget build(BuildContext context) { 111 | return buildScopeModels( 112 | child: (context) { 113 | return SingleChildScrollView( 114 | child: Container( 115 | height: MediaQuery.of(context).size.height, 116 | child: Column( 117 | 118 | mainAxisSize: MainAxisSize.max, 119 | children: [ 120 | Card( 121 | color: CalendarOptions.of(context).headerMonthBackColor, 122 | shadowColor: CalendarOptions.of(context).headerMonthShadowColor, 123 | shape: CalendarOptions.of(context).headerMonthShape, 124 | elevation: CalendarOptions.of(context).headerMonthElevation, 125 | child: Column( 126 | children: [ 127 | Header( 128 | onDateTimeReset: () { 129 | widget.onDateTimeReset?.call(EventCalendar.dateTime!); 130 | setState(() {}); 131 | }, 132 | onMonthChanged: (int selectedMonth) { 133 | widget.onMonthChanged?.call(EventCalendar.dateTime!); 134 | CalendarUtils.goToMonth(selectedMonth); 135 | setState(() {}); 136 | }, 137 | onViewTypeChanged: (ViewType viewType) { 138 | setState(() {}); 139 | widget.onChangeViewType?.call(viewType); 140 | }, 141 | onYearChanged: (int selectedYear) { 142 | widget.onYearChanged?.call(EventCalendar.dateTime!); 143 | CalendarUtils.goToYear(selectedYear); 144 | setState(() {}); 145 | }, 146 | ), 147 | isMonthlyView() 148 | ? SingleChildScrollView( 149 | child: CalendarMonthly( 150 | specialDays: widget.specialDays, 151 | onCalendarChanged: () { 152 | widget.onChangeDateTime 153 | ?.call(EventCalendar.dateTime!); 154 | 155 | setState(() {}); 156 | }), 157 | ) 158 | : CalendarDaily( 159 | specialDays: widget.specialDays, 160 | onCalendarChanged: () { 161 | widget.onChangeDateTime 162 | ?.call(EventCalendar.dateTime!); 163 | setState(() {}); 164 | }), 165 | ], 166 | ), 167 | ), 168 | if (widget.middleWidget != null) 169 | widget.middleWidget!.call(EventCalendar.dateTime!)!, 170 | Events(onEventsChanged: () { 171 | widget.onChangeDateTime?.call(EventCalendar.dateTime!); 172 | setState(() {}); 173 | }), 174 | ], 175 | ), 176 | ), 177 | ); 178 | }, 179 | ); 180 | } 181 | 182 | isMonthlyView() { 183 | return widget.calendarOptions?.viewType == ViewType.MONTHLY; 184 | } 185 | 186 | buildScopeModels({required WidgetBuilder child}) { 187 | return ScopedModel( 188 | model: widget.calendarOptions!, 189 | child: ScopedModel( 190 | model: widget.dayOptions!, 191 | child: ScopedModel( 192 | model: widget.eventOptions!, 193 | child: ScopedModel( 194 | model: widget.headerOptions!, 195 | child: Builder(builder: child), 196 | ), 197 | ), 198 | ), 199 | ); 200 | } 201 | 202 | @override 203 | void dispose() { 204 | /// reset date time after disposing child 205 | EventCalendar.dateTime = EventCalendar.calendarProvider.getDateTime(); 206 | // EventCalendar.dateTime = null; 207 | super.dispose(); 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /lib/src/widgets/header.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter_event_calendar/flutter_event_calendar.dart'; 4 | import 'package:flutter_event_calendar/src/handlers/calendar_utils.dart'; 5 | import 'package:flutter_event_calendar/src/models/style/select_month_options.dart'; 6 | import 'package:flutter_event_calendar/src/models/style/select_year_options.dart'; 7 | import 'package:flutter_event_calendar/src/widgets/select_month.dart'; 8 | import 'package:flutter_event_calendar/src/widgets/select_year.dart'; 9 | typedef ViewTypeChangeCallback = Function(ViewType); 10 | 11 | class Header extends StatelessWidget { 12 | ViewTypeChangeCallback? onViewTypeChanged; 13 | Function onDateTimeReset; 14 | Function(int selectedYear) onYearChanged; 15 | Function(int selectedMonth) onMonthChanged; 16 | Header({required this.onViewTypeChanged,required this.onYearChanged,required this.onMonthChanged,required this.onDateTimeReset}); 17 | 18 | @override 19 | Widget build(BuildContext context) { 20 | return Material( 21 | color: Colors.transparent, 22 | child: Padding( 23 | padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8), 24 | child: Directionality( 25 | textDirection: EventCalendar.calendarProvider.isRTL() ? TextDirection.rtl : TextDirection.ltr, 26 | child: Row( 27 | crossAxisAlignment: CrossAxisAlignment.center, 28 | // Title , next and previous button 29 | children: [ 30 | Row( 31 | children: [ 32 | InkWell( 33 | onTap: () { 34 | CalendarUtils.goToDay(1); 35 | CalendarUtils.previousMonth(); 36 | onMonthChanged.call(CalendarUtils.getPartByInt(format:PartFormat.MONTH)); 37 | }, 38 | customBorder: CircleBorder(), 39 | child: Padding( 40 | padding: EdgeInsets.all(8), 41 | child: RotatedBox( 42 | quarterTurns: 2, 43 | child: Icon( 44 | Icons.arrow_forward_ios, 45 | size: 18, 46 | color: HeaderOptions.of(context).navigationColor, 47 | ), 48 | ), 49 | ), 50 | ), 51 | ], 52 | ), 53 | Expanded( 54 | child: FittedBox( 55 | fit: BoxFit.scaleDown, 56 | alignment: EventCalendar.calendarProvider.isRTL() ? Alignment.centerRight : Alignment.centerLeft, 57 | child: Row( 58 | crossAxisAlignment: CrossAxisAlignment.center, 59 | children: [ 60 | GestureDetector( 61 | onTap: () { 62 | showModalBottomSheet( 63 | backgroundColor: Colors.transparent, 64 | context: context, 65 | builder: (BuildContext mmm) { 66 | return SelectMonth( 67 | onHeaderChanged: onMonthChanged, 68 | monthStyle: MonthOptions( 69 | font: CalendarOptions.of(context).font, 70 | selectedColor: DayOptions.of(context) 71 | .selectedBackgroundColor, 72 | backgroundColor: CalendarOptions.of(context).bottomSheetBackColor 73 | ), 74 | ); 75 | }, 76 | ); 77 | }, 78 | child: Container( 79 | padding: EdgeInsets.symmetric(horizontal: 5), 80 | child: Text( 81 | '${CalendarUtils.getPartByString( 82 | format: PartFormat.MONTH, 83 | options: HeaderOptions.of(context), 84 | )}', 85 | style: TextStyle( 86 | fontWeight: FontWeight.w500, 87 | fontSize: 20, 88 | color: HeaderOptions.of(context).headerTextColor, 89 | fontFamily: CalendarOptions.of(context).font, 90 | ), 91 | ), 92 | ), 93 | ), 94 | GestureDetector( 95 | onTap: () { 96 | showModalBottomSheet( 97 | backgroundColor: Colors.transparent, 98 | context: context, 99 | builder: (BuildContext mmm) { 100 | return SelectYear( 101 | onHeaderChanged: onYearChanged, 102 | yearStyle: YearOptions( 103 | font: CalendarOptions.of(context).font, 104 | selectedColor: DayOptions.of(context) 105 | .selectedBackgroundColor, 106 | backgroundColor: CalendarOptions.of(context).bottomSheetBackColor 107 | ), 108 | ); 109 | }, 110 | ); 111 | }, 112 | child: Text( 113 | '${CalendarUtils.getPartByInt(format: PartFormat.YEAR)}', 114 | style: TextStyle( 115 | fontWeight: FontWeight.w500, 116 | fontSize: 20, 117 | color: HeaderOptions.of(context).headerTextColor, 118 | fontFamily: CalendarOptions.of(context).font, 119 | ), 120 | ), 121 | ), 122 | ], 123 | ), 124 | ), 125 | ), 126 | // if (!isInTodayIndex()) buildRefreshView(), 127 | Row( 128 | children: [ 129 | buildRefreshView(context), 130 | buildSelectViewType(context), 131 | InkWell( 132 | customBorder: CircleBorder(), 133 | onTap: () { 134 | CalendarUtils.goToDay(1); 135 | CalendarUtils.nextMonth(); 136 | onMonthChanged.call(CalendarUtils.getPartByInt(format:PartFormat.MONTH)); 137 | }, 138 | child: Padding( 139 | padding: EdgeInsets.all(8), 140 | child: Icon( 141 | Icons.arrow_forward_ios, 142 | size: 18, 143 | color: HeaderOptions.of(context).navigationColor, 144 | ), 145 | ), 146 | ), 147 | ], 148 | ), 149 | ], 150 | ), 151 | ), 152 | ), 153 | ); 154 | } 155 | 156 | isInTodayIndex() { 157 | return EventCalendar.dateTime!.isDateEqual(EventCalendar.calendarProvider.getDateTime()); 158 | } 159 | 160 | buildRefreshView(BuildContext context) { 161 | return AnimatedOpacity( 162 | duration: Duration(milliseconds: 300), 163 | opacity: !isInTodayIndex() ? 1 : 0, 164 | child: InkWell( 165 | customBorder: CircleBorder(), 166 | onTap: () { 167 | EventCalendar.dateTime = EventCalendar.calendarProvider.getDateTime(); 168 | onDateTimeReset.call(); 169 | }, 170 | child: Padding( 171 | padding: EdgeInsets.all(5), 172 | child: Icon( 173 | Icons.restore, 174 | size: 24, 175 | color: HeaderOptions.of(context).headerTextColor, 176 | ), 177 | ), 178 | ), 179 | ); 180 | } 181 | 182 | buildSelectViewType(BuildContext context) { 183 | if (CalendarOptions.of(context).toggleViewType) { 184 | return InkWell( 185 | customBorder: CircleBorder(), 186 | onTap: () { 187 | // EventCalendar.dateTime = EventCalendar.calendarProvider.getDateTime(); 188 | if (CalendarOptions.of(context).viewType == ViewType.MONTHLY) { 189 | CalendarOptions.of(context).viewType = ViewType.DAILY; 190 | } else { 191 | CalendarOptions.of(context).viewType = ViewType.MONTHLY; 192 | } 193 | onViewTypeChanged?.call(CalendarOptions.of(context).viewType); 194 | }, 195 | child: Padding( 196 | padding: const EdgeInsets.all(5), 197 | child: Icon( 198 | CalendarOptions.of(context).viewType == ViewType.MONTHLY 199 | ? Icons.calendar_today_outlined 200 | : Icons.calendar_today_outlined, 201 | size: 18, 202 | color: HeaderOptions.of(context).calendarIconColor, 203 | ), 204 | ), 205 | ); 206 | } 207 | return const SizedBox(); 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | flutter Event Calendar Package 3 |

4 | 5 |

6 | Pub 7 | License: MIT 8 |

9 | 10 | 11 | --- 12 | 13 | 14 | # Event Calendar 15 | 16 | ## How to install : 17 | 18 | Add this to your package's pubspec.yaml file: 19 | 20 | ```yaml 21 | dependencies: 22 | flutter_event_calendar: ^1.0.0 23 | ``` 24 | 25 | Then You can install packages from the command line: 26 | ```yaml 27 | $ pub get 28 | ``` 29 | 30 | or 31 | 32 | ```yaml 33 | $ flutter pub get 34 | ``` 35 | 36 | Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more. 37 | 38 | Now in your Dart code, you can use: 39 | 40 | ```dart 41 | import 'package:flutter_event_calendar/flutter_event_calendar.dart'; 42 | ``` 43 |

44 | flutter Event Calendar Package 45 |

46 | 47 | ## Basic Usage : 48 | 49 | You can load a full calendar with events . 50 | 51 | ```dart 52 | return EventCalendar( 53 | calendarType: CalendarType.JALALI, 54 | calendarLanguage: 'fa', 55 | events: [ 56 | Event( 57 | child: const Text('Laravel Event'), 58 | dateTime: CalendarDateTime( 59 | year: 1401, 60 | month: 5, 61 | day: 12, 62 | calendarType: CalendarType.JALALI, 63 | ), 64 | ), 65 | ], 66 | ); 67 | ``` 68 | 69 | 70 |

71 | flutter Event Calendar Package 72 |

73 | 74 | ## Options : 75 | 76 | You have many option for changes in : style , locale and structure. 77 | 78 | 79 | | Option | Type | 80 | |------------------------|---------------------------------------| 81 | | calendarType | CalendarType ( JALALI or GREGORIAN ) | 82 | | middleWidget | Widget | 83 | | events | List | 84 | | calendarOptions | CalendarOptions | 85 | | headerOptions | HeaderOptions | 86 | | eventOptions | EventOptions | 87 | | dayOptions | DayOptions | 88 | | showLoadingForEvent | bool | 89 | | specialDays | List | 90 | | calendarLanguage | String(fa,en,pt,de) | 91 | 92 | ### Events 93 | 94 | | Name | Description | 95 | |---------------------|---------------------------------------------------------------------------------------------------------------------| 96 | | onInit | Called when Event Calendar object is inserted into the tree. | 97 | | onChangeDateTime | Return a string of new date selected like (year-month-day) | 98 | | onMonthChanged | When the month changes return a string of CalendarDateTime (year-month-day hour:minute:second) | 99 | | onYearChanged | When the year changes return a string of CalendarDateTime (year-month-day hour:minute:second) | 100 | | onDateTimeReset | When clicking on the reset button return a string of current CalendarDateTime (year-month-day hour:minute:second) | 101 | | onChangeViewType | When clicking on the toggleViewType return ViewType | 102 | 103 | ## CalendarOptions : 104 | 105 | | Option | Type | Description | 106 | |---------------------------|--------------------------------|--------------------------------------------------------------------| 107 | | toggleViewType | bool | Whether user can toggle view type between monthly and daily or not | 108 | | viewType | ViewType | Default view type of Calendar Daily or Monthly | 109 | | font | String | Name of your font | 110 | | headerMonthBackColor | Color | The background color of Calendar card | 111 | | headerMonthShadowColor | Color | The shadow color of Calendar card | 112 | | headerMonthElevation | double | The elevation of shadow color Calendar card | 113 | | headerMonthShape | ShapeBorder | The shape of Calendar card like(RoundedRectangleBorder) | 114 | | bottomSheetBackColor | Color | The background color of select month and year bottom sheet) | 115 | 116 | ### HeaderOptions : 117 | 118 | | Option | Type | Description | 119 | |---------------------|--------------------------------|--------------------------------------| 120 | | weekDayStringType | WeekDayStringTypes | Day names FULL or SHORT | 121 | | MonthStringTypes | MonthStringTypes | Month names FULL or SHORT | 122 | | headerTextColor | Color | The color of Header Text | 123 | | navigationColor | Color | The color of Header navigation icons | 124 | | resetDateColor | Color | The color of reset date icon | 125 | 126 | ### EventOptions : 127 | 128 | | Option | Type | Description | 129 | |-------------------|--------------------------------|------------------------------------------------------| 130 | | emptyText | String | if it doesn't have any event, this text will display | 131 | | emptyTextColor | Color | The color of empty text | 132 | | emptyIcon | IconData | if it doesn't have any event, this icon will display | 133 | | emptyIconColor | Color | The color of empty icon | 134 | 135 | 136 | ### DayOptions : 137 | 138 | | Option | Type | Description | 139 | |------------------------------|--------------------------------|------------------------------------------------| 140 | | weekDaySelectedColor | Color | The color of the Selected weekday | 141 | | weekDayUnselectedColor | Color | The color of the UnSelected weekday | 142 | | showWeekDay | bool | Whether weekdays show or not | 143 | | compactMode | bool | Whether the Calendar card is compact or not | 144 | | selectedBackgroundColor | Color | The background color of the selected day | 145 | | unselectedBackgroundColor | Color | The background color of the unselected day | 146 | | selectedTextColor | Color | The text color of the selected day | 147 | | disabledTextColor | Color | The text color of the disabled day | 148 | | unselectedTextColor | Color | The text color of the unselected day | 149 | | eventCounterColor | Color | The background color of the event counter | 150 | | eventCounterViewType | DayEventCounterViewType | The view type of event counter | 151 | | eventCounterTextColor | Color | The text color of the event Counter | 152 | | disableFadeEffect | bool | Whether days before now has fade effect or not | 153 | | disableDaysBeforeNow | bool | Whether days before now Disabled or not | 154 | 155 | 156 | ### Event Structure 157 | 158 | 159 | | Option | Type | 160 | |----------------|--------------------------------| 161 | | child | Widget | 162 | | dateTime | CalendarDateTime | 163 | | onTap | Function | 164 | | onLongPress | Function | 165 | 166 | ## Locales : 167 | 168 | **Event Calendar** supports two types of calendar now . **Gregorian** , and **Jalali** . 169 | 170 | 171 | ## Contribute : 172 | You can help us and contribute for : 173 | - New options 174 | - More locales 175 | - Better exceptions 176 | --------------------------------------------------------------------------------