├── .github └── ISSUE_TEMPLATE.md ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── Example-Objc ├── AppDelegate.h ├── AppDelegate.m ├── Base.lproj │ └── Main.storyboard ├── ButtonsViewController.h ├── ButtonsViewController.m ├── CalendarConfigViewController.h ├── CalendarConfigViewController.m ├── DIYCalendarCell.h ├── DIYCalendarCell.m ├── DIYExampleViewController.h ├── DIYExampleViewController.m ├── DelegateAppearanceViewController.h ├── DelegateAppearanceViewController.m ├── FSCalendar.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ ├── xcbaselines │ │ └── 30671DC61D6D574C00BCFC4E.xcbaseline │ │ │ ├── 3003B86B-B981-4064-9C85-E799A3B13220.plist │ │ │ ├── 621090AF-4CF3-4245-99AD-46AD956ACA82.plist │ │ │ ├── A165CA85-3EFC-487B-954E-5AD1DC2EB21D.plist │ │ │ └── Info.plist │ │ └── xcschemes │ │ ├── FSCalendar.xcscheme │ │ └── FSCalendarExample.xcscheme ├── FSCalendarExampleUITests │ ├── FSCalendarExampleUITests.m │ └── Info.plist ├── FSCalendarScopeExampleViewController.h ├── FSCalendarScopeExampleViewController.m ├── FSCalendarTests │ ├── FSCalendarExtensionTest.m │ ├── FSCalendarTests.m │ └── Info.plist ├── FSTableViewController.h ├── FSTableViewController.m ├── FullScreenExampleViewController.h ├── FullScreenExampleViewController.m ├── HidePlaceholderViewController.h ├── HidePlaceholderViewController.m ├── Images.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── 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-57x57@1x.png │ │ ├── Icon-App-57x57@2x.png │ │ ├── Icon-App-60x60@2x.png │ │ ├── Icon-App-60x60@3x.png │ │ ├── Icon-App-76x76@1x.png │ │ ├── Icon-App-76x76@2x.png │ │ └── Icon-App-83.5x83.5@2x.png │ ├── Contents.json │ ├── LaunchImage.launchimage │ │ ├── Contents.json │ │ ├── LaunchImage-1024.png │ │ ├── LaunchImage-1334.png │ │ ├── LaunchImage-1536.png │ │ ├── LaunchImage-2048.png │ │ ├── LaunchImage-2208.png │ │ ├── LaunchImage-768.png │ │ ├── LaunchImage-960.png │ │ └── LaunchImage.png │ ├── circle.imageset │ │ ├── Contents.json │ │ └── circle@2x.png │ ├── fire.imageset │ │ └── Contents.json │ ├── icon_cat.imageset │ │ ├── Contents.json │ │ └── icon_cat@2x.png │ ├── icon_footprint.imageset │ │ ├── Contents.json │ │ └── icon_footprint@2x.png │ ├── icon_next.imageset │ │ ├── Contents.json │ │ ├── icon_next@2x.png │ │ └── icon_next@3x.png │ ├── icon_prev.imageset │ │ ├── Contents.json │ │ ├── icon_prev@2x.png │ │ └── icon_prev@3x.png │ └── icon_setting.imageset │ │ ├── Contents.json │ │ └── icon_setting@2x.png ├── Info.plist ├── LaunchScreen.xib ├── LoadViewExampleViewController.h ├── LoadViewExampleViewController.m ├── LunarFormatter.h ├── LunarFormatter.m ├── RangePickerCell.h ├── RangePickerCell.m ├── RangePickerViewController.h ├── RangePickerViewController.m ├── StoryboardExampleViewController.h ├── StoryboardExampleViewController.m └── main.m ├── Example-Swift ├── FSCalendarSwiftExample.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── FSCalendarSwiftExample │ ├── AppDelegate.swift │ ├── Base.lproj │ │ ├── LaunchScreen.xib │ │ └── Main.storyboard │ ├── CalendarConfigViewController.swift │ ├── DIYCalendarCell.swift │ ├── DIYExampleViewController.swift │ ├── DelegateAppearanceViewController.swift │ ├── FSCalendarScopeViewController.swift │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── 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-57x57@1x.png │ │ │ ├── Icon-App-57x57@2x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ └── Icon-App-83.5x83.5@2x.png │ │ ├── Contents.json │ │ ├── LaunchImage.launchimage │ │ │ ├── Contents.json │ │ │ ├── LaunchImage-1024.png │ │ │ ├── LaunchImage-1334.png │ │ │ ├── LaunchImage-1536.png │ │ │ ├── LaunchImage-2048.png │ │ │ ├── LaunchImage-2208.png │ │ │ ├── LaunchImage-768.png │ │ │ ├── LaunchImage-960.png │ │ │ └── LaunchImage.png │ │ ├── circle.imageset │ │ │ ├── Contents.json │ │ │ └── circle@2x.png │ │ ├── icon_cat.imageset │ │ │ ├── Contents.json │ │ │ └── icon_cat@2x.png │ │ └── icon_setting.imageset │ │ │ ├── Contents.json │ │ │ └── icon_setting@2x.png │ ├── Info.plist │ ├── InterfaceBuilderViewController.swift │ ├── LoadViewExampleViewController.swift │ ├── LunarFormatter.swift │ ├── Objc-Bridge-Header.h │ └── TableViewController.swift └── FSCalendarSwiftExampleUITests │ ├── FSCalendarSwiftExampleUITests.swift │ ├── Info.plist │ └── Objc-Bridge-Header.h ├── Example-TodayExtension ├── Example-TodayExtension.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── TodayExtension │ ├── Base.lproj │ │ └── MainInterface.storyboard │ ├── Image.xcassets │ │ ├── Contents.json │ │ ├── circle_next.imageset │ │ │ ├── Contents.json │ │ │ └── circle_next.png │ │ └── circle_prev.imageset │ │ │ ├── Contents.json │ │ │ └── circle_prev.png │ ├── Info.plist │ ├── TodayViewController.h │ └── TodayViewController.m └── TodayExtensionExample │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── 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-57x57@1x.png │ │ ├── Icon-App-57x57@2x.png │ │ ├── Icon-App-60x60@2x.png │ │ ├── Icon-App-60x60@3x.png │ │ ├── Icon-App-76x76@1x.png │ │ ├── Icon-App-76x76@2x.png │ │ └── Icon-App-83.5x83.5@2x.png │ └── Contents.json │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Info.plist │ ├── ViewController.h │ ├── ViewController.m │ └── main.m ├── Example-TodayExtension2 └── Example-TodayExtension.xcodeproj │ └── project.pbxproj ├── FSCalendar.podspec ├── FSCalendar ├── FSCalendar.h ├── FSCalendar.m ├── FSCalendarAppearance.h ├── FSCalendarAppearance.m ├── FSCalendarCalculator.h ├── FSCalendarCalculator.m ├── FSCalendarCell.h ├── FSCalendarCell.m ├── FSCalendarCollectionView.h ├── FSCalendarCollectionView.m ├── FSCalendarCollectionViewLayout.h ├── FSCalendarCollectionViewLayout.m ├── FSCalendarConstants.h ├── FSCalendarConstants.m ├── FSCalendarDelegationFactory.h ├── FSCalendarDelegationFactory.m ├── FSCalendarDelegationProxy.h ├── FSCalendarDelegationProxy.m ├── FSCalendarDynamicHeader.h ├── FSCalendarExtensions.h ├── FSCalendarExtensions.m ├── FSCalendarHeaderView.h ├── FSCalendarHeaderView.m ├── FSCalendarSeparatorDecorationView.h ├── FSCalendarSeparatorDecorationView.m ├── FSCalendarStickyHeader.h ├── FSCalendarStickyHeader.m ├── FSCalendarTransitionCoordinator.h ├── FSCalendarTransitionCoordinator.m ├── FSCalendarWeekdayView.h ├── FSCalendarWeekdayView.m ├── Info.plist └── include │ ├── FSCalendar.h │ ├── FSCalendarAppearance.h │ ├── FSCalendarCalculator.h │ ├── FSCalendarCell.h │ ├── FSCalendarCollectionView.h │ ├── FSCalendarCollectionViewLayout.h │ ├── FSCalendarConstants.h │ ├── FSCalendarDelegationFactory.h │ ├── FSCalendarDelegationProxy.h │ ├── FSCalendarDynamicHeader.h │ ├── FSCalendarExtensions.h │ ├── FSCalendarHeaderView.h │ ├── FSCalendarSeparatorDecorationView.h │ ├── FSCalendarStickyHeader.h │ ├── FSCalendarTransitionCoordinator.h │ ├── FSCalendarWeekdayView.h │ └── module.modulemap ├── FSCalendarExamples.xcworkspace ├── contents.xcworkspacedata └── xcshareddata │ └── IDEWorkspaceChecks.plist ├── LICENSE ├── MOREUSAGE.md ├── Package.swift └── README.md /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | ## The following informations are requested in a bug report 3 | * A brief bug description. 4 | * Stack trace. 5 | * Integration method.`(manually/cocoapods/carthage)` 6 | * Full steps to reproduce. 7 | * Device modal and iOS version. `e.g. iPhone 6s iOS9.1` 8 | * Xcode version. `e.g. Xcode 8.1` 9 | * FSCalendar version. `e.g. FSCalenda 2.5.1` 10 | * Does this happen in the demo project? Which one? Or a link to another demo project. 11 | 12 | 13 | ## 如果在使用过程中遇到问题,请提供以下信息以便于尽快将问题修复 14 | * 简单描述一下问题。 15 | * 控制台输出的堆栈跟踪(如果有的话)。 16 | * 安装方式. `如手动安装、cocoapods安装、或者通过carthage安装`。 17 | * 能够重现此问题的完整步骤。 18 | * 设备型号及版本。 `例如: iPhone6s iOS9.1` 19 | * 使用的Xcode版本。 `例如: Xcode8.1` 20 | * FSCalendar版本. `例如: FSCalendar 2.5.1` 21 | * 是否能在demo中重现,以及在哪个demo中重现?或者附加一个重现问题的demo链接。 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store 3 | 4 | # Xcode 5 | build/ 6 | *.pbxuser 7 | !default.pbxuser 8 | *.mode1v3 9 | !default.mode1v3 10 | *.mode2v3 11 | !default.mode2v3 12 | *.perspectivev3 13 | !default.perspectivev3 14 | xcuserdata 15 | *.xccheckout 16 | profile 17 | *.moved-aside 18 | DerivedData 19 | *.hmap 20 | *.ipa 21 | *.idea 22 | .swiftpm/ 23 | 24 | # Bundler 25 | .bundle 26 | 27 | Pods/ 28 | Carthage/Checkouts 29 | Carthage/Build 30 | 31 | fastlane/report.xml 32 | fastlane/screenshots 33 | 34 | Index/ 35 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | osx_image: xcode9 3 | 4 | script: 5 | 6 | - xcodebuild -project Example-Objc/FSCalendar.xcodeproj -sdk iphonesimulator -alltargets 7 | - xcodebuild -project Example-Swift/FSCalendarSwiftExample.xcodeproj -sdk iphonesimulator -alltargets 8 | - xcodebuild -project Example-TodayExtension/Example-TodayExtension.xcodeproj -sdk iphonesimulator -alltargets 9 | -------------------------------------------------------------------------------- /Example-Objc/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // FSAppDelegate.h 3 | // FSCalendar 4 | // 5 | // Created by CocoaPods on 02/13/2015. 6 | // Copyright (c) 2014 =. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Example-Objc/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // FSAppDelegate.m 3 | // FSCalendar 4 | // 5 | // Created by CocoaPods on 02/13/2015. 6 | // Copyright (c) 2014 =. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @implementation AppDelegate 12 | 13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 14 | { 15 | // Override point for customization after application launch. 16 | return YES; 17 | } 18 | 19 | - (void)applicationWillResignActive:(UIApplication *)application 20 | { 21 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 22 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 23 | } 24 | 25 | - (void)applicationDidEnterBackground:(UIApplication *)application 26 | { 27 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 29 | } 30 | 31 | - (void)applicationWillEnterForeground:(UIApplication *)application 32 | { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | - (void)applicationDidBecomeActive:(UIApplication *)application 37 | { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application 42 | { 43 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /Example-Objc/ButtonsViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ButtonsViewController.h 3 | // FSCalendar 4 | // 5 | // Created by dingwenchao on 4/15/16. 6 | // Copyright © 2016 Wenchao Ding. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ButtonsViewController : UIViewController 12 | 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Example-Objc/ButtonsViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ButtonsViewController.m 3 | // FSCalendar 4 | // 5 | // Created by dingwenchao on 4/15/16. 6 | // Copyright © 2016 Wenchao Ding. All rights reserved. 7 | // 8 | 9 | #import "ButtonsViewController.h" 10 | #import "FSCalendar.h" 11 | 12 | @interface ButtonsViewController() 13 | 14 | @property (weak, nonatomic) FSCalendar *calendar; 15 | @property (weak, nonatomic) UIButton *previousButton; 16 | @property (weak, nonatomic) UIButton *nextButton; 17 | 18 | @property (strong, nonatomic) NSCalendar *gregorian; 19 | 20 | - (void)previousClicked:(id)sender; 21 | - (void)nextClicked:(id)sender; 22 | 23 | @end 24 | 25 | @implementation ButtonsViewController 26 | 27 | - (instancetype)init 28 | { 29 | self = [super init]; 30 | if (self) { 31 | self.title = @"FSCalendar"; 32 | self.gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]; 33 | } 34 | return self; 35 | } 36 | 37 | - (void)loadView 38 | { 39 | UIView *view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 40 | view.backgroundColor = [UIColor groupTableViewBackgroundColor]; 41 | self.view = view; 42 | 43 | // 450 for iPad and 300 for iPhone 44 | CGFloat height = [[UIDevice currentDevice].model hasPrefix:@"iPad"] ? 450 : 300; 45 | FSCalendar *calendar = [[FSCalendar alloc] initWithFrame:CGRectMake(0, 64, view.frame.size.width, height)]; 46 | calendar.dataSource = self; 47 | calendar.delegate = self; 48 | calendar.backgroundColor = [UIColor whiteColor]; 49 | calendar.appearance.headerMinimumDissolvedAlpha = 0; 50 | calendar.appearance.caseOptions = FSCalendarCaseOptionsHeaderUsesUpperCase; 51 | [self.view addSubview:calendar]; 52 | self.calendar = calendar; 53 | 54 | UIButton *previousButton = [UIButton buttonWithType:UIButtonTypeCustom]; 55 | previousButton.frame = CGRectMake(0, 64+5, 95, 34); 56 | previousButton.backgroundColor = [UIColor whiteColor]; 57 | previousButton.titleLabel.font = [UIFont systemFontOfSize:15]; 58 | [previousButton setImage:[UIImage imageNamed:@"icon_prev"] forState:UIControlStateNormal]; 59 | [previousButton addTarget:self action:@selector(previousClicked:) forControlEvents:UIControlEventTouchUpInside]; 60 | [self.view addSubview:previousButton]; 61 | self.previousButton = previousButton; 62 | 63 | UIButton *nextButton = [UIButton buttonWithType:UIButtonTypeCustom]; 64 | nextButton.frame = CGRectMake(CGRectGetWidth(self.view.frame)-95, 64+5, 95, 34); 65 | nextButton.backgroundColor = [UIColor whiteColor]; 66 | nextButton.titleLabel.font = [UIFont systemFontOfSize:15]; 67 | [nextButton setImage:[UIImage imageNamed:@"icon_next"] forState:UIControlStateNormal]; 68 | [nextButton addTarget:self action:@selector(nextClicked:) forControlEvents:UIControlEventTouchUpInside]; 69 | [self.view addSubview:nextButton]; 70 | self.nextButton = nextButton; 71 | 72 | } 73 | 74 | - (void)previousClicked:(id)sender 75 | { 76 | NSDate *currentMonth = self.calendar.currentPage; 77 | NSDate *previousMonth = [self.gregorian dateByAddingUnit:NSCalendarUnitMonth value:-1 toDate:currentMonth options:0]; 78 | [self.calendar setCurrentPage:previousMonth animated:YES]; 79 | } 80 | 81 | - (void)nextClicked:(id)sender 82 | { 83 | NSDate *currentMonth = self.calendar.currentPage; 84 | NSDate *nextMonth = [self.gregorian dateByAddingUnit:NSCalendarUnitMonth value:1 toDate:currentMonth options:0]; 85 | [self.calendar setCurrentPage:nextMonth animated:YES]; 86 | } 87 | 88 | 89 | @end 90 | -------------------------------------------------------------------------------- /Example-Objc/CalendarConfigViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // CalendarConfigViewController.h 3 | // FSCalendar 4 | // 5 | // Created by Wenchao Ding on 2/15/15. 6 | // Copyright (c) 2015 Wenchao Ding. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "FSCalendar.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface CalendarConfigViewController : UITableViewController 15 | 16 | @property (assign, nonatomic) NSInteger theme; 17 | @property (assign, nonatomic) BOOL lunar; 18 | @property (assign, nonatomic) NSUInteger firstWeekday; 19 | @property (assign, nonatomic) FSCalendarScrollDirection scrollDirection; 20 | @property (strong, nonatomic) NSDate *selectedDate; 21 | 22 | @end 23 | 24 | NS_ASSUME_NONNULL_END 25 | -------------------------------------------------------------------------------- /Example-Objc/CalendarConfigViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // CalendarConfigViewController.m 3 | // FSCalendar 4 | // 5 | // Created by Wenchao Ding on 2/15/15. 6 | // Copyright (c) 2015 Wenchao Ding. All rights reserved. 7 | // 8 | 9 | #import "CalendarConfigViewController.h" 10 | #import "FScalendar.h" 11 | 12 | @interface CalendarConfigViewController () 13 | 14 | @property (weak, nonatomic) IBOutlet UIDatePicker *datePicker; 15 | 16 | @end 17 | 18 | @implementation CalendarConfigViewController 19 | 20 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 21 | { 22 | UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath]; 23 | switch (indexPath.section) { 24 | case 0: { 25 | cell.accessoryType = self.theme == indexPath.row ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone; 26 | break; 27 | } 28 | case 1: { 29 | cell.accessoryType = self.lunar ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone; 30 | break; 31 | } 32 | case 2: { 33 | cell.accessoryType = indexPath.row == 1 - self.scrollDirection ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone; 34 | break; 35 | } 36 | case 4: { 37 | cell.accessoryType = indexPath.row == self.firstWeekday - 1 ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone; 38 | break; 39 | } 40 | default: 41 | break; 42 | } 43 | return cell; 44 | } 45 | 46 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 47 | { 48 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 49 | switch (indexPath.section) { 50 | case 0: { 51 | self.theme = indexPath.row; 52 | break; 53 | } 54 | case 1: { 55 | self.lunar = !self.lunar; 56 | break; 57 | } 58 | case 2: { 59 | self.scrollDirection = (FSCalendarScrollDirection)(1-indexPath.row); 60 | break; 61 | } 62 | case 3: { 63 | self.selectedDate = self.datePicker.date; 64 | break; 65 | } 66 | case 4: { 67 | self.firstWeekday = indexPath.row + 1; 68 | break; 69 | } 70 | default: 71 | break; 72 | } 73 | [tableView reloadSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationAutomatic]; 74 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.05 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 75 | [self performSegueWithIdentifier:@"unwind2StoryboardExample" sender:self]; 76 | }); 77 | } 78 | 79 | @end 80 | -------------------------------------------------------------------------------- /Example-Objc/DIYCalendarCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // DIYCalendarCell.h 3 | // FSCalendar 4 | // 5 | // Created by dingwenchao on 02/11/2016. 6 | // Copyright © 2016 Wenchao Ding. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM(NSUInteger, SelectionType) { 12 | SelectionTypeNone, 13 | SelectionTypeSingle, 14 | SelectionTypeLeftBorder, 15 | SelectionTypeMiddle, 16 | SelectionTypeRightBorder 17 | }; 18 | 19 | 20 | @interface DIYCalendarCell : FSCalendarCell 21 | 22 | @property (weak, nonatomic) UIImageView *circleImageView; 23 | 24 | @property (weak, nonatomic) CAShapeLayer *selectionLayer; 25 | 26 | @property (assign, nonatomic) SelectionType selectionType; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /Example-Objc/DIYCalendarCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // DIYCalendarCell.m 3 | // FSCalendar 4 | // 5 | // Created by dingwenchao on 02/11/2016. 6 | // Copyright © 2016 Wenchao Ding. All rights reserved. 7 | // 8 | 9 | #import "DIYCalendarCell.h" 10 | #import "FSCalendarExtensions.h" 11 | 12 | @implementation DIYCalendarCell 13 | 14 | - (instancetype)initWithFrame:(CGRect)frame 15 | { 16 | self = [super initWithFrame:frame]; 17 | if (self) { 18 | UIImageView *circleImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"circle"]]; 19 | [self.contentView insertSubview:circleImageView atIndex:0]; 20 | self.circleImageView = circleImageView; 21 | 22 | CAShapeLayer *selectionLayer = [[CAShapeLayer alloc] init]; 23 | selectionLayer.fillColor = [UIColor blackColor].CGColor; 24 | selectionLayer.actions = @{@"hidden":[NSNull null]}; 25 | [self.contentView.layer insertSublayer:selectionLayer below:self.titleLabel.layer]; 26 | self.selectionLayer = selectionLayer; 27 | 28 | self.shapeLayer.hidden = YES; 29 | self.backgroundView = [[UIView alloc] initWithFrame:self.bounds]; 30 | self.backgroundView.backgroundColor = [[UIColor lightGrayColor] colorWithAlphaComponent:0.1]; 31 | 32 | } 33 | return self; 34 | } 35 | 36 | 37 | - (void)layoutSubviews 38 | { 39 | [super layoutSubviews]; 40 | 41 | self.backgroundView.frame = CGRectInset(self.bounds, 1, 1); 42 | self.circleImageView.frame = self.backgroundView.frame; 43 | self.selectionLayer.frame = self.bounds; 44 | 45 | if (self.selectionType == SelectionTypeMiddle) { 46 | 47 | self.selectionLayer.path = [UIBezierPath bezierPathWithRect:self.selectionLayer.bounds].CGPath; 48 | 49 | } else if (self.selectionType == SelectionTypeLeftBorder) { 50 | 51 | self.selectionLayer.path = [UIBezierPath bezierPathWithRoundedRect:self.selectionLayer.bounds byRoundingCorners:UIRectCornerTopLeft|UIRectCornerBottomLeft cornerRadii:CGSizeMake(self.selectionLayer.fs_width/2, self.selectionLayer.fs_width/2)].CGPath; 52 | 53 | } else if (self.selectionType == SelectionTypeRightBorder) { 54 | 55 | self.selectionLayer.path = [UIBezierPath bezierPathWithRoundedRect:self.selectionLayer.bounds byRoundingCorners:UIRectCornerTopRight|UIRectCornerBottomRight cornerRadii:CGSizeMake(self.selectionLayer.fs_width/2, self.selectionLayer.fs_width/2)].CGPath; 56 | 57 | } else if (self.selectionType == SelectionTypeSingle) { 58 | 59 | CGFloat diameter = MIN(self.selectionLayer.fs_height, self.selectionLayer.fs_width); 60 | self.selectionLayer.path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(self.contentView.fs_width/2-diameter/2, self.contentView.fs_height/2-diameter/2, diameter, diameter)].CGPath; 61 | 62 | } 63 | } 64 | 65 | - (void)configureAppearance 66 | { 67 | [super configureAppearance]; 68 | // Override the build-in appearance configuration 69 | if (self.isPlaceholder) { 70 | self.titleLabel.textColor = [UIColor lightGrayColor]; 71 | self.eventIndicator.hidden = YES; 72 | } 73 | } 74 | 75 | - (void)setSelectionType:(SelectionType)selectionType 76 | { 77 | if (_selectionType != selectionType) { 78 | _selectionType = selectionType; 79 | [self setNeedsLayout]; 80 | } 81 | } 82 | 83 | @end 84 | -------------------------------------------------------------------------------- /Example-Objc/DIYExampleViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DIYExampleViewController.h 3 | // FSCalendar 4 | // 5 | // Created by dingwenchao on 5/8/16. 6 | // Copyright © 2016 Wenchao Ding. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DIYExampleViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Example-Objc/DelegateAppearanceViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RollViewController.h 3 | // FSCalendar 4 | // 5 | // Created by dingwenchao on 10/16/15. 6 | // Copyright (c) 2015 Wenchao Ding. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "FSCalendar.h" 11 | 12 | @interface DelegateAppearanceViewController : UIViewController 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Example-Objc/FSCalendar.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example-Objc/FSCalendar.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example-Objc/FSCalendar.xcodeproj/xcshareddata/xcbaselines/30671DC61D6D574C00BCFC4E.xcbaseline/3003B86B-B981-4064-9C85-E799A3B13220.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | classNames 6 | 7 | FSCalendarTests 8 | 9 | testDateForIndexPathPerformance 10 | 11 | com.apple.XCTPerformanceMetric_WallClockTime 12 | 13 | baselineAverage 14 | 0.001 15 | baselineIntegrationDisplayName 16 | Local Baseline 17 | 18 | 19 | testIndexPathForDatePerformance 20 | 21 | com.apple.XCTPerformanceMetric_WallClockTime 22 | 23 | baselineAverage 24 | 0.001 25 | baselineIntegrationDisplayName 26 | Local Baseline 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Example-Objc/FSCalendar.xcodeproj/xcshareddata/xcbaselines/30671DC61D6D574C00BCFC4E.xcbaseline/621090AF-4CF3-4245-99AD-46AD956ACA82.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | classNames 6 | 7 | FSCalendarTests 8 | 9 | testIndexPathForDatePerformance 10 | 11 | com.apple.XCTPerformanceMetric_WallClockTime 12 | 13 | baselineAverage 14 | 0 15 | baselineIntegrationDisplayName 16 | Local Baseline 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Example-Objc/FSCalendar.xcodeproj/xcshareddata/xcbaselines/30671DC61D6D574C00BCFC4E.xcbaseline/A165CA85-3EFC-487B-954E-5AD1DC2EB21D.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | classNames 6 | 7 | FSCalendarTests 8 | 9 | testIndexPathForDatePerformance 10 | 11 | com.apple.XCTPerformanceMetric_WallClockTime 12 | 13 | baselineAverage 14 | 0 15 | baselineIntegrationDisplayName 16 | Local Baseline 17 | 18 | 19 | testNSCacheReading 20 | 21 | com.apple.XCTPerformanceMetric_WallClockTime 22 | 23 | baselineAverage 24 | 1.1193e-06 25 | baselineIntegrationDisplayName 26 | Local Baseline 27 | 28 | 29 | testPerformanceExample 30 | 31 | com.apple.XCTPerformanceMetric_WallClockTime 32 | 33 | baselineAverage 34 | 8.0435e-05 35 | baselineIntegrationDisplayName 36 | Local Baseline 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /Example-Objc/FSCalendar.xcodeproj/xcshareddata/xcbaselines/30671DC61D6D574C00BCFC4E.xcbaseline/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | runDestinationsByUUID 6 | 7 | 3003B86B-B981-4064-9C85-E799A3B13220 8 | 9 | localComputer 10 | 11 | busSpeedInMHz 12 | 100 13 | cpuCount 14 | 1 15 | cpuKind 16 | Intel Core i5 17 | cpuSpeedInMHz 18 | 2900 19 | logicalCPUCoresPerPackage 20 | 4 21 | modelCode 22 | MacBookPro12,1 23 | physicalCPUCoresPerPackage 24 | 2 25 | platformIdentifier 26 | com.apple.platform.macosx 27 | 28 | targetArchitecture 29 | x86_64 30 | targetDevice 31 | 32 | modelCode 33 | iPhone7,2 34 | platformIdentifier 35 | com.apple.platform.iphonesimulator 36 | 37 | 38 | 621090AF-4CF3-4245-99AD-46AD956ACA82 39 | 40 | targetArchitecture 41 | arm64 42 | targetDevice 43 | 44 | modelCode 45 | iPhone8,4 46 | platformIdentifier 47 | com.apple.platform.iphoneos 48 | 49 | 50 | A165CA85-3EFC-487B-954E-5AD1DC2EB21D 51 | 52 | localComputer 53 | 54 | busSpeedInMHz 55 | 100 56 | cpuCount 57 | 1 58 | cpuKind 59 | Intel Core i7 60 | cpuSpeedInMHz 61 | 2500 62 | logicalCPUCoresPerPackage 63 | 8 64 | modelCode 65 | MacBookPro11,5 66 | physicalCPUCoresPerPackage 67 | 4 68 | platformIdentifier 69 | com.apple.platform.macosx 70 | 71 | targetArchitecture 72 | x86_64 73 | targetDevice 74 | 75 | modelCode 76 | iPhone7,2 77 | platformIdentifier 78 | com.apple.platform.iphonesimulator 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /Example-Objc/FSCalendar.xcodeproj/xcshareddata/xcschemes/FSCalendar.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /Example-Objc/FSCalendar.xcodeproj/xcshareddata/xcschemes/FSCalendarExample.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 63 | 65 | 71 | 72 | 73 | 74 | 80 | 82 | 88 | 89 | 90 | 91 | 93 | 94 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /Example-Objc/FSCalendarExampleUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Example-Objc/FSCalendarScopeExampleViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // FSCalendarScopeExampleViewController.h 3 | // FSCalendar 4 | // 5 | // Created by Wenchao Ding on 8/29/15. 6 | // Copyright (c) 2015 Wenchao Ding. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "FSCalendar.h" 11 | 12 | @interface FSCalendarScopeExampleViewController : UIViewController 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /Example-Objc/FSCalendarTests/FSCalendarExtensionTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // FSExtensionTest.m 3 | // FSCalendar 4 | // 5 | // Created by dingwenchao on 9/13/16. 6 | // Copyright © 2016 Wenchao Ding. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "FSCalendarExtensions.h" 11 | 12 | @interface FSCalendarExtensionTest : XCTestCase 13 | 14 | @end 15 | 16 | @implementation FSCalendarExtensionTest 17 | 18 | - (void)setUp 19 | { 20 | [super setUp]; 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testNSObjectExtension 29 | { 30 | NSString *string = @"hello"; 31 | NSString *newString = [string fs_performSelector:@selector(stringByAppendingString:) withObjects:@" world.", nil]; 32 | XCTAssertEqualObjects(newString, @"hello world."); 33 | 34 | NSArray *array = @[@0]; 35 | NSArray *newArray = [array fs_performSelector:@selector(arrayByAddingObject:) withObjects:@1, nil]; 36 | XCTAssertEqualObjects(newArray, (@[@0,@1])); 37 | 38 | UITableView *t = [UITableView new]; 39 | NSValue *insets = [t fs_performSelector:@selector(contentInset) withObjects:nil, nil]; 40 | XCTAssertEqualObjects(insets, ([NSValue valueWithUIEdgeInsets:t.contentInset])); 41 | 42 | NSNumber *rowHeight = [t fs_performSelector:@selector(rowHeight) withObjects:nil, nil]; 43 | XCTAssertEqualObjects(rowHeight, @(t.rowHeight)); 44 | 45 | UIColor *color = [UIColor alloc]; 46 | UIColor *color1 = [color initWithRed:1 green:1 blue:1 alpha:1]; 47 | UIColor *color2 = [color fs_performSelector:@selector(initWithRed:green:blue:alpha:) withObjects:@1,@1,@1,@1,nil]; 48 | XCTAssertEqualObjects(color1, color2); 49 | 50 | NSValue *value1 = [NSValue valueWithCGSize:CGSizeMake(10, 10)]; 51 | NSValue *value2 = [NSValue fs_performSelector:@selector(valueWithCGSize:) withObjects:[NSValue valueWithCGSize:CGSizeMake(10, 10)],nil]; 52 | XCTAssertEqualObjects(value1, value2); 53 | 54 | } 55 | 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /Example-Objc/FSCalendarTests/FSCalendarTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // FSCalendarTests.m 3 | // FSCalendarTests 4 | // 5 | // Created by dingwenchao on 8/24/16. 6 | // Copyright © 2016 Wenchao Ding. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "FSCalendar.h" 11 | #import "FSCalendarDynamicHeader.h" 12 | #import "FSCalendarExtensions.h" 13 | 14 | @interface FSCalendarTests : XCTestCase 15 | 16 | @property (strong, nonatomic) FSCalendar *calendar; 17 | @property (strong, nonatomic) NSDate *date; 18 | @property (strong, nonatomic) NSIndexPath *indexPath; 19 | @property (strong, nonatomic) NSMutableArray *indexPaths; 20 | @property (strong, nonatomic) NSDateFormatter *formatter; 21 | 22 | @end 23 | 24 | @implementation FSCalendarTests 25 | 26 | - (void)setUp 27 | { 28 | [super setUp]; 29 | self.calendar = [[FSCalendar alloc] initWithFrame:CGRectMake(0, 0, 320, 300)]; 30 | [self.calendar.calculator reloadSections]; 31 | self.indexPath = [NSIndexPath indexPathForItem:25 inSection:0]; 32 | 33 | self.indexPaths = [NSMutableArray array]; 34 | for (int i = 0; i < 42; i++) { 35 | [self.indexPaths addObject:[NSIndexPath indexPathForItem:i inSection:0]]; 36 | } 37 | self.formatter = [[NSDateFormatter alloc] init]; 38 | self.formatter.dateFormat = @"yyyy-MM-dd"; 39 | self.date = [self.formatter dateFromString:@"1900-11-11"]; 40 | 41 | } 42 | 43 | - (NSDate *)minimumDateForCalendar:(FSCalendar *)calendar 44 | { 45 | return [self.formatter dateFromString:@"1900-01-01"]; 46 | } 47 | 48 | - (NSDate *)maximumDateForCalendar:(FSCalendar *)calendar 49 | { 50 | return [self.formatter dateFromString:@"2300-01-01"]; 51 | } 52 | 53 | - (void)tearDown 54 | { 55 | [super tearDown]; 56 | self.calendar = nil; 57 | self.indexPath = nil; 58 | self.date = nil; 59 | } 60 | 61 | - (void)testOutOfBoundsException 62 | { 63 | XCTAssertThrows([self.calendar selectDate:[self.formatter dateFromString:@"1900-01-01"]]); 64 | XCTAssertThrows([self.calendar selectDate:[self.formatter dateFromString:@"2300-01-01"]]); 65 | } 66 | 67 | - (void)testIndexPathForDatePerformance { 68 | [self measureBlock:^{ 69 | [self.calendar.calculator indexPathForDate:self.date scope:FSCalendarScopeMonth]; 70 | }]; 71 | } 72 | 73 | - (void)testDateForIndexPathPerformance { 74 | [self measureBlock:^{ 75 | [self.indexPaths enumerateObjectsUsingBlock:^(NSIndexPath * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 76 | [self.calendar.calculator dateForIndexPath:obj]; 77 | }]; 78 | }]; 79 | } 80 | 81 | @end 82 | -------------------------------------------------------------------------------- /Example-Objc/FSCalendarTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Example-Objc/FSTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // FSTableViewController.h 3 | // FSCalendar 4 | // 5 | // Created by DingWenchao on 6/25/15. 6 | // Copyright (c) 2015 =. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface FSTableViewController : UITableViewController 12 | 13 | @property (strong, nonatomic) NSArray *viewControllers; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Example-Objc/FSTableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // FSTableViewController.m 3 | // FSCalendar 4 | // 5 | // Created by DingWenchao on 6/25/15. 6 | // Copyright (c) 2015 =. All rights reserved. 7 | // 8 | 9 | #import "FSTableViewController.h" 10 | #import "LoadViewExampleViewController.h" 11 | #import "FullScreenExampleViewController.h" 12 | #import "DelegateAppearanceViewController.h" 13 | #import "HidePlaceholderViewController.h" 14 | #import "ButtonsViewController.h" 15 | #import "DIYExampleViewController.h" 16 | #import "RangePickerViewController.h" 17 | 18 | @implementation FSTableViewController 19 | 20 | - (void)viewDidLoad 21 | { 22 | [super viewDidLoad]; 23 | 24 | self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil]; 25 | 26 | self.viewControllers = @[ 27 | [RangePickerViewController class], 28 | [DIYExampleViewController class], 29 | [ButtonsViewController class], 30 | [HidePlaceholderViewController class], 31 | [DelegateAppearanceViewController class], 32 | [FullScreenExampleViewController class], 33 | [NSObject class], 34 | [NSObject class], 35 | [LoadViewExampleViewController class] 36 | ]; 37 | 38 | self.tableView.rowHeight = [[UIDevice currentDevice].model hasSuffix:@"iPad"] ? 60.0 : 44.0; 39 | } 40 | 41 | - (void)viewWillAppear:(BOOL)animated 42 | { 43 | [super viewWillAppear:animated]; 44 | if (self.tableView.indexPathForSelectedRow) { 45 | [self.tableView deselectRowAtIndexPath:self.tableView.indexPathForSelectedRow animated:animated]; 46 | } 47 | } 48 | 49 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 50 | { 51 | id viewControllerClass = self.viewControllers[indexPath.row]; 52 | if ([viewControllerClass isSubclassOfClass:[UIViewController class]]) { 53 | [self.navigationController pushViewController:[[viewControllerClass alloc] init] animated:YES]; 54 | } 55 | } 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /Example-Objc/FullScreenExampleViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // FullScreenExample.h 3 | // FSCalendar 4 | // 5 | // Created by Wenchao Ding on 9/16/15. 6 | // Copyright (c) 2015 Wenchao Ding. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface FullScreenExampleViewController : UIViewController 12 | 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Example-Objc/HidePlaceholderViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // HidePlaceholderViewController.h 3 | // FSCalendar 4 | // 5 | // Created by dingwenchao on 3/9/16. 6 | // Copyright © 2016 Wenchao Ding. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface HidePlaceholderViewController : UIViewController 12 | 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Example-Objc/HidePlaceholderViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // HidePlaceholderViewController.m 3 | // FSCalendar 4 | // 5 | // Created by dingwenchao on 3/9/16. 6 | // Copyright © 2016 Wenchao Ding. All rights reserved. 7 | // 8 | 9 | #import "HidePlaceholderViewController.h" 10 | #import "FSCalendar.h" 11 | 12 | #define kContainerFrame (CGRectMake(0, CGRectGetMaxY(calendar.frame), CGRectGetWidth(self.view.frame), 50)) 13 | 14 | NS_ASSUME_NONNULL_BEGIN 15 | 16 | @interface HidePlaceholderViewController() 17 | 18 | @property (weak, nonatomic) FSCalendar *calendar; 19 | 20 | @property (weak, nonatomic) UIView *bottomContainer; 21 | @property (weak, nonatomic) UILabel *eventLabel; 22 | @property (weak, nonatomic) UIButton *nextButton; 23 | @property (weak, nonatomic) UIButton *prevButton; 24 | 25 | @property (strong, nonatomic) NSCalendar *gregorian; 26 | @property (strong, nonatomic) NSDateFormatter *dateFormatter; 27 | 28 | - (void)nextClicked:(id)sender; 29 | - (void)prevClicked:(id)sender; 30 | 31 | @end 32 | 33 | NS_ASSUME_NONNULL_END 34 | 35 | @implementation HidePlaceholderViewController 36 | 37 | #pragma mark - Life cycle 38 | 39 | - (instancetype)init 40 | { 41 | self = [super init]; 42 | if (self) { 43 | self.title = @"FSCalendar"; 44 | self.dateFormatter = [[NSDateFormatter alloc] init]; 45 | self.dateFormatter.dateFormat = @"yyyy-MM-dd"; 46 | } 47 | return self; 48 | } 49 | 50 | - (void)loadView 51 | { 52 | UIView *view; 53 | UIButton *button; 54 | 55 | view = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds]; 56 | view.backgroundColor = [UIColor groupTableViewBackgroundColor]; 57 | self.view = view; 58 | 59 | // 400 for iPad and 300 for iPhone 60 | CGFloat height = [[UIDevice currentDevice].model hasPrefix:@"iPad"] ? 400 : 300; 61 | FSCalendar *calendar = [[FSCalendar alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(self.navigationController.navigationBar.frame), CGRectGetWidth(self.view.frame), height)]; 62 | calendar.backgroundColor = [UIColor whiteColor]; 63 | calendar.dataSource = self; 64 | calendar.delegate = self; 65 | calendar.placeholderType = FSCalendarPlaceholderTypeNone; 66 | calendar.adjustsBoundingRectWhenChangingMonths = YES; 67 | calendar.currentPage = [self.dateFormatter dateFromString:@"2020-06-01"]; 68 | calendar.firstWeekday = 2; 69 | calendar.scrollDirection = FSCalendarScrollDirectionVertical; 70 | [self.view addSubview:calendar]; 71 | self.calendar = calendar; 72 | 73 | view = [[UIView alloc] initWithFrame:kContainerFrame]; 74 | [self.view addSubview:view]; 75 | self.bottomContainer = view; 76 | 77 | UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(15, 0, 170, 50)]; 78 | label.font = [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline]; 79 | [self.bottomContainer addSubview:label]; 80 | self.eventLabel = label; 81 | 82 | button = [UIButton buttonWithType:UIButtonTypeSystem]; 83 | button.frame = CGRectMake(CGRectGetMaxX(self.eventLabel.frame)+5, 10, 60, 30); 84 | [button setTitle:@"PREV" forState:UIControlStateNormal]; 85 | [button addTarget:self action:@selector(prevClicked:) forControlEvents:UIControlEventTouchUpInside]; 86 | button.layer.borderWidth = 1; 87 | button.layer.borderColor = button.tintColor.CGColor; 88 | button.layer.cornerRadius = 6; 89 | [self.bottomContainer addSubview:button]; 90 | self.prevButton = button; 91 | 92 | button = [UIButton buttonWithType:UIButtonTypeSystem]; 93 | button.frame = CGRectMake(CGRectGetMaxX(self.prevButton.frame)+5, 10, 60, 30); 94 | [button setTitle:@"NEXT" forState:UIControlStateNormal]; 95 | [button addTarget:self action:@selector(nextClicked:) forControlEvents:UIControlEventTouchUpInside]; 96 | button.layer.borderWidth = 1; 97 | button.layer.borderColor = button.tintColor.CGColor; 98 | button.layer.cornerRadius = 6; 99 | [self.bottomContainer addSubview:button]; 100 | self.nextButton = button; 101 | 102 | } 103 | 104 | - (void)viewDidLoad 105 | { 106 | [super viewDidLoad]; 107 | 108 | NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:@""]; 109 | NSTextAttachment *attatchment = [[NSTextAttachment alloc] init]; 110 | attatchment.image = [UIImage imageNamed:@"icon_cat"]; 111 | attatchment.bounds = CGRectMake(0, -3, attatchment.image.size.width, attatchment.image.size.height); 112 | [attributedText appendAttributedString:[NSAttributedString attributedStringWithAttachment:attatchment]]; 113 | [attributedText appendAttributedString:[[NSAttributedString alloc] initWithString:@" Hey Daily Event "]]; 114 | [attributedText appendAttributedString:[NSAttributedString attributedStringWithAttachment:attatchment]]; 115 | self.eventLabel.attributedText = attributedText.copy; 116 | 117 | self.gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]; 118 | 119 | self.calendar.appearance.separators = FSCalendarSeparatorInterRows; 120 | self.calendar.swipeToChooseGesture.enabled = YES; 121 | 122 | // For UITest 123 | self.calendar.accessibilityIdentifier = @"calendar"; 124 | 125 | } 126 | 127 | - (NSDate *)minimumDateForCalendar:(FSCalendar *)calendar 128 | { 129 | return [self.dateFormatter dateFromString:@"2020-01-08"]; 130 | } 131 | 132 | - (NSDate *)maximumDateForCalendar:(FSCalendar *)calendar 133 | { 134 | return [self.dateFormatter dateFromString:@"2023-10-08"]; 135 | } 136 | 137 | - (void)dealloc 138 | { 139 | NSLog(@"%s",__FUNCTION__); 140 | } 141 | 142 | #pragma mark - 143 | 144 | - (void)calendar:(FSCalendar *)calendar boundingRectWillChange:(CGRect)bounds animated:(BOOL)animated 145 | { 146 | calendar.frame = (CGRect){calendar.frame.origin,bounds.size}; 147 | self.bottomContainer.frame = kContainerFrame; 148 | } 149 | 150 | #pragma mark - Target action 151 | 152 | - (void)nextClicked:(id)sender 153 | { 154 | NSDate *nextMonth = [self.gregorian dateByAddingUnit:NSCalendarUnitMonth value:1 toDate:self.calendar.currentPage options:0]; 155 | [self.calendar setCurrentPage:nextMonth animated:YES]; 156 | } 157 | 158 | - (void)prevClicked:(id)sender 159 | { 160 | NSDate *prevMonth = [self.gregorian dateByAddingUnit:NSCalendarUnitMonth value:-1 toDate:self.calendar.currentPage options:0]; 161 | [self.calendar setCurrentPage:prevMonth animated:YES]; 162 | } 163 | 164 | @end 165 | -------------------------------------------------------------------------------- /Example-Objc/Images.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" : "57x57", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-57x57@1x.png", 49 | "scale" : "1x" 50 | }, 51 | { 52 | "size" : "57x57", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-57x57@2x.png", 55 | "scale" : "2x" 56 | }, 57 | { 58 | "size" : "60x60", 59 | "idiom" : "iphone", 60 | "filename" : "Icon-App-60x60@2x.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "60x60", 65 | "idiom" : "iphone", 66 | "filename" : "Icon-App-60x60@3x.png", 67 | "scale" : "3x" 68 | }, 69 | { 70 | "size" : "20x20", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-20x20@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "20x20", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-20x20@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "29x29", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-29x29@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "29x29", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-29x29@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "40x40", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-40x40@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "40x40", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-40x40@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "76x76", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-76x76@1x.png", 109 | "scale" : "1x" 110 | }, 111 | { 112 | "size" : "76x76", 113 | "idiom" : "ipad", 114 | "filename" : "Icon-App-76x76@2x.png", 115 | "scale" : "2x" 116 | }, 117 | { 118 | "size" : "83.5x83.5", 119 | "idiom" : "ipad", 120 | "filename" : "Icon-App-83.5x83.5@2x.png", 121 | "scale" : "2x" 122 | }, 123 | { 124 | "idiom" : "ios-marketing", 125 | "size" : "1024x1024", 126 | "scale" : "1x" 127 | } 128 | ], 129 | "info" : { 130 | "version" : 1, 131 | "author" : "xcode" 132 | } 133 | } -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Objc/Images.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Objc/Images.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Objc/Images.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Objc/Images.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Objc/Images.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Objc/Images.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Objc/Images.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Objc/Images.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Objc/Images.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Objc/Images.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Objc/Images.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Objc/Images.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Objc/Images.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Objc/Images.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Objc/Images.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Objc/Images.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "extent" : "full-screen", 5 | "idiom" : "iphone", 6 | "subtype" : "736h", 7 | "filename" : "LaunchImage-2208.png", 8 | "minimum-system-version" : "8.0", 9 | "orientation" : "portrait", 10 | "scale" : "3x" 11 | }, 12 | { 13 | "extent" : "full-screen", 14 | "idiom" : "iphone", 15 | "subtype" : "667h", 16 | "filename" : "LaunchImage-1334.png", 17 | "minimum-system-version" : "8.0", 18 | "orientation" : "portrait", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "orientation" : "portrait", 23 | "idiom" : "iphone", 24 | "filename" : "LaunchImage-960.png", 25 | "extent" : "full-screen", 26 | "minimum-system-version" : "7.0", 27 | "scale" : "2x" 28 | }, 29 | { 30 | "extent" : "full-screen", 31 | "idiom" : "iphone", 32 | "subtype" : "retina4", 33 | "filename" : "LaunchImage.png", 34 | "minimum-system-version" : "7.0", 35 | "orientation" : "portrait", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "orientation" : "portrait", 40 | "idiom" : "ipad", 41 | "filename" : "LaunchImage-1024.png", 42 | "extent" : "full-screen", 43 | "minimum-system-version" : "7.0", 44 | "scale" : "1x" 45 | }, 46 | { 47 | "orientation" : "landscape", 48 | "idiom" : "ipad", 49 | "filename" : "LaunchImage-768.png", 50 | "extent" : "full-screen", 51 | "minimum-system-version" : "7.0", 52 | "scale" : "1x" 53 | }, 54 | { 55 | "orientation" : "portrait", 56 | "idiom" : "ipad", 57 | "filename" : "LaunchImage-2048.png", 58 | "extent" : "full-screen", 59 | "minimum-system-version" : "7.0", 60 | "scale" : "2x" 61 | }, 62 | { 63 | "orientation" : "landscape", 64 | "idiom" : "ipad", 65 | "filename" : "LaunchImage-1536.png", 66 | "extent" : "full-screen", 67 | "minimum-system-version" : "7.0", 68 | "scale" : "2x" 69 | } 70 | ], 71 | "info" : { 72 | "version" : 1, 73 | "author" : "xcode" 74 | } 75 | } -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/LaunchImage.launchimage/LaunchImage-1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Objc/Images.xcassets/LaunchImage.launchimage/LaunchImage-1024.png -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/LaunchImage.launchimage/LaunchImage-1334.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Objc/Images.xcassets/LaunchImage.launchimage/LaunchImage-1334.png -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/LaunchImage.launchimage/LaunchImage-1536.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Objc/Images.xcassets/LaunchImage.launchimage/LaunchImage-1536.png -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/LaunchImage.launchimage/LaunchImage-2048.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Objc/Images.xcassets/LaunchImage.launchimage/LaunchImage-2048.png -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/LaunchImage.launchimage/LaunchImage-2208.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Objc/Images.xcassets/LaunchImage.launchimage/LaunchImage-2208.png -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/LaunchImage.launchimage/LaunchImage-768.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Objc/Images.xcassets/LaunchImage.launchimage/LaunchImage-768.png -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/LaunchImage.launchimage/LaunchImage-960.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Objc/Images.xcassets/LaunchImage.launchimage/LaunchImage-960.png -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/LaunchImage.launchimage/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Objc/Images.xcassets/LaunchImage.launchimage/LaunchImage.png -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/circle.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "circle@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/circle.imageset/circle@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Objc/Images.xcassets/circle.imageset/circle@2x.png -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/fire.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "scale" : "3x" 14 | } 15 | ], 16 | "info" : { 17 | "version" : 1, 18 | "author" : "xcode" 19 | } 20 | } -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/icon_cat.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "icon_cat@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/icon_cat.imageset/icon_cat@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Objc/Images.xcassets/icon_cat.imageset/icon_cat@2x.png -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/icon_footprint.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "icon_footprint@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/icon_footprint.imageset/icon_footprint@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Objc/Images.xcassets/icon_footprint.imageset/icon_footprint@2x.png -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/icon_next.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "icon_next@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "icon_next@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/icon_next.imageset/icon_next@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Objc/Images.xcassets/icon_next.imageset/icon_next@2x.png -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/icon_next.imageset/icon_next@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Objc/Images.xcassets/icon_next.imageset/icon_next@3x.png -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/icon_prev.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "icon_prev@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "icon_prev@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/icon_prev.imageset/icon_prev@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Objc/Images.xcassets/icon_prev.imageset/icon_prev@2x.png -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/icon_prev.imageset/icon_prev@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Objc/Images.xcassets/icon_prev.imageset/icon_prev@3x.png -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/icon_setting.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "icon_setting@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example-Objc/Images.xcassets/icon_setting.imageset/icon_setting@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Objc/Images.xcassets/icon_setting.imageset/icon_setting@2x.png -------------------------------------------------------------------------------- /Example-Objc/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | NSCalendarsUsageDescription 26 | Events 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UIRequiresFullScreen 36 | 37 | UISupportedInterfaceOrientations 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationLandscapeLeft 41 | UIInterfaceOrientationLandscapeRight 42 | UIInterfaceOrientationPortraitUpsideDown 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /Example-Objc/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 25 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /Example-Objc/LoadViewExampleViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // LoadViewExampleViewController.h 3 | // FSCalendar 4 | // 5 | // Created by DingWenchao on 6/25/15. 6 | // Copyright (c) 2017 Wenchao Ding. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface LoadViewExampleViewController : UIViewController 12 | 13 | @end 14 | 15 | -------------------------------------------------------------------------------- /Example-Objc/LoadViewExampleViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // LoadViewExampleViewController.m 3 | // FSCalendar 4 | // 5 | // Created by DingWenchao on 6/25/15. 6 | // Copyright (c) 2016 Wenchao Ding. All rights reserved. 7 | // 8 | 9 | #import "LoadViewExampleViewController.h" 10 | #import "FSCalendar.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface LoadViewExampleViewController() 15 | 16 | @property (weak, nonatomic) FSCalendar *calendar; 17 | 18 | @property (strong, nonatomic) NSDateFormatter *dateFormatter; 19 | @property (strong, nonatomic) NSDictionary *images; 20 | 21 | @end 22 | 23 | NS_ASSUME_NONNULL_END 24 | 25 | @implementation LoadViewExampleViewController 26 | 27 | #pragma mark - Life cycle 28 | 29 | - (instancetype)init 30 | { 31 | self = [super init]; 32 | if (self) { 33 | self.title = @"FSCalendar"; 34 | self.images = @{@"2020/11/01":[UIImage imageNamed:@"icon_cat"], 35 | @"2020/11/05":[UIImage imageNamed:@"icon_footprint"], 36 | @"2020/11/20":[UIImage imageNamed:@"icon_cat"], 37 | @"2020/11/07":[UIImage imageNamed:@"icon_footprint"]}; 38 | } 39 | return self; 40 | } 41 | 42 | - (void)loadView 43 | { 44 | UIView *view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 45 | view.backgroundColor = [UIColor groupTableViewBackgroundColor]; 46 | self.view = view; 47 | 48 | // 450 for iPad and 300 for iPhone 49 | CGFloat height = [[UIDevice currentDevice].model hasPrefix:@"iPad"] ? 450 : 300; 50 | FSCalendar *calendar = [[FSCalendar alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(self.navigationController.navigationBar.frame), view.frame.size.width, height)]; 51 | calendar.dataSource = self; 52 | calendar.delegate = self; 53 | calendar.scrollDirection = FSCalendarScrollDirectionVertical; 54 | calendar.backgroundColor = [UIColor whiteColor]; 55 | 56 | [view addSubview:calendar]; 57 | self.calendar = calendar; 58 | 59 | } 60 | 61 | - (void)viewDidLoad 62 | { 63 | [super viewDidLoad]; 64 | self.dateFormatter = [[NSDateFormatter alloc] init]; 65 | self.dateFormatter.dateFormat = @"yyyy/MM/dd"; 66 | 67 | 68 | // [self.calendar selectDate:[self.dateFormatter dateFromString:@"2020/02/03"]]; 69 | 70 | /* 71 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 72 | [self.calendar setScope:FSCalendarScopeWeek animated:YES]; 73 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 74 | [self.calendar setScope:FSCalendarScopeMonth animated:YES]; 75 | }); 76 | }); 77 | */ 78 | 79 | 80 | } 81 | 82 | - (void)dealloc 83 | { 84 | NSLog(@"%s", __FUNCTION__); 85 | } 86 | 87 | #pragma mark - 88 | 89 | - (BOOL)calendar:(FSCalendar *)calendar shouldSelectDate:(NSDate *)date atMonthPosition:(FSCalendarMonthPosition)monthPosition 90 | { 91 | NSLog(@"should select date %@",[self.dateFormatter stringFromDate:date]); 92 | return YES; 93 | } 94 | 95 | - (void)calendar:(FSCalendar *)calendar didSelectDate:(NSDate *)date atMonthPosition:(FSCalendarMonthPosition)monthPosition 96 | { 97 | NSLog(@"did select date %@",[self.dateFormatter stringFromDate:date]); 98 | if (monthPosition == FSCalendarMonthPositionNext || monthPosition == FSCalendarMonthPositionPrevious) { 99 | [calendar setCurrentPage:date animated:YES]; 100 | } 101 | } 102 | 103 | - (void)calendarCurrentPageDidChange:(FSCalendar *)calendar 104 | { 105 | NSLog(@"did change to page %@",[self.dateFormatter stringFromDate:calendar.currentPage]); 106 | } 107 | 108 | - (void)calendar:(FSCalendar *)calendar boundingRectWillChange:(CGRect)bounds animated:(BOOL)animated 109 | { 110 | calendar.frame = (CGRect){calendar.frame.origin,bounds.size}; 111 | } 112 | 113 | #pragma mark - 114 | 115 | 116 | - (NSDate *)minimumDateForCalendar:(FSCalendar *)calendar 117 | { 118 | return [self.dateFormatter dateFromString:@"2020/10/01"]; 119 | } 120 | 121 | - (NSDate *)maximumDateForCalendar:(FSCalendar *)calendar 122 | { 123 | return [self.dateFormatter dateFromString:@"2023/10/10"]; 124 | } 125 | 126 | 127 | - (UIImage *)calendar:(FSCalendar *)calendar imageForDate:(NSDate *)date 128 | { 129 | NSString *dateString = [self.dateFormatter stringFromDate:date]; 130 | return self.images[dateString]; 131 | } 132 | 133 | @end 134 | -------------------------------------------------------------------------------- /Example-Objc/LunarFormatter.h: -------------------------------------------------------------------------------- 1 | // 2 | // LunarFormatter.h 3 | // FSCalendar 4 | // 5 | // Created by Wenchao Ding on 25/07/2017. 6 | // Copyright © 2017 wenchaoios. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface LunarFormatter : NSObject 14 | 15 | - (NSString *)stringFromDate:(NSDate *)date; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /Example-Objc/LunarFormatter.m: -------------------------------------------------------------------------------- 1 | // 2 | // LunarFormatter.m 3 | // FSCalendar 4 | // 5 | // Created by Wenchao Ding on 25/07/2017. 6 | // Copyright © 2017 wenchaoios. All rights reserved. 7 | // 8 | 9 | #import "LunarFormatter.h" 10 | 11 | @interface LunarFormatter () 12 | 13 | @property (strong, nonatomic) NSCalendar *chineseCalendar; 14 | @property (strong, nonatomic) NSDateFormatter *formatter; 15 | @property (strong, nonatomic) NSArray *lunarDays; 16 | @property (strong, nonatomic) NSArray *lunarMonths; 17 | 18 | @end 19 | 20 | @implementation LunarFormatter 21 | 22 | - (instancetype)init 23 | { 24 | self = [super init]; 25 | if (self) { 26 | self.chineseCalendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierChinese]; 27 | self.formatter = [[NSDateFormatter alloc] init]; 28 | self.formatter.calendar = self.chineseCalendar; 29 | self.formatter.dateFormat = @"M"; 30 | self.lunarDays = @[@"初二",@"初三",@"初四",@"初五",@"初六",@"初七",@"初八",@"初九",@"初十",@"十一",@"十二",@"十三",@"十四",@"十五",@"十六",@"十七",@"十八",@"十九",@"二十",@"二一",@"二二",@"二三",@"二四",@"二五",@"二六",@"二七",@"二八",@"二九",@"三十"]; 31 | self.lunarMonths = @[@"正月",@"二月",@"三月",@"四月",@"五月",@"六月",@"七月",@"八月",@"九月",@"十月",@"冬月",@"腊月"]; 32 | } 33 | return self; 34 | } 35 | 36 | - (NSString *)stringFromDate:(NSDate *)date 37 | { 38 | NSInteger day = [self.chineseCalendar component:NSCalendarUnitDay fromDate:date]; 39 | if (day != 1) { 40 | return self.lunarDays[day-2]; 41 | } 42 | // First day of month 43 | NSString *monthString = [self.formatter stringFromDate:date]; 44 | if ([self.chineseCalendar.veryShortMonthSymbols containsObject:monthString]) { 45 | return self.lunarMonths[monthString.integerValue-1]; 46 | } 47 | // Leap month 48 | NSInteger month = [self.chineseCalendar component:NSCalendarUnitMonth fromDate:date]; 49 | monthString = [NSString stringWithFormat:@"闰%@", self.lunarMonths[month-1]]; 50 | return monthString; 51 | } 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /Example-Objc/RangePickerCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // RangePickerCell.h 3 | // FSCalendar 4 | // 5 | // Created by dingwenchao on 02/11/2016. 6 | // Copyright © 2016 Wenchao Ding. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface RangePickerCell : FSCalendarCell 12 | 13 | // The start/end of the range 14 | @property (weak, nonatomic) CALayer *selectionLayer; 15 | 16 | // The middle of the range 17 | @property (weak, nonatomic) CALayer *middleLayer; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Example-Objc/RangePickerCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // RangePickerCell.m 3 | // FSCalendar 4 | // 5 | // Created by dingwenchao on 02/11/2016. 6 | // Copyright © 2016 Wenchao Ding. All rights reserved. 7 | // 8 | 9 | #import "RangePickerCell.h" 10 | #import "FSCalendarExtensions.h" 11 | 12 | @implementation RangePickerCell 13 | 14 | - (instancetype)initWithFrame:(CGRect)frame 15 | { 16 | self = [super initWithFrame:frame]; 17 | if (self) { 18 | 19 | CALayer *selectionLayer = [[CALayer alloc] init]; 20 | selectionLayer.backgroundColor = [UIColor orangeColor].CGColor; 21 | selectionLayer.actions = @{@"hidden":[NSNull null]}; // Remove hiding animation 22 | [self.contentView.layer insertSublayer:selectionLayer below:self.titleLabel.layer]; 23 | self.selectionLayer = selectionLayer; 24 | 25 | CALayer *middleLayer = [[CALayer alloc] init]; 26 | middleLayer.backgroundColor = [[UIColor orangeColor] colorWithAlphaComponent:0.3].CGColor; 27 | middleLayer.actions = @{@"hidden":[NSNull null]}; // Remove hiding animation 28 | [self.contentView.layer insertSublayer:middleLayer below:self.titleLabel.layer]; 29 | self.middleLayer = middleLayer; 30 | 31 | // Hide the default selection layer 32 | self.shapeLayer.hidden = YES; 33 | 34 | } 35 | return self; 36 | } 37 | 38 | - (void)layoutSubviews 39 | { 40 | [super layoutSubviews]; 41 | self.titleLabel.frame = self.contentView.bounds; 42 | } 43 | 44 | - (void)layoutSublayersOfLayer:(CALayer *)layer 45 | { 46 | [super layoutSublayersOfLayer:layer]; 47 | self.selectionLayer.frame = self.contentView.bounds; 48 | self.middleLayer.frame = self.contentView.bounds; 49 | } 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /Example-Objc/RangePickerViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RangePickerViewController.h 3 | // FSCalendar 4 | // 5 | // Created by dingwenchao on 5/8/16. 6 | // Copyright © 2016 Wenchao Ding. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface RangePickerViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Example-Objc/StoryboardExampleViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // FSViewController.h 3 | // Chinese-Lunar-Calendar 4 | // 5 | // Created by Wenchao Ding on 01/29/2015. 6 | // Copyright (c) 2017 Wenchao Ding. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "FSCalendar.h" 11 | 12 | @interface StoryboardExampleViewController : UIViewController 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Example-Objc/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // FSCalendar 4 | // 5 | // Created by Wenchao Ding on 8/23/15. 6 | // Copyright (c) 2015 Wenchao Ding. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // FSCalendarSwiftExample 4 | // 5 | // Created by Wenchao Ding on 9/3/15. 6 | // Copyright (c) 2015 wenchao. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 25 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/CalendarConfigViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CalendarConfigViewController.swift 3 | // FSCalendarSwiftExample 4 | // 5 | // Created by Wenchao Ding on 28/01/2017. 6 | // Copyright © 2017 wenchao. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class CalendarConfigViewController: UITableViewController { 12 | 13 | var theme: Int = 0 14 | var lunar: Bool = false 15 | var firstWeekday: UInt = 1 16 | var scrollDirection: FSCalendarScrollDirection = .horizontal 17 | var selectedDate: Date? 18 | 19 | @IBOutlet 20 | weak var datePicker: UIDatePicker! 21 | 22 | override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 23 | let cell = super.tableView(tableView, cellForRowAt: indexPath) 24 | switch indexPath.section { 25 | case 0: 26 | cell.accessoryType = self.theme == indexPath.row ? .checkmark : .none; 27 | case 1: 28 | cell.accessoryType = self.lunar ? .checkmark : .none; 29 | case 2: 30 | cell.accessoryType = indexPath.row == 1 - Int(self.scrollDirection.rawValue) ? .checkmark : .none; 31 | case 4: 32 | cell.accessoryType = indexPath.row == Int(self.firstWeekday-1) ? .checkmark : .none; 33 | default: 34 | break 35 | } 36 | return cell 37 | } 38 | 39 | override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 40 | tableView.deselectRow(at: indexPath, animated: true) 41 | switch indexPath.section { 42 | case 0: 43 | self.theme = indexPath.row 44 | case 1: 45 | self.lunar = !self.lunar 46 | case 2: 47 | self.scrollDirection = FSCalendarScrollDirection(rawValue: UInt(1-indexPath.row))! 48 | case 3: 49 | self.selectedDate = self.datePicker.date; 50 | case 4: 51 | self.firstWeekday = UInt(indexPath.row + 1) 52 | default: 53 | break 54 | } 55 | tableView.reloadSections([indexPath.section] as IndexSet, with: .none) 56 | DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+0.2) { 57 | self.performSegue(withIdentifier: "unwind2InterfaceBuilder", sender: self) 58 | } 59 | 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/DIYCalendarCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DIYCalendarCell.swift 3 | // FSCalendarSwiftExample 4 | // 5 | // Created by dingwenchao on 06/11/2016. 6 | // Copyright © 2016 wenchao. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | import UIKit 12 | 13 | enum SelectionType : Int { 14 | case none 15 | case single 16 | case leftBorder 17 | case middle 18 | case rightBorder 19 | } 20 | 21 | 22 | class DIYCalendarCell: FSCalendarCell { 23 | 24 | weak var circleImageView: UIImageView! 25 | weak var selectionLayer: CAShapeLayer! 26 | 27 | var selectionType: SelectionType = .none { 28 | didSet { 29 | setNeedsLayout() 30 | } 31 | } 32 | 33 | required init!(coder aDecoder: NSCoder!) { 34 | fatalError("init(coder:) has not been implemented") 35 | } 36 | 37 | override init(frame: CGRect) { 38 | super.init(frame: frame) 39 | 40 | let circleImageView = UIImageView(image: UIImage(named: "circle")!) 41 | self.contentView.insertSubview(circleImageView, at: 0) 42 | self.circleImageView = circleImageView 43 | 44 | let selectionLayer = CAShapeLayer() 45 | selectionLayer.fillColor = UIColor.black.cgColor 46 | selectionLayer.actions = ["hidden": NSNull()] 47 | self.contentView.layer.insertSublayer(selectionLayer, below: self.titleLabel!.layer) 48 | self.selectionLayer = selectionLayer 49 | 50 | self.shapeLayer.isHidden = true 51 | 52 | let view = UIView(frame: self.bounds) 53 | view.backgroundColor = UIColor.lightGray.withAlphaComponent(0.12) 54 | self.backgroundView = view; 55 | 56 | } 57 | 58 | override func layoutSubviews() { 59 | super.layoutSubviews() 60 | self.circleImageView.frame = self.contentView.bounds 61 | self.backgroundView?.frame = self.bounds.insetBy(dx: 1, dy: 1) 62 | self.selectionLayer.frame = self.contentView.bounds 63 | 64 | if selectionType == .middle { 65 | self.selectionLayer.path = UIBezierPath(rect: self.selectionLayer.bounds).cgPath 66 | } 67 | else if selectionType == .leftBorder { 68 | self.selectionLayer.path = UIBezierPath(roundedRect: self.selectionLayer.bounds, byRoundingCorners: [.topLeft, .bottomLeft], cornerRadii: CGSize(width: self.selectionLayer.frame.width / 2, height: self.selectionLayer.frame.width / 2)).cgPath 69 | } 70 | else if selectionType == .rightBorder { 71 | self.selectionLayer.path = UIBezierPath(roundedRect: self.selectionLayer.bounds, byRoundingCorners: [.topRight, .bottomRight], cornerRadii: CGSize(width: self.selectionLayer.frame.width / 2, height: self.selectionLayer.frame.width / 2)).cgPath 72 | } 73 | else if selectionType == .single { 74 | let diameter: CGFloat = min(self.selectionLayer.frame.height, self.selectionLayer.frame.width) 75 | self.selectionLayer.path = UIBezierPath(ovalIn: CGRect(x: self.contentView.frame.width / 2 - diameter / 2, y: self.contentView.frame.height / 2 - diameter / 2, width: diameter, height: diameter)).cgPath 76 | } 77 | } 78 | 79 | override func configureAppearance() { 80 | super.configureAppearance() 81 | // Override the build-in appearance configuration 82 | if self.isPlaceholder { 83 | self.eventIndicator.isHidden = true 84 | self.titleLabel.textColor = UIColor.lightGray 85 | } 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/DelegateAppearanceViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DelegateAppearanceViewController.swift 3 | // FSCalendarSwiftExample 4 | // 5 | // Created by dingwenchao on 30/12/2016. 6 | // Copyright © 2016 wenchao. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class DelegateAppearanceViewController: UIViewController, FSCalendarDataSource, FSCalendarDelegate, FSCalendarDelegateAppearance { 12 | 13 | fileprivate weak var calendar: FSCalendar! 14 | 15 | fileprivate let gregorian: Calendar = Calendar(identifier: .gregorian) 16 | fileprivate lazy var dateFormatter1: DateFormatter = { 17 | let formatter = DateFormatter() 18 | formatter.dateFormat = "yyyy/MM/dd" 19 | return formatter 20 | }() 21 | fileprivate lazy var dateFormatter2: DateFormatter = { 22 | let formatter = DateFormatter() 23 | formatter.dateFormat = "yyyy-MM-dd" 24 | return formatter 25 | }() 26 | 27 | let fillSelectionColors = ["2015/10/08": UIColor.green, "2015/10/06": UIColor.purple, "2015/10/17": UIColor.gray, "2015/10/21": UIColor.cyan, "2015/11/08": UIColor.green, "2015/11/06": UIColor.purple, "2015/11/17": UIColor.gray, "2015/11/21": UIColor.cyan, "2015/12/08": UIColor.green, "2015/12/06": UIColor.purple, "2015/12/17": UIColor.gray, "2015/12/21": UIColor.cyan] 28 | 29 | 30 | let fillDefaultColors = ["2015/10/08": UIColor.purple, "2015/10/06": UIColor.green, "2015/10/18": UIColor.cyan, "2015/10/22": UIColor.yellow, "2015/11/08": UIColor.purple, "2015/11/06": UIColor.green, "2015/11/18": UIColor.cyan, "2015/11/22": UIColor.yellow, "2015/12/08": UIColor.purple, "2015/12/06": UIColor.green, "2015/12/18": UIColor.cyan, "2015/12/22": UIColor.magenta] 31 | 32 | let borderDefaultColors = ["2015/10/08": UIColor.brown, "2015/10/17": UIColor.magenta, "2015/10/21": UIColor.cyan, "2015/10/25": UIColor.black, "2015/11/08": UIColor.brown, "2015/11/17": UIColor.magenta, "2015/11/21": UIColor.cyan, "2015/11/25": UIColor.black, "2015/12/08": UIColor.brown, "2015/12/17": UIColor.magenta, "2015/12/21": UIColor.purple, "2015/12/25": UIColor.black] 33 | 34 | let borderSelectionColors = ["2015/10/08": UIColor.red, "2015/10/17": UIColor.purple, "2015/10/21": UIColor.cyan, "2015/10/25": UIColor.magenta, "2015/11/08": UIColor.red, "2015/11/17": UIColor.purple, "2015/11/21": UIColor.cyan, "2015/11/25": UIColor.purple, "2015/12/08": UIColor.red, "2015/12/17": UIColor.purple, "2015/12/21": UIColor.cyan, "2015/12/25": UIColor.magenta] 35 | 36 | var datesWithEvent = ["2015-10-03", "2015-10-06", "2015-10-12", "2015-10-25"] 37 | var datesWithMultipleEvents = ["2015-10-08", "2015-10-16", "2015-10-20", "2015-10-28"] 38 | 39 | 40 | override func loadView() { 41 | let view = UIView(frame: UIScreen.main.bounds) 42 | view.backgroundColor = UIColor.groupTableViewBackground 43 | self.view = view 44 | 45 | let height: CGFloat = UIDevice.current.model.hasPrefix("iPad") ? 450 : 300 46 | let calendar = FSCalendar(frame: CGRect(x:0, y:64, width:self.view.bounds.size.width, height:height)) 47 | calendar.dataSource = self 48 | calendar.delegate = self 49 | calendar.allowsMultipleSelection = true 50 | calendar.swipeToChooseGesture.isEnabled = true 51 | calendar.backgroundColor = UIColor.white 52 | calendar.appearance.caseOptions = [.headerUsesUpperCase,.weekdayUsesSingleUpperCase] 53 | self.view.addSubview(calendar) 54 | self.calendar = calendar 55 | calendar.select(self.dateFormatter1.date(from: "2015/10/03")) 56 | let todayItem = UIBarButtonItem(title: "TODAY", style: .plain, target: self, action: #selector(self.todayItemClicked(sender:))) 57 | self.navigationItem.rightBarButtonItem = todayItem 58 | 59 | // For UITest 60 | self.calendar.accessibilityIdentifier = "calendar" 61 | } 62 | 63 | deinit { 64 | print("\(#function)") 65 | } 66 | 67 | @objc 68 | func todayItemClicked(sender: AnyObject) { 69 | self.calendar.setCurrentPage(Date(), animated: false) 70 | } 71 | 72 | func calendar(_ calendar: FSCalendar, numberOfEventsFor date: Date) -> Int { 73 | let dateString = self.dateFormatter2.string(from: date) 74 | if self.datesWithEvent.contains(dateString) { 75 | return 1 76 | } 77 | if self.datesWithMultipleEvents.contains(dateString) { 78 | return 3 79 | } 80 | return 0 81 | } 82 | 83 | func calendar(_ calendar: FSCalendar, appearance: FSCalendarAppearance, eventDefaultColorsFor date: Date) -> [UIColor]? { 84 | let key = self.dateFormatter2.string(from: date) 85 | if self.datesWithMultipleEvents.contains(key) { 86 | return [UIColor.magenta, appearance.eventDefaultColor, UIColor.black] 87 | } 88 | return nil 89 | } 90 | 91 | func calendar(_ calendar: FSCalendar, appearance: FSCalendarAppearance, fillSelectionColorFor date: Date) -> UIColor? { 92 | let key = self.dateFormatter1.string(from: date) 93 | if let color = self.fillSelectionColors[key] { 94 | return color 95 | } 96 | return appearance.selectionColor 97 | } 98 | 99 | func calendar(_ calendar: FSCalendar, appearance: FSCalendarAppearance, fillDefaultColorFor date: Date) -> UIColor? { 100 | let key = self.dateFormatter1.string(from: date) 101 | if let color = self.fillDefaultColors[key] { 102 | return color 103 | } 104 | return nil 105 | } 106 | 107 | func calendar(_ calendar: FSCalendar, appearance: FSCalendarAppearance, borderDefaultColorFor date: Date) -> UIColor? { 108 | let key = self.dateFormatter1.string(from: date) 109 | if let color = self.borderDefaultColors[key] { 110 | return color 111 | } 112 | return appearance.borderDefaultColor 113 | } 114 | 115 | func calendar(_ calendar: FSCalendar, appearance: FSCalendarAppearance, borderSelectionColorFor date: Date) -> UIColor? { 116 | let key = self.dateFormatter1.string(from: date) 117 | if let color = self.borderSelectionColors[key] { 118 | return color 119 | } 120 | return appearance.borderSelectionColor 121 | } 122 | 123 | func calendar(_ calendar: FSCalendar, appearance: FSCalendarAppearance, borderRadiusFor date: Date) -> CGFloat { 124 | if [8, 17, 21, 25].contains((self.gregorian.component(.day, from: date))) { 125 | return 0.0 126 | } 127 | return 1.0 128 | } 129 | 130 | } 131 | -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/FSCalendarScopeViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FSCalendarScopeViewController.swift 3 | // FSCalendarSwiftExample 4 | // 5 | // Created by dingwenchao on 30/12/2016. 6 | // Copyright © 2016 wenchao. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class FSCalendarScopeExampleViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, FSCalendarDataSource, FSCalendarDelegate, UIGestureRecognizerDelegate { 12 | 13 | @IBOutlet weak var tableView: UITableView! 14 | @IBOutlet weak var calendar: FSCalendar! 15 | @IBOutlet weak var animationSwitch: UISwitch! 16 | 17 | @IBOutlet weak var calendarHeightConstraint: NSLayoutConstraint! 18 | 19 | fileprivate lazy var dateFormatter: DateFormatter = { 20 | let formatter = DateFormatter() 21 | formatter.dateFormat = "yyyy/MM/dd" 22 | return formatter 23 | }() 24 | fileprivate lazy var scopeGesture: UIPanGestureRecognizer = { 25 | [unowned self] in 26 | let panGesture = UIPanGestureRecognizer(target: self.calendar, action: #selector(self.calendar.handleScopeGesture(_:))) 27 | panGesture.delegate = self 28 | panGesture.minimumNumberOfTouches = 1 29 | panGesture.maximumNumberOfTouches = 2 30 | return panGesture 31 | }() 32 | 33 | override func viewDidLoad() { 34 | super.viewDidLoad() 35 | 36 | if UIDevice.current.model.hasPrefix("iPad") { 37 | self.calendarHeightConstraint.constant = 400 38 | } 39 | 40 | self.calendar.select(Date()) 41 | 42 | self.view.addGestureRecognizer(self.scopeGesture) 43 | self.tableView.panGestureRecognizer.require(toFail: self.scopeGesture) 44 | self.calendar.scope = .week 45 | 46 | // For UITest 47 | self.calendar.accessibilityIdentifier = "calendar" 48 | 49 | } 50 | 51 | deinit { 52 | print("\(#function)") 53 | } 54 | 55 | // MARK:- UIGestureRecognizerDelegate 56 | 57 | func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { 58 | let shouldBegin = self.tableView.contentOffset.y <= -self.tableView.contentInset.top 59 | if shouldBegin { 60 | let velocity = self.scopeGesture.velocity(in: self.view) 61 | switch self.calendar.scope { 62 | case .month: 63 | return velocity.y < 0 64 | case .week: 65 | return velocity.y > 0 66 | } 67 | } 68 | return shouldBegin 69 | } 70 | 71 | func calendar(_ calendar: FSCalendar, boundingRectWillChange bounds: CGRect, animated: Bool) { 72 | self.calendarHeightConstraint.constant = bounds.height 73 | self.view.layoutIfNeeded() 74 | } 75 | 76 | func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition) { 77 | print("did select date \(self.dateFormatter.string(from: date))") 78 | let selectedDates = calendar.selectedDates.map({self.dateFormatter.string(from: $0)}) 79 | print("selected dates is \(selectedDates)") 80 | if monthPosition == .next || monthPosition == .previous { 81 | calendar.setCurrentPage(date, animated: true) 82 | } 83 | } 84 | 85 | func calendarCurrentPageDidChange(_ calendar: FSCalendar) { 86 | print("\(self.dateFormatter.string(from: calendar.currentPage))") 87 | } 88 | 89 | // MARK:- UITableViewDataSource 90 | 91 | func numberOfSections(in tableView: UITableView) -> Int { 92 | return 2 93 | } 94 | 95 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 96 | return [2,20][section] 97 | } 98 | 99 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 100 | if indexPath.section == 0 { 101 | let identifier = ["cell_month", "cell_week"][indexPath.row] 102 | let cell = tableView.dequeueReusableCell(withIdentifier: identifier)! 103 | return cell 104 | } else { 105 | let cell = tableView.dequeueReusableCell(withIdentifier: "cell")! 106 | return cell 107 | } 108 | } 109 | 110 | 111 | // MARK:- UITableViewDelegate 112 | 113 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 114 | tableView.deselectRow(at: indexPath, animated: true) 115 | if indexPath.section == 0 { 116 | let scope: FSCalendarScope = (indexPath.row == 0) ? .month : .week 117 | self.calendar.setScope(scope, animated: self.animationSwitch.isOn) 118 | } 119 | } 120 | 121 | func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { 122 | return 10 123 | } 124 | 125 | // MARK:- Target actions 126 | 127 | @IBAction func toggleClicked(sender: AnyObject) { 128 | if self.calendar.scope == .month { 129 | self.calendar.setScope(.week, animated: self.animationSwitch.isOn) 130 | } else { 131 | self.calendar.setScope(.month, animated: self.animationSwitch.isOn) 132 | } 133 | } 134 | 135 | } 136 | -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/Images.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" : "57x57", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-57x57@1x.png", 49 | "scale" : "1x" 50 | }, 51 | { 52 | "size" : "57x57", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-57x57@2x.png", 55 | "scale" : "2x" 56 | }, 57 | { 58 | "size" : "60x60", 59 | "idiom" : "iphone", 60 | "filename" : "Icon-App-60x60@2x.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "60x60", 65 | "idiom" : "iphone", 66 | "filename" : "Icon-App-60x60@3x.png", 67 | "scale" : "3x" 68 | }, 69 | { 70 | "size" : "20x20", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-20x20@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "20x20", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-20x20@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "29x29", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-29x29@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "29x29", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-29x29@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "40x40", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-40x40@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "40x40", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-40x40@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "76x76", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-76x76@1x.png", 109 | "scale" : "1x" 110 | }, 111 | { 112 | "size" : "76x76", 113 | "idiom" : "ipad", 114 | "filename" : "Icon-App-76x76@2x.png", 115 | "scale" : "2x" 116 | }, 117 | { 118 | "size" : "83.5x83.5", 119 | "idiom" : "ipad", 120 | "filename" : "Icon-App-83.5x83.5@2x.png", 121 | "scale" : "2x" 122 | }, 123 | { 124 | "idiom" : "ios-marketing", 125 | "size" : "1024x1024", 126 | "scale" : "1x" 127 | } 128 | ], 129 | "info" : { 130 | "version" : 1, 131 | "author" : "xcode" 132 | } 133 | } -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/Images.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Swift/FSCalendarSwiftExample/Images.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/Images.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Swift/FSCalendarSwiftExample/Images.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/Images.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Swift/FSCalendarSwiftExample/Images.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/Images.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Swift/FSCalendarSwiftExample/Images.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/Images.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Swift/FSCalendarSwiftExample/Images.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/Images.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Swift/FSCalendarSwiftExample/Images.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/Images.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Swift/FSCalendarSwiftExample/Images.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/Images.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Swift/FSCalendarSwiftExample/Images.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/Images.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Swift/FSCalendarSwiftExample/Images.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/Images.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Swift/FSCalendarSwiftExample/Images.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/Images.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Swift/FSCalendarSwiftExample/Images.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/Images.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Swift/FSCalendarSwiftExample/Images.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/Images.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Swift/FSCalendarSwiftExample/Images.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/Images.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Swift/FSCalendarSwiftExample/Images.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/Images.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Swift/FSCalendarSwiftExample/Images.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/Images.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Swift/FSCalendarSwiftExample/Images.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "extent" : "full-screen", 5 | "idiom" : "iphone", 6 | "subtype" : "736h", 7 | "filename" : "LaunchImage-2208.png", 8 | "minimum-system-version" : "8.0", 9 | "orientation" : "portrait", 10 | "scale" : "3x" 11 | }, 12 | { 13 | "extent" : "full-screen", 14 | "idiom" : "iphone", 15 | "subtype" : "667h", 16 | "filename" : "LaunchImage-1334.png", 17 | "minimum-system-version" : "8.0", 18 | "orientation" : "portrait", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "orientation" : "portrait", 23 | "idiom" : "iphone", 24 | "filename" : "LaunchImage-960.png", 25 | "extent" : "full-screen", 26 | "minimum-system-version" : "7.0", 27 | "scale" : "2x" 28 | }, 29 | { 30 | "extent" : "full-screen", 31 | "idiom" : "iphone", 32 | "subtype" : "retina4", 33 | "filename" : "LaunchImage.png", 34 | "minimum-system-version" : "7.0", 35 | "orientation" : "portrait", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "orientation" : "portrait", 40 | "idiom" : "ipad", 41 | "filename" : "LaunchImage-1024.png", 42 | "extent" : "full-screen", 43 | "minimum-system-version" : "7.0", 44 | "scale" : "1x" 45 | }, 46 | { 47 | "orientation" : "landscape", 48 | "idiom" : "ipad", 49 | "filename" : "LaunchImage-768.png", 50 | "extent" : "full-screen", 51 | "minimum-system-version" : "7.0", 52 | "scale" : "1x" 53 | }, 54 | { 55 | "orientation" : "portrait", 56 | "idiom" : "ipad", 57 | "filename" : "LaunchImage-2048.png", 58 | "extent" : "full-screen", 59 | "minimum-system-version" : "7.0", 60 | "scale" : "2x" 61 | }, 62 | { 63 | "orientation" : "landscape", 64 | "idiom" : "ipad", 65 | "filename" : "LaunchImage-1536.png", 66 | "extent" : "full-screen", 67 | "minimum-system-version" : "7.0", 68 | "scale" : "2x" 69 | } 70 | ], 71 | "info" : { 72 | "version" : 1, 73 | "author" : "xcode" 74 | } 75 | } -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/Images.xcassets/LaunchImage.launchimage/LaunchImage-1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Swift/FSCalendarSwiftExample/Images.xcassets/LaunchImage.launchimage/LaunchImage-1024.png -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/Images.xcassets/LaunchImage.launchimage/LaunchImage-1334.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Swift/FSCalendarSwiftExample/Images.xcassets/LaunchImage.launchimage/LaunchImage-1334.png -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/Images.xcassets/LaunchImage.launchimage/LaunchImage-1536.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Swift/FSCalendarSwiftExample/Images.xcassets/LaunchImage.launchimage/LaunchImage-1536.png -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/Images.xcassets/LaunchImage.launchimage/LaunchImage-2048.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Swift/FSCalendarSwiftExample/Images.xcassets/LaunchImage.launchimage/LaunchImage-2048.png -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/Images.xcassets/LaunchImage.launchimage/LaunchImage-2208.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Swift/FSCalendarSwiftExample/Images.xcassets/LaunchImage.launchimage/LaunchImage-2208.png -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/Images.xcassets/LaunchImage.launchimage/LaunchImage-768.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Swift/FSCalendarSwiftExample/Images.xcassets/LaunchImage.launchimage/LaunchImage-768.png -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/Images.xcassets/LaunchImage.launchimage/LaunchImage-960.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Swift/FSCalendarSwiftExample/Images.xcassets/LaunchImage.launchimage/LaunchImage-960.png -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/Images.xcassets/LaunchImage.launchimage/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Swift/FSCalendarSwiftExample/Images.xcassets/LaunchImage.launchimage/LaunchImage.png -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/Images.xcassets/circle.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "circle@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/Images.xcassets/circle.imageset/circle@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Swift/FSCalendarSwiftExample/Images.xcassets/circle.imageset/circle@2x.png -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/Images.xcassets/icon_cat.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "icon_cat@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/Images.xcassets/icon_cat.imageset/icon_cat@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Swift/FSCalendarSwiftExample/Images.xcassets/icon_cat.imageset/icon_cat@2x.png -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/Images.xcassets/icon_setting.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "icon_setting@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/Images.xcassets/icon_setting.imageset/icon_setting@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-Swift/FSCalendarSwiftExample/Images.xcassets/icon_setting.imageset/icon_setting@2x.png -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UIRequiresFullScreen 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationLandscapeRight 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/LoadViewExampleViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LoadViewExampleViewController.swift 3 | // FSCalendarSwiftExample 4 | // 5 | // Created by dingwenchao on 10/17/16. 6 | // Copyright © 2016 wenchao. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class LoadViewExampleViewController: UIViewController, FSCalendarDataSource, FSCalendarDelegate { 12 | 13 | private weak var calendar: FSCalendar! 14 | 15 | override func loadView() { 16 | 17 | let view = UIView(frame: UIScreen.main.bounds) 18 | view.backgroundColor = UIColor.groupTableViewBackground 19 | self.view = view 20 | 21 | let height: CGFloat = UIDevice.current.model.hasPrefix("iPad") ? 400 : 300 22 | let calendar = FSCalendar(frame: CGRect(x: 0, y: self.navigationController!.navigationBar.frame.maxY, width: self.view.bounds.width, height: height)) 23 | calendar.dataSource = self 24 | calendar.delegate = self 25 | calendar.backgroundColor = UIColor.white 26 | self.view.addSubview(calendar) 27 | self.calendar = calendar 28 | 29 | } 30 | 31 | override func viewDidLoad() { 32 | super.viewDidLoad() 33 | self.title = "FSCalendar" 34 | } 35 | 36 | func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition) { 37 | if monthPosition == .previous || monthPosition == .next { 38 | calendar.setCurrentPage(date, animated: true) 39 | } 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/LunarFormatter.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LunarFormatter.swift 3 | // FSCalendarSwiftExample 4 | // 5 | // Created by Wenchao Ding on 25/07/2017. 6 | // Copyright © 2017 wenchao. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | open class LunarFormatter: NSObject { 12 | 13 | fileprivate let chineseCalendar = Calendar(identifier: .chinese) 14 | fileprivate let formatter = DateFormatter() 15 | fileprivate let lunarDays = ["初二","初三","初四","初五","初六","初七","初八","初九","初十","十一","十二","十三","十四","十五","十六","十七","十八","十九","二十","二一","二二","二三","二四","二五","二六","二七","二八","二九","三十"] 16 | fileprivate let lunarMonths = ["正月","二月","三月","四月","五月","六月","七月","八月","九月","十月","冬月","腊月"] 17 | 18 | 19 | override init() { 20 | self.formatter.calendar = self.chineseCalendar 21 | self.formatter.dateFormat = "M" 22 | } 23 | 24 | open func string(from date: Date) -> String { 25 | let day = self.chineseCalendar.component(.day, from: date) 26 | if day != 1 { 27 | return self.lunarDays[day-2] 28 | } 29 | // First day of month 30 | let monthString = self.formatter.string(from: date) 31 | if self.chineseCalendar.veryShortMonthSymbols.contains(monthString) { 32 | if let month = Int(monthString) { 33 | return self.lunarMonths[month-1] 34 | } 35 | return "" 36 | } 37 | // Leap month 38 | let month = self.chineseCalendar.component(.month, from: date) 39 | return "闰" + self.lunarMonths[month-1] 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/Objc-Bridge-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Objc-Bridge-Header.h 3 | // FSCalendarSwiftExample 4 | // 5 | // Created by Wenchao Ding on 9/3/15. 6 | // Copyright (c) 2015 wenchao. All rights reserved. 7 | // 8 | 9 | #ifndef FSCalendarSwiftExample_Objc_Bridge_Header_h 10 | #define FSCalendarSwiftExample_Objc_Bridge_Header_h 11 | 12 | #import "FSCalendar.h" 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExample/TableViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TableViewController.swift 3 | // FSCalendarSwiftExample 4 | // 5 | // Created by dingwenchao on 10/17/16. 6 | // Copyright © 2016 wenchao. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class TableViewController: UITableViewController { 12 | 13 | override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 14 | let objects = [DIYExampleViewController.self, NSObject.self,DelegateAppearanceViewController.self, NSObject.self, LoadViewExampleViewController.self] 15 | if let ViewControllerClass = objects[indexPath.row] as? UIViewController.Type { 16 | self.navigationController?.pushViewController(ViewControllerClass.init(), animated: true) 17 | } 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExampleUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Example-Swift/FSCalendarSwiftExampleUITests/Objc-Bridge-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Objc-Bridge-Header.h 3 | // FSCalendarSwiftExampleUITests 4 | // 5 | // Created by Wenchao Ding on 29/01/2017. 6 | // Copyright © 2017 wenchao. All rights reserved. 7 | // 8 | 9 | 10 | #ifndef FSCalendarSwiftExampleUITests_Objc_Bridge_Header_h 11 | #define FSCalendarSwiftExampleUITests_Objc_Bridge_Header_h 12 | 13 | #import "FSCalendar.h" 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /Example-TodayExtension/Example-TodayExtension.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example-TodayExtension/TodayExtension/Image.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Example-TodayExtension/TodayExtension/Image.xcassets/circle_next.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "circle_next.png", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example-TodayExtension/TodayExtension/Image.xcassets/circle_next.imageset/circle_next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-TodayExtension/TodayExtension/Image.xcassets/circle_next.imageset/circle_next.png -------------------------------------------------------------------------------- /Example-TodayExtension/TodayExtension/Image.xcassets/circle_prev.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "circle_prev.png", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example-TodayExtension/TodayExtension/Image.xcassets/circle_prev.imageset/circle_prev.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-TodayExtension/TodayExtension/Image.xcassets/circle_prev.imageset/circle_prev.png -------------------------------------------------------------------------------- /Example-TodayExtension/TodayExtension/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | FSCalendar 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | XPC! 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | NSExtension 26 | 27 | NSExtensionMainStoryboard 28 | MainInterface 29 | NSExtensionPointIdentifier 30 | com.apple.widget-extension 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /Example-TodayExtension/TodayExtension/TodayViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TodayViewController.h 3 | // Example-TodayExtension 4 | // 5 | // Created by dingwenchao on 9/6/16. 6 | // Copyright © 2016 dingwenchao. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "FSCalendar.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface TodayViewController : UIViewController 15 | 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /Example-TodayExtension/TodayExtension/TodayViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TodayViewController.m 3 | // Example-TodayExtension 4 | // 5 | // Created by dingwenchao on 9/6/16. 6 | // Copyright © 2016 dingwenchao. All rights reserved. 7 | // 8 | 9 | #import "TodayViewController.h" 10 | #import 11 | #import "FSCalendar.h" 12 | 13 | @interface TodayViewController () 14 | 15 | @property (weak , nonatomic) IBOutlet FSCalendar *calendar; 16 | @property (weak , nonatomic) IBOutlet UIButton *prevButton; 17 | @property (weak , nonatomic) IBOutlet UIButton *nextButton; 18 | @property (weak , nonatomic) IBOutlet NSLayoutConstraint *calendarHeight; 19 | 20 | @property (strong, nonatomic) NSCalendar *gregorian; 21 | @property (strong, nonatomic) NSCalendar *lunarCalendar; 22 | @property (strong, nonatomic) NSArray *lunarChars; 23 | 24 | @end 25 | 26 | @implementation TodayViewController 27 | 28 | - (void)viewDidLoad 29 | { 30 | [super viewDidLoad]; 31 | // Do any additional setup after loading the view from its nib. 32 | self.calendar.today = nil; 33 | self.calendar.locale = [NSLocale localeWithLocaleIdentifier:@"zh-CN"]; 34 | self.calendar.adjustsBoundingRectWhenChangingMonths = NO; 35 | self.calendar.placeholderType = FSCalendarPlaceholderTypeNone; 36 | self.calendar.appearance.headerMinimumDissolvedAlpha = 0; 37 | self.lunarCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierChinese]; 38 | self.lunarCalendar.locale = [NSLocale localeWithLocaleIdentifier:@"zh-CN"]; 39 | self.lunarChars = @[@"初一",@"初二",@"初三",@"初四",@"初五",@"初六",@"初七",@"初八",@"初九",@"初十",@"十一",@"十二",@"十三",@"十四",@"十五",@"十六",@"十七",@"十八",@"十九",@"二十",@"二一",@"二二",@"二三",@"二四",@"二五",@"二六",@"二七",@"二八",@"二九",@"三十"]; 40 | self.gregorian = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian]; 41 | if ([self.extensionContext respondsToSelector:@selector(setWidgetLargestAvailableDisplayMode:)]) { 42 | self.extensionContext.widgetLargestAvailableDisplayMode = NCWidgetDisplayModeExpanded; 43 | } else { 44 | self.preferredContentSize = CGSizeMake(0, self.calendarHeight.constant); 45 | } 46 | 47 | } 48 | 49 | - (void)widgetActiveDisplayModeDidChange:(NCWidgetDisplayMode)activeDisplayMode withMaximumSize:(CGSize)maxSize 50 | { 51 | if (activeDisplayMode == NCWidgetDisplayModeCompact) { 52 | [self.calendar setScope:FSCalendarScopeWeek animated:YES]; 53 | self.preferredContentSize = maxSize; 54 | } else if (activeDisplayMode == NCWidgetDisplayModeExpanded) { 55 | [self.calendar setScope:FSCalendarScopeMonth animated:YES]; 56 | self.preferredContentSize = CGSizeMake(maxSize.width, self.calendarHeight.constant); 57 | } 58 | } 59 | 60 | - (void)widgetPerformUpdateWithCompletionHandler:(void (^)(NCUpdateResult))completionHandler 61 | { 62 | // Perform any setup necessary in order to update the view. 63 | 64 | // If an error is encountered, use NCUpdateResultFailed 65 | // If there's no update required, use NCUpdateResultNoData 66 | // If there's an update, use NCUpdateResultNewData 67 | 68 | completionHandler(NCUpdateResultNewData); 69 | } 70 | 71 | - (UIEdgeInsets)widgetMarginInsetsForProposedMarginInsets:(UIEdgeInsets)defaultMarginInsets 72 | { 73 | return UIEdgeInsetsZero; 74 | } 75 | 76 | - (void)calendar:(FSCalendar *)calendar boundingRectWillChange:(CGRect)bounds animated:(BOOL)animated 77 | { 78 | self.calendarHeight.constant = CGRectGetHeight(bounds); 79 | [self.view layoutIfNeeded]; 80 | self.preferredContentSize = CGSizeMake(calendar.frame.size.width, self.calendarHeight.constant); 81 | } 82 | 83 | - (UIColor *)calendar:(FSCalendar *)calendar appearance:(FSCalendarAppearance *)appearance borderDefaultColorForDate:(NSDate *)date 84 | { 85 | return [self.gregorian isDateInToday:date] ? appearance.todayColor : nil; 86 | } 87 | 88 | - (UIColor *)calendar:(FSCalendar *)calendar appearance:(FSCalendarAppearance *)appearance fillSelectionColorForDate:(NSDate *)date 89 | { 90 | return [UIColor clearColor]; 91 | } 92 | 93 | - (UIColor *)calendar:(FSCalendar *)calendar appearance:(FSCalendarAppearance *)appearance borderSelectionColorForDate:(NSDate *)date 94 | { 95 | return appearance.selectionColor; 96 | } 97 | 98 | - (NSString *)calendar:(FSCalendar *)calendar subtitleForDate:(NSDate *)date 99 | { 100 | NSInteger day = [_lunarCalendar components:NSCalendarUnitDay fromDate:date].day; 101 | return _lunarChars[day-1]; 102 | } 103 | 104 | - (void)calendar:(FSCalendar *)calendar didSelectDate:(NSDate *)date atMonthPosition:(FSCalendarMonthPosition)monthPosition 105 | { 106 | if (monthPosition != FSCalendarMonthPositionCurrent) { 107 | [calendar setCurrentPage:date animated:YES]; 108 | } 109 | } 110 | 111 | - (IBAction)prevClicked:(id)sender 112 | { 113 | NSCalendarUnit unit = (self.calendar.scope==FSCalendarScopeMonth) ? NSCalendarUnitMonth : NSCalendarUnitWeekOfYear; 114 | NSDate *prevPage = [self.gregorian dateByAddingUnit:unit value:-1 toDate:self.calendar.currentPage options:0]; 115 | [self.calendar setCurrentPage:prevPage animated:YES]; 116 | 117 | } 118 | 119 | - (IBAction)nextClicked:(id)sender 120 | { 121 | NSCalendarUnit unit = (self.calendar.scope==FSCalendarScopeMonth) ? NSCalendarUnitMonth : NSCalendarUnitWeekOfYear; 122 | NSDate *nextPage = [self.gregorian dateByAddingUnit:unit value:1 toDate:self.calendar.currentPage options:0]; 123 | [self.calendar setCurrentPage:nextPage animated:YES]; 124 | } 125 | 126 | @end 127 | -------------------------------------------------------------------------------- /Example-TodayExtension/TodayExtensionExample/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // Example-TodayExtension 4 | // 5 | // Created by dingwenchao on 9/6/16. 6 | // Copyright © 2016 dingwenchao. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /Example-TodayExtension/TodayExtensionExample/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // Example-TodayExtension 4 | // 5 | // Created by dingwenchao on 9/6/16. 6 | // Copyright © 2016 dingwenchao. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /Example-TodayExtension/TodayExtensionExample/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" : "57x57", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-57x57@1x.png", 49 | "scale" : "1x" 50 | }, 51 | { 52 | "size" : "57x57", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-57x57@2x.png", 55 | "scale" : "2x" 56 | }, 57 | { 58 | "size" : "60x60", 59 | "idiom" : "iphone", 60 | "filename" : "Icon-App-60x60@2x.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "60x60", 65 | "idiom" : "iphone", 66 | "filename" : "Icon-App-60x60@3x.png", 67 | "scale" : "3x" 68 | }, 69 | { 70 | "size" : "20x20", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-20x20@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "20x20", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-20x20@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "29x29", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-29x29@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "29x29", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-29x29@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "40x40", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-40x40@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "40x40", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-40x40@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "76x76", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-76x76@1x.png", 109 | "scale" : "1x" 110 | }, 111 | { 112 | "size" : "76x76", 113 | "idiom" : "ipad", 114 | "filename" : "Icon-App-76x76@2x.png", 115 | "scale" : "2x" 116 | }, 117 | { 118 | "size" : "83.5x83.5", 119 | "idiom" : "ipad", 120 | "filename" : "Icon-App-83.5x83.5@2x.png", 121 | "scale" : "2x" 122 | } 123 | ], 124 | "info" : { 125 | "version" : 1, 126 | "author" : "xcode" 127 | } 128 | } -------------------------------------------------------------------------------- /Example-TodayExtension/TodayExtensionExample/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-TodayExtension/TodayExtensionExample/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /Example-TodayExtension/TodayExtensionExample/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-TodayExtension/TodayExtensionExample/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /Example-TodayExtension/TodayExtensionExample/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-TodayExtension/TodayExtensionExample/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /Example-TodayExtension/TodayExtensionExample/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-TodayExtension/TodayExtensionExample/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /Example-TodayExtension/TodayExtensionExample/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-TodayExtension/TodayExtensionExample/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /Example-TodayExtension/TodayExtensionExample/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-TodayExtension/TodayExtensionExample/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /Example-TodayExtension/TodayExtensionExample/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-TodayExtension/TodayExtensionExample/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /Example-TodayExtension/TodayExtensionExample/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-TodayExtension/TodayExtensionExample/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /Example-TodayExtension/TodayExtensionExample/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-TodayExtension/TodayExtensionExample/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /Example-TodayExtension/TodayExtensionExample/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-TodayExtension/TodayExtensionExample/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png -------------------------------------------------------------------------------- /Example-TodayExtension/TodayExtensionExample/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-TodayExtension/TodayExtensionExample/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png -------------------------------------------------------------------------------- /Example-TodayExtension/TodayExtensionExample/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-TodayExtension/TodayExtensionExample/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /Example-TodayExtension/TodayExtensionExample/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-TodayExtension/TodayExtensionExample/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /Example-TodayExtension/TodayExtensionExample/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-TodayExtension/TodayExtensionExample/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /Example-TodayExtension/TodayExtensionExample/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-TodayExtension/TodayExtensionExample/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /Example-TodayExtension/TodayExtensionExample/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WenchaoD/FSCalendar/df53e79c324ea5f9e3dcb03b35b2b324de901205/Example-TodayExtension/TodayExtensionExample/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /Example-TodayExtension/TodayExtensionExample/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Example-TodayExtension/TodayExtensionExample/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 | -------------------------------------------------------------------------------- /Example-TodayExtension/TodayExtensionExample/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 | 28 | -------------------------------------------------------------------------------- /Example-TodayExtension/TodayExtensionExample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /Example-TodayExtension/TodayExtensionExample/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // Example-TodayExtension 4 | // 5 | // Created by dingwenchao on 9/6/16. 6 | // Copyright © 2016 dingwenchao. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /Example-TodayExtension/TodayExtensionExample/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // Example-TodayExtension 4 | // 5 | // Created by dingwenchao on 9/6/16. 6 | // Copyright © 2016 dingwenchao. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | @interface ViewController () 12 | 13 | @end 14 | 15 | @implementation ViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | // Do any additional setup after loading the view, typically from a nib. 20 | } 21 | 22 | - (void)didReceiveMemoryWarning { 23 | [super didReceiveMemoryWarning]; 24 | // Dispose of any resources that can be recreated. 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /Example-TodayExtension/TodayExtensionExample/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // Example-TodayExtension 4 | // 5 | // Created by dingwenchao on 9/6/16. 6 | // Copyright © 2016 dingwenchao. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /FSCalendar.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | 3 | s.name = "FSCalendar" 4 | s.version = "2.8.4" 5 | s.summary = "A superiorly awesome iOS7+ calendar control, compatible with Objective-C and Swift." 6 | 7 | s.homepage = "https://github.com/WenchaoD/FSCalendar" 8 | s.screenshots = "https://cloud.githubusercontent.com/assets/5186464/10262249/4fabae40-69f2-11e5-97ab-afbacd0a3da2.jpg" 9 | s.license = 'MIT' 10 | s.author = { "Wenchao Ding" => "f33chobits@gmail.com" } 11 | s.source = { :git => "https://github.com/WenchaoD/FSCalendar.git", :tag => s.version.to_s } 12 | 13 | s.platform = :ios 14 | s.ios.deployment_target = '8.0' 15 | s.requires_arc = true 16 | s.framework = 'UIKit', 'QuartzCore' 17 | s.source_files = 'FSCalendar/*.{h,m}' 18 | 19 | end 20 | -------------------------------------------------------------------------------- /FSCalendar/FSCalendarAppearance.h: -------------------------------------------------------------------------------- 1 | // 2 | // FSCalendarAppearance.h 3 | // Pods 4 | // 5 | // Created by DingWenchao on 6/29/15. 6 | // Copyright © 2016 Wenchao Ding. All rights reserved. 7 | // 8 | // https://github.com/WenchaoD 9 | // 10 | 11 | #import "FSCalendarConstants.h" 12 | 13 | @class FSCalendar; 14 | 15 | typedef NS_ENUM(NSInteger, FSCalendarCellState) { 16 | FSCalendarCellStateNormal = 0, 17 | FSCalendarCellStateSelected = 1, 18 | FSCalendarCellStatePlaceholder = 1 << 1, 19 | FSCalendarCellStateDisabled = 1 << 2, 20 | FSCalendarCellStateToday = 1 << 3, 21 | FSCalendarCellStateWeekend = 1 << 4, 22 | FSCalendarCellStateTodaySelected = FSCalendarCellStateToday|FSCalendarCellStateSelected 23 | }; 24 | 25 | typedef NS_ENUM(NSUInteger, FSCalendarSeparators) { 26 | FSCalendarSeparatorNone = 0, 27 | FSCalendarSeparatorInterRows = 1 28 | }; 29 | 30 | typedef NS_OPTIONS(NSUInteger, FSCalendarCaseOptions) { 31 | FSCalendarCaseOptionsHeaderUsesDefaultCase = 0, 32 | FSCalendarCaseOptionsHeaderUsesUpperCase = 1 << 0, 33 | FSCalendarCaseOptionsHeaderUsesCapitalized = 1 << 1, 34 | 35 | FSCalendarCaseOptionsWeekdayUsesDefaultCase = 0 << 4, 36 | FSCalendarCaseOptionsWeekdayUsesUpperCase = 1 << 4, 37 | FSCalendarCaseOptionsWeekdayUsesSingleUpperCase = 2 << 4, 38 | }; 39 | 40 | /** 41 | * FSCalendarAppearance determines the fonts and colors of components in the calendar. 42 | * 43 | * @see FSCalendarDelegateAppearance 44 | */ 45 | @interface FSCalendarAppearance : NSObject 46 | 47 | /** 48 | * The font of the day text. 49 | */ 50 | @property (strong, nonatomic) UIFont *titleFont; 51 | 52 | /** 53 | * The font of the subtitle text. 54 | */ 55 | @property (strong, nonatomic) UIFont *subtitleFont; 56 | 57 | /** 58 | * The font of the weekday text. 59 | */ 60 | @property (strong, nonatomic) UIFont *weekdayFont; 61 | 62 | /** 63 | * The font of the month text. 64 | */ 65 | @property (strong, nonatomic) UIFont *headerTitleFont; 66 | 67 | /** 68 | * The offset of the month header from default position. 69 | */ 70 | @property (assign, nonatomic) CGPoint headerTitleOffset; 71 | 72 | /** 73 | * The offset of the day text from default position. 74 | */ 75 | @property (assign, nonatomic) CGPoint titleOffset; 76 | 77 | /** 78 | * The offset of the day text from default position. 79 | */ 80 | @property (assign, nonatomic) CGPoint subtitleOffset; 81 | 82 | /** 83 | * The offset of the event dots from default position. 84 | */ 85 | @property (assign, nonatomic) CGPoint eventOffset; 86 | 87 | /** 88 | * The offset of the image from default position. 89 | */ 90 | @property (assign, nonatomic) CGPoint imageOffset; 91 | 92 | /** 93 | * The color of event dots. 94 | */ 95 | @property (strong, nonatomic) UIColor *eventDefaultColor; 96 | 97 | /** 98 | * The color of event dots. 99 | */ 100 | @property (strong, nonatomic) UIColor *eventSelectionColor; 101 | 102 | /** 103 | * The color of weekday text. 104 | */ 105 | @property (strong, nonatomic) UIColor *weekdayTextColor; 106 | 107 | /** 108 | * The color of month header text. 109 | */ 110 | @property (strong, nonatomic) UIColor *headerTitleColor; 111 | 112 | /** 113 | * The color oh month header separator 114 | */ 115 | @property (strong, nonatomic) UIColor *headerSeparatorColor; 116 | 117 | /** 118 | * The date format of the month header. 119 | */ 120 | @property (strong, nonatomic) NSString *headerDateFormat; 121 | 122 | /** 123 | * The text alignment of the month header. 124 | */ 125 | @property (assign, nonatomic) NSTextAlignment headerTitleAlignment; 126 | 127 | /** 128 | * The alpha value of month label staying on the fringes. 129 | */ 130 | @property (assign, nonatomic) CGFloat headerMinimumDissolvedAlpha; 131 | 132 | /** 133 | * The day text color for unselected state. 134 | */ 135 | @property (strong, nonatomic) UIColor *titleDefaultColor; 136 | 137 | /** 138 | * The day text color for selected state. 139 | */ 140 | @property (strong, nonatomic) UIColor *titleSelectionColor; 141 | 142 | /** 143 | * The day text color for today in the calendar. 144 | */ 145 | @property (strong, nonatomic) UIColor *titleTodayColor; 146 | 147 | /** 148 | * The day text color for days out of current month. 149 | */ 150 | @property (strong, nonatomic) UIColor *titlePlaceholderColor; 151 | 152 | /** 153 | * The day text color for weekend. 154 | */ 155 | @property (strong, nonatomic) UIColor *titleWeekendColor; 156 | 157 | /** 158 | * The subtitle text color for unselected state. 159 | */ 160 | @property (strong, nonatomic) UIColor *subtitleDefaultColor; 161 | 162 | /** 163 | * The subtitle text color for selected state. 164 | */ 165 | @property (strong, nonatomic) UIColor *subtitleSelectionColor; 166 | 167 | /** 168 | * The subtitle text color for today in the calendar. 169 | */ 170 | @property (strong, nonatomic) UIColor *subtitleTodayColor; 171 | 172 | /** 173 | * The subtitle text color for days out of current month. 174 | */ 175 | @property (strong, nonatomic) UIColor *subtitlePlaceholderColor; 176 | 177 | /** 178 | * The subtitle text color for weekend. 179 | */ 180 | @property (strong, nonatomic) UIColor *subtitleWeekendColor; 181 | 182 | /** 183 | * The fill color of the shape for selected state. 184 | */ 185 | @property (strong, nonatomic) UIColor *selectionColor; 186 | 187 | /** 188 | * The fill color of the shape for today. 189 | */ 190 | @property (strong, nonatomic) UIColor *todayColor; 191 | 192 | /** 193 | * The fill color of the shape for today and selected state. 194 | */ 195 | @property (strong, nonatomic) UIColor *todaySelectionColor; 196 | 197 | /** 198 | * The border color of the shape for unselected state. 199 | */ 200 | @property (strong, nonatomic) UIColor *borderDefaultColor; 201 | 202 | /** 203 | * The border color of the shape for selected state. 204 | */ 205 | @property (strong, nonatomic) UIColor *borderSelectionColor; 206 | 207 | /** 208 | * The border radius, while 1 means a circle, 0 means a rectangle, and the middle value will give it a corner radius. 209 | */ 210 | @property (assign, nonatomic) CGFloat borderRadius; 211 | 212 | /** 213 | * The case options manage the case of month label and weekday symbols. 214 | * 215 | * @see FSCalendarCaseOptions 216 | */ 217 | @property (assign, nonatomic) FSCalendarCaseOptions caseOptions; 218 | 219 | /** 220 | * The line integrations for calendar. 221 | * 222 | */ 223 | @property (assign, nonatomic) FSCalendarSeparators separators; 224 | 225 | #if TARGET_INTERFACE_BUILDER 226 | 227 | // For preview only 228 | @property (assign, nonatomic) BOOL fakeSubtitles; 229 | @property (assign, nonatomic) BOOL fakeEventDots; 230 | @property (assign, nonatomic) NSInteger fakedSelectedDay; 231 | 232 | #endif 233 | 234 | @end 235 | 236 | 237 | 238 | -------------------------------------------------------------------------------- /FSCalendar/FSCalendarCalculator.h: -------------------------------------------------------------------------------- 1 | // 2 | // FSCalendarCalculator.h 3 | // FSCalendar 4 | // 5 | // Created by dingwenchao on 30/10/2016. 6 | // Copyright © 2016 Wenchao Ding. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | struct FSCalendarCoordinate { 13 | NSInteger row; 14 | NSInteger column; 15 | }; 16 | typedef struct FSCalendarCoordinate FSCalendarCoordinate; 17 | 18 | @interface FSCalendarCalculator : NSObject 19 | 20 | @property (weak , nonatomic) FSCalendar *calendar; 21 | 22 | @property (readonly, nonatomic) NSInteger numberOfSections; 23 | 24 | - (instancetype)initWithCalendar:(FSCalendar *)calendar; 25 | 26 | - (NSDate *)safeDateForDate:(NSDate *)date; 27 | 28 | - (NSDate *)dateForIndexPath:(NSIndexPath *)indexPath; 29 | - (NSDate *)dateForIndexPath:(NSIndexPath *)indexPath scope:(FSCalendarScope)scope; 30 | - (NSIndexPath *)indexPathForDate:(NSDate *)date; 31 | - (NSIndexPath *)indexPathForDate:(NSDate *)date scope:(FSCalendarScope)scope; 32 | - (NSIndexPath *)indexPathForDate:(NSDate *)date atMonthPosition:(FSCalendarMonthPosition)position; 33 | - (NSIndexPath *)indexPathForDate:(NSDate *)date atMonthPosition:(FSCalendarMonthPosition)position scope:(FSCalendarScope)scope; 34 | 35 | - (NSDate *)pageForSection:(NSInteger)section; 36 | - (NSDate *)weekForSection:(NSInteger)section; 37 | - (NSDate *)monthForSection:(NSInteger)section; 38 | - (NSDate *)monthHeadForSection:(NSInteger)section; 39 | 40 | - (NSInteger)numberOfHeadPlaceholdersForMonth:(NSDate *)month; 41 | - (NSInteger)numberOfRowsInMonth:(NSDate *)month; 42 | - (NSInteger)numberOfRowsInSection:(NSInteger)section; 43 | 44 | - (FSCalendarMonthPosition)monthPositionForIndexPath:(NSIndexPath *)indexPath; 45 | - (FSCalendarCoordinate)coordinateForIndexPath:(NSIndexPath *)indexPath; 46 | 47 | - (void)reloadSections; 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /FSCalendar/FSCalendarCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // FSCalendarCell.h 3 | // Pods 4 | // 5 | // Created by Wenchao Ding on 12/3/15. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @class FSCalendar, FSCalendarAppearance, FSCalendarEventIndicator; 12 | 13 | typedef NS_ENUM(NSUInteger, FSCalendarMonthPosition); 14 | 15 | @interface FSCalendarCell : UICollectionViewCell 16 | 17 | #pragma mark - Public properties 18 | 19 | /** 20 | The day text label of the cell 21 | */ 22 | @property (weak, nonatomic) UILabel *titleLabel; 23 | 24 | 25 | /** 26 | The subtitle label of the cell 27 | */ 28 | @property (weak, nonatomic) UILabel *subtitleLabel; 29 | 30 | 31 | /** 32 | The shape layer of the cell 33 | */ 34 | @property (weak, nonatomic) CAShapeLayer *shapeLayer; 35 | 36 | /** 37 | The imageView below shape layer of the cell 38 | */ 39 | @property (weak, nonatomic) UIImageView *imageView; 40 | 41 | 42 | /** 43 | The collection of event dots of the cell 44 | */ 45 | @property (weak, nonatomic) FSCalendarEventIndicator *eventIndicator; 46 | 47 | /** 48 | A boolean value indicates that whether the cell is "placeholder". Default is NO. 49 | */ 50 | @property (assign, nonatomic, getter=isPlaceholder) BOOL placeholder; 51 | 52 | #pragma mark - Private properties 53 | 54 | @property (weak, nonatomic) FSCalendar *calendar; 55 | @property (weak, nonatomic) FSCalendarAppearance *appearance; 56 | 57 | @property (strong, nonatomic) NSString *subtitle; 58 | @property (strong, nonatomic) UIImage *image; 59 | @property (assign, nonatomic) FSCalendarMonthPosition monthPosition; 60 | 61 | @property (assign, nonatomic) NSInteger numberOfEvents; 62 | @property (assign, nonatomic) BOOL dateIsToday; 63 | @property (assign, nonatomic) BOOL weekend; 64 | 65 | @property (strong, nonatomic) UIColor *preferredFillDefaultColor; 66 | @property (strong, nonatomic) UIColor *preferredFillSelectionColor; 67 | @property (strong, nonatomic) UIColor *preferredTitleDefaultColor; 68 | @property (strong, nonatomic) UIColor *preferredTitleSelectionColor; 69 | @property (strong, nonatomic) UIColor *preferredSubtitleDefaultColor; 70 | @property (strong, nonatomic) UIColor *preferredSubtitleSelectionColor; 71 | @property (strong, nonatomic) UIColor *preferredBorderDefaultColor; 72 | @property (strong, nonatomic) UIColor *preferredBorderSelectionColor; 73 | @property (assign, nonatomic) CGPoint preferredTitleOffset; 74 | @property (assign, nonatomic) CGPoint preferredSubtitleOffset; 75 | @property (assign, nonatomic) CGPoint preferredImageOffset; 76 | @property (assign, nonatomic) CGPoint preferredEventOffset; 77 | 78 | @property (strong, nonatomic) NSArray *preferredEventDefaultColors; 79 | @property (strong, nonatomic) NSArray *preferredEventSelectionColors; 80 | @property (assign, nonatomic) CGFloat preferredBorderRadius; 81 | 82 | // Add subviews to self.contentView and set up constraints 83 | - (instancetype)initWithFrame:(CGRect)frame NS_REQUIRES_SUPER; 84 | - (instancetype)initWithCoder:(NSCoder *)aDecoder NS_REQUIRES_SUPER; 85 | 86 | // For DIY overridden 87 | - (void)layoutSubviews NS_REQUIRES_SUPER; // Configure frames of subviews 88 | - (void)configureAppearance NS_REQUIRES_SUPER; // Configure appearance for cell 89 | 90 | - (UIColor *)colorForCurrentStateInDictionary:(NSDictionary *)dictionary; 91 | - (void)performSelecting; 92 | 93 | @end 94 | 95 | @interface FSCalendarEventIndicator : UIView 96 | 97 | @property (assign, nonatomic) NSInteger numberOfEvents; 98 | @property (strong, nonatomic) id color; 99 | 100 | @end 101 | 102 | @interface FSCalendarBlankCell : UICollectionViewCell 103 | 104 | - (void)configureAppearance; 105 | 106 | @end 107 | 108 | -------------------------------------------------------------------------------- /FSCalendar/FSCalendarCollectionView.h: -------------------------------------------------------------------------------- 1 | // 2 | // FSCalendarCollectionView.h 3 | // FSCalendar 4 | // 5 | // Created by Wenchao Ding on 10/25/15. 6 | // Copyright (c) 2015 Wenchao Ding. All rights reserved. 7 | // 8 | 9 | #import 10 | @class FSCalendarCollectionView; 11 | 12 | 13 | @protocol FSCalendarCollectionViewInternalDelegate 14 | 15 | @optional 16 | - (void)collectionViewDidFinishLayoutSubviews:(FSCalendarCollectionView *)collectionView; 17 | 18 | @end 19 | 20 | @interface FSCalendarCollectionView : UICollectionView 21 | 22 | @property (weak, nonatomic) id internalDelegate; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /FSCalendar/FSCalendarCollectionView.m: -------------------------------------------------------------------------------- 1 | // 2 | // FSCalendarCollectionView.m 3 | // FSCalendar 4 | // 5 | // Created by Wenchao Ding on 10/25/15. 6 | // Copyright (c) 2015 Wenchao Ding. All rights reserved. 7 | // 8 | // Reject -[UIScrollView(UIScrollViewInternal) _adjustContentOffsetIfNecessary] 9 | 10 | 11 | #import "FSCalendarCollectionView.h" 12 | #import "FSCalendarExtensions.h" 13 | #import "FSCalendarConstants.h" 14 | 15 | @interface FSCalendarCollectionView () 16 | 17 | - (void)commonInit; 18 | 19 | @end 20 | 21 | @implementation FSCalendarCollectionView 22 | 23 | @synthesize scrollsToTop = _scrollsToTop, contentInset = _contentInset; 24 | 25 | - (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout 26 | { 27 | self = [super initWithFrame:frame collectionViewLayout:layout]; 28 | if (self) { 29 | [self commonInit]; 30 | } 31 | return self; 32 | } 33 | 34 | - (instancetype)initWithFrame:(CGRect)frame 35 | { 36 | self = [super initWithFrame:frame]; 37 | if (self) { 38 | [self commonInit]; 39 | } 40 | return self; 41 | } 42 | 43 | - (void)commonInit 44 | { 45 | self.scrollsToTop = NO; 46 | self.contentInset = UIEdgeInsetsZero; 47 | if (@available(iOS 10.0, *)) self.prefetchingEnabled = NO; 48 | if (@available(iOS 11.0, *)) self.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; 49 | } 50 | 51 | - (void)layoutSubviews 52 | { 53 | [super layoutSubviews]; 54 | if (self.internalDelegate && [self.internalDelegate respondsToSelector:@selector(collectionViewDidFinishLayoutSubviews:)]) { 55 | [self.internalDelegate collectionViewDidFinishLayoutSubviews:self]; 56 | } 57 | } 58 | 59 | - (void)setContentInset:(UIEdgeInsets)contentInset 60 | { 61 | [super setContentInset:UIEdgeInsetsZero]; 62 | if (contentInset.top) { 63 | self.contentOffset = CGPointMake(self.contentOffset.x, self.contentOffset.y+contentInset.top); 64 | } 65 | } 66 | 67 | - (void)setScrollsToTop:(BOOL)scrollsToTop 68 | { 69 | [super setScrollsToTop:NO]; 70 | } 71 | 72 | @end 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /FSCalendar/FSCalendarCollectionViewLayout.h: -------------------------------------------------------------------------------- 1 | // 2 | // FSCalendarAnimationLayout.h 3 | // FSCalendar 4 | // 5 | // Created by dingwenchao on 1/3/16. 6 | // Copyright © 2016 Wenchao Ding. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class FSCalendar; 12 | 13 | @interface FSCalendarCollectionViewLayout : UICollectionViewLayout 14 | 15 | @property (weak, nonatomic) FSCalendar *calendar; 16 | 17 | @property (assign, nonatomic) UIEdgeInsets sectionInsets; 18 | @property (assign, nonatomic) UICollectionViewScrollDirection scrollDirection; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /FSCalendar/FSCalendarConstants.h: -------------------------------------------------------------------------------- 1 | // 2 | // FSCalendarConstants.h 3 | // FSCalendar 4 | // 5 | // Created by dingwenchao on 8/28/15. 6 | // Copyright © 2016 Wenchao Ding. All rights reserved. 7 | // 8 | // https://github.com/WenchaoD 9 | // 10 | 11 | #import 12 | #import 13 | 14 | #pragma mark - Constants 15 | 16 | CG_EXTERN CGFloat const FSCalendarStandardHeaderHeight; 17 | CG_EXTERN CGFloat const FSCalendarStandardWeekdayHeight; 18 | CG_EXTERN CGFloat const FSCalendarStandardMonthlyPageHeight; 19 | CG_EXTERN CGFloat const FSCalendarStandardWeeklyPageHeight; 20 | CG_EXTERN CGFloat const FSCalendarStandardCellDiameter; 21 | CG_EXTERN CGFloat const FSCalendarStandardSeparatorThickness; 22 | CG_EXTERN CGFloat const FSCalendarAutomaticDimension; 23 | CG_EXTERN CGFloat const FSCalendarDefaultBounceAnimationDuration; 24 | CG_EXTERN CGFloat const FSCalendarStandardRowHeight; 25 | CG_EXTERN CGFloat const FSCalendarStandardTitleTextSize; 26 | CG_EXTERN CGFloat const FSCalendarStandardSubtitleTextSize; 27 | CG_EXTERN CGFloat const FSCalendarStandardWeekdayTextSize; 28 | CG_EXTERN CGFloat const FSCalendarStandardHeaderTextSize; 29 | CG_EXTERN CGFloat const FSCalendarMaximumEventDotDiameter; 30 | 31 | UIKIT_EXTERN NSInteger const FSCalendarDefaultHourComponent; 32 | UIKIT_EXTERN NSInteger const FSCalendarMaximumNumberOfEvents; 33 | 34 | UIKIT_EXTERN NSString * const FSCalendarDefaultCellReuseIdentifier; 35 | UIKIT_EXTERN NSString * const FSCalendarBlankCellReuseIdentifier; 36 | UIKIT_EXTERN NSString * const FSCalendarInvalidArgumentsExceptionName; 37 | 38 | CG_EXTERN CGPoint const CGPointInfinity; 39 | CG_EXTERN CGSize const CGSizeAutomatic; 40 | 41 | #if TARGET_INTERFACE_BUILDER 42 | #define FSCalendarDeviceIsIPad NO 43 | #else 44 | #define FSCalendarDeviceIsIPad [[UIDevice currentDevice].model hasPrefix:@"iPad"] 45 | #endif 46 | 47 | #define FSCalendarStandardSelectionColor FSColorRGBA(31,119,219,1.0) 48 | #define FSCalendarStandardTodayColor FSColorRGBA(198,51,42 ,1.0) 49 | #define FSCalendarStandardTitleTextColor FSColorRGBA(14,69,221 ,1.0) 50 | #define FSCalendarStandardEventDotColor FSColorRGBA(31,119,219,0.75) 51 | 52 | #define FSCalendarStandardLineColor [[UIColor lightGrayColor] colorWithAlphaComponent:0.30] 53 | #define FSCalendarStandardSeparatorColor [[UIColor lightGrayColor] colorWithAlphaComponent:0.60] 54 | 55 | #define FSColorRGBA(r,g,b,a) [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:a] 56 | #define FSCalendarInAppExtension [[[NSBundle mainBundle] bundlePath] hasSuffix:@".appex"] 57 | 58 | #define FSCalendarFloor(c) floorf(c) 59 | #define FSCalendarRound(c) roundf(c) 60 | #define FSCalendarCeil(c) ceilf(c) 61 | #define FSCalendarMod(c1,c2) fmodf(c1,c2) 62 | 63 | #define FSCalendarHalfRound(c) (FSCalendarRound(c*2)*0.5) 64 | #define FSCalendarHalfFloor(c) (FSCalendarFloor(c*2)*0.5) 65 | #define FSCalendarHalfCeil(c) (FSCalendarCeil(c*2)*0.5) 66 | 67 | #define FSCalendarUseWeakSelf __weak __typeof__(self) FSCalendarWeakSelf = self; 68 | #define FSCalendarUseStrongSelf __strong __typeof__(self) self = FSCalendarWeakSelf; 69 | 70 | 71 | #pragma mark - Deprecated 72 | 73 | #define FSCalendarDeprecated(instead) DEPRECATED_MSG_ATTRIBUTE(" Use " # instead " instead") 74 | 75 | static inline void FSCalendarSliceCake(CGFloat cake, NSInteger count, CGFloat *pieces) { 76 | CGFloat total = cake; 77 | for (int i = 0; i < count; i++) { 78 | NSInteger remains = count - i; 79 | CGFloat piece = FSCalendarRound(total/remains*2)*0.5; 80 | total -= piece; 81 | pieces[i] = piece; 82 | } 83 | } 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /FSCalendar/FSCalendarConstants.m: -------------------------------------------------------------------------------- 1 | // 2 | // FSCalendarConstants.m 3 | // FSCalendar 4 | // 5 | // Created by dingwenchao on 8/28/15. 6 | // Copyright © 2016 Wenchao Ding. All rights reserved. 7 | // 8 | // https://github.com/WenchaoD 9 | // 10 | 11 | #import "FSCalendarConstants.h" 12 | 13 | CGFloat const FSCalendarStandardHeaderHeight = 40; 14 | CGFloat const FSCalendarStandardWeekdayHeight = 25; 15 | CGFloat const FSCalendarStandardMonthlyPageHeight = 300.0; 16 | CGFloat const FSCalendarStandardWeeklyPageHeight = 108+1/3.0; 17 | CGFloat const FSCalendarStandardCellDiameter = 100/3.0; 18 | CGFloat const FSCalendarStandardSeparatorThickness = 0.5; 19 | CGFloat const FSCalendarAutomaticDimension = -1; 20 | CGFloat const FSCalendarDefaultBounceAnimationDuration = 0.15; 21 | CGFloat const FSCalendarStandardRowHeight = 38; 22 | CGFloat const FSCalendarStandardTitleTextSize = 13.5; 23 | CGFloat const FSCalendarStandardSubtitleTextSize = 10; 24 | CGFloat const FSCalendarStandardWeekdayTextSize = 14; 25 | CGFloat const FSCalendarStandardHeaderTextSize = 16.5; 26 | CGFloat const FSCalendarMaximumEventDotDiameter = 4.8; 27 | 28 | NSInteger const FSCalendarDefaultHourComponent = 0; 29 | NSInteger const FSCalendarMaximumNumberOfEvents = 3; 30 | 31 | NSString * const FSCalendarDefaultCellReuseIdentifier = @"_FSCalendarDefaultCellReuseIdentifier"; 32 | NSString * const FSCalendarBlankCellReuseIdentifier = @"_FSCalendarBlankCellReuseIdentifier"; 33 | NSString * const FSCalendarInvalidArgumentsExceptionName = @"Invalid argument exception"; 34 | 35 | CGPoint const CGPointInfinity = { 36 | .x = CGFLOAT_MAX, 37 | .y = CGFLOAT_MAX 38 | }; 39 | 40 | CGSize const CGSizeAutomatic = { 41 | .width = FSCalendarAutomaticDimension, 42 | .height = FSCalendarAutomaticDimension 43 | }; 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /FSCalendar/FSCalendarDelegationFactory.h: -------------------------------------------------------------------------------- 1 | // 2 | // FSCalendarDelegationFactory.h 3 | // FSCalendar 4 | // 5 | // Created by dingwenchao on 19/12/2016. 6 | // Copyright © 2016 wenchaoios. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "FSCalendarDelegationProxy.h" 11 | 12 | @interface FSCalendarDelegationFactory : NSObject 13 | 14 | + (FSCalendarDelegationProxy *)dataSourceProxy; 15 | + (FSCalendarDelegationProxy *)delegateProxy; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /FSCalendar/FSCalendarDelegationFactory.m: -------------------------------------------------------------------------------- 1 | // 2 | // FSCalendarDelegationFactory.m 3 | // FSCalendar 4 | // 5 | // Created by dingwenchao on 19/12/2016. 6 | // Copyright © 2016 wenchaoios. All rights reserved. 7 | // 8 | 9 | #import "FSCalendarDelegationFactory.h" 10 | 11 | @implementation FSCalendarDelegationFactory 12 | 13 | + (FSCalendarDelegationProxy *)dataSourceProxy 14 | { 15 | FSCalendarDelegationProxy *delegation = [[FSCalendarDelegationProxy alloc] init]; 16 | delegation.protocol = @protocol(FSCalendarDataSource); 17 | return delegation; 18 | } 19 | 20 | + (FSCalendarDelegationProxy *)delegateProxy 21 | { 22 | FSCalendarDelegationProxy *delegation = [[FSCalendarDelegationProxy alloc] init]; 23 | delegation.protocol = @protocol(FSCalendarDelegateAppearance); 24 | return delegation; 25 | } 26 | 27 | @end 28 | 29 | #undef FSCalendarSelectorEntry 30 | 31 | -------------------------------------------------------------------------------- /FSCalendar/FSCalendarDelegationProxy.h: -------------------------------------------------------------------------------- 1 | // 2 | // FSCalendarDelegationProxy.h 3 | // FSCalendar 4 | // 5 | // Created by dingwenchao on 11/12/2016. 6 | // Copyright © 2016 Wenchao Ding. All rights reserved. 7 | // 8 | // https://github.com/WenchaoD 9 | // 10 | // 1. Smart proxy delegation http://petersteinberger.com/blog/2013/smart-proxy-delegation/ 11 | // 2. Manage deprecated delegation functions 12 | // 13 | 14 | #import 15 | #import "FSCalendar.h" 16 | 17 | NS_ASSUME_NONNULL_BEGIN 18 | 19 | @interface FSCalendarDelegationProxy : NSProxy 20 | 21 | @property (weak , nonatomic) id delegation; 22 | @property (strong, nonatomic) Protocol *protocol; 23 | @property (strong, nonatomic) NSDictionary *deprecations; 24 | 25 | - (instancetype)init; 26 | - (SEL)deprecatedSelectorOfSelector:(SEL)selector; 27 | 28 | @end 29 | 30 | NS_ASSUME_NONNULL_END 31 | 32 | -------------------------------------------------------------------------------- /FSCalendar/FSCalendarDelegationProxy.m: -------------------------------------------------------------------------------- 1 | // 2 | // FSCalendarDelegationProxy.m 3 | // FSCalendar 4 | // 5 | // Created by dingwenchao on 11/12/2016. 6 | // Copyright © 2016 Wenchao Ding. All rights reserved. 7 | // 8 | 9 | #import "FSCalendarDelegationProxy.h" 10 | #import 11 | 12 | @implementation FSCalendarDelegationProxy 13 | 14 | - (instancetype)init 15 | { 16 | return self; 17 | } 18 | 19 | - (BOOL)respondsToSelector:(SEL)selector 20 | { 21 | BOOL responds = [self.delegation respondsToSelector:selector]; 22 | if (!responds) responds = [self.delegation respondsToSelector:[self deprecatedSelectorOfSelector:selector]]; 23 | if (!responds) responds = [super respondsToSelector:selector]; 24 | return responds; 25 | } 26 | 27 | - (BOOL)conformsToProtocol:(Protocol *)protocol 28 | { 29 | return [self.delegation conformsToProtocol:protocol]; 30 | } 31 | 32 | - (void)forwardInvocation:(NSInvocation *)invocation 33 | { 34 | SEL selector = invocation.selector; 35 | if (![self.delegation respondsToSelector:selector]) { 36 | selector = [self deprecatedSelectorOfSelector:selector]; 37 | invocation.selector = selector; 38 | } 39 | if ([self.delegation respondsToSelector:selector]) { 40 | [invocation invokeWithTarget:self.delegation]; 41 | } 42 | } 43 | 44 | - (NSMethodSignature *)methodSignatureForSelector:(SEL)sel 45 | { 46 | if ([self.delegation respondsToSelector:sel]) { 47 | return [(NSObject *)self.delegation methodSignatureForSelector:sel]; 48 | } 49 | SEL selector = [self deprecatedSelectorOfSelector:sel]; 50 | if ([self.delegation respondsToSelector:selector]) { 51 | return [(NSObject *)self.delegation methodSignatureForSelector:selector]; 52 | } 53 | #if TARGET_INTERFACE_BUILDER 54 | return [NSObject methodSignatureForSelector:@selector(init)]; 55 | #else 56 | struct objc_method_description desc = protocol_getMethodDescription(self.protocol, sel, NO, YES); 57 | const char *types = desc.types; 58 | return types?[NSMethodSignature signatureWithObjCTypes:types]:[NSObject methodSignatureForSelector:@selector(init)]; 59 | #endif 60 | } 61 | 62 | - (SEL)deprecatedSelectorOfSelector:(SEL)selector 63 | { 64 | NSString *selectorString = NSStringFromSelector(selector); 65 | selectorString = self.deprecations[selectorString]; 66 | return NSSelectorFromString(selectorString); 67 | } 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /FSCalendar/FSCalendarDynamicHeader.h: -------------------------------------------------------------------------------- 1 | // 2 | // FSCalendarDynamicHeader.h 3 | // Pods 4 | // 5 | // Created by DingWenchao on 6/29/15. 6 | // 7 | // 动感头文件,仅供框架内部使用。 8 | // Private header, don't use it. 9 | // 10 | 11 | #import 12 | #import 13 | 14 | #import "FSCalendar.h" 15 | #import "FSCalendarCell.h" 16 | #import "FSCalendarHeaderView.h" 17 | #import "FSCalendarStickyHeader.h" 18 | #import "FSCalendarCollectionView.h" 19 | #import "FSCalendarCollectionViewLayout.h" 20 | #import "FSCalendarCalculator.h" 21 | #import "FSCalendarTransitionCoordinator.h" 22 | #import "FSCalendarDelegationProxy.h" 23 | 24 | @interface FSCalendar (Dynamic) 25 | 26 | @property (readonly, nonatomic) FSCalendarCollectionView *collectionView; 27 | @property (readonly, nonatomic) FSCalendarCollectionViewLayout *collectionViewLayout; 28 | @property (readonly, nonatomic) FSCalendarTransitionCoordinator *transitionCoordinator; 29 | @property (readonly, nonatomic) FSCalendarCalculator *calculator; 30 | @property (readonly, nonatomic) BOOL floatingMode; 31 | @property (readonly, nonatomic) NSArray *visibleStickyHeaders; 32 | @property (readonly, nonatomic) CGFloat preferredHeaderHeight; 33 | @property (readonly, nonatomic) CGFloat preferredWeekdayHeight; 34 | 35 | @property (readonly, nonatomic) NSCalendar *gregorian; 36 | @property (readonly, nonatomic) NSDateFormatter *formatter; 37 | 38 | @property (readonly, nonatomic) UIView *contentView; 39 | @property (readonly, nonatomic) UIView *daysContainer; 40 | 41 | @property (assign, nonatomic) BOOL needsAdjustingViewFrame; 42 | 43 | - (void)adjustMonthPosition; 44 | - (void)configureAppearance; 45 | 46 | - (CGSize)sizeThatFits:(CGSize)size scope:(FSCalendarScope)scope; 47 | 48 | @end 49 | 50 | @interface FSCalendarAppearance (Dynamic) 51 | 52 | @property (readwrite, nonatomic) FSCalendar *calendar; 53 | 54 | @property (readonly, nonatomic) NSDictionary *backgroundColors; 55 | @property (readonly, nonatomic) NSDictionary *titleColors; 56 | @property (readonly, nonatomic) NSDictionary *subtitleColors; 57 | @property (readonly, nonatomic) NSDictionary *borderColors; 58 | 59 | @end 60 | 61 | @interface FSCalendarWeekdayView (Dynamic) 62 | 63 | @property (readwrite, nonatomic) FSCalendar *calendar; 64 | 65 | @end 66 | 67 | @interface FSCalendarCollectionViewLayout (Dynamic) 68 | 69 | @property (readonly, nonatomic) CGSize estimatedItemSize; 70 | 71 | @end 72 | 73 | @interface FSCalendarDelegationProxy() 74 | @end 75 | 76 | 77 | -------------------------------------------------------------------------------- /FSCalendar/FSCalendarExtensions.h: -------------------------------------------------------------------------------- 1 | // 2 | // FSCalendarExtensions.h 3 | // FSCalendar 4 | // 5 | // Created by dingwenchao on 10/8/16. 6 | // Copyright © 2016 Wenchao Ding. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface UIView (FSCalendarExtensions) 15 | 16 | @property (nonatomic) CGFloat fs_width; 17 | @property (nonatomic) CGFloat fs_height; 18 | 19 | @property (nonatomic) CGFloat fs_top; 20 | @property (nonatomic) CGFloat fs_left; 21 | @property (nonatomic) CGFloat fs_bottom; 22 | @property (nonatomic) CGFloat fs_right; 23 | 24 | @end 25 | 26 | 27 | @interface CALayer (FSCalendarExtensions) 28 | 29 | @property (nonatomic) CGFloat fs_width; 30 | @property (nonatomic) CGFloat fs_height; 31 | 32 | @property (nonatomic) CGFloat fs_top; 33 | @property (nonatomic) CGFloat fs_left; 34 | @property (nonatomic) CGFloat fs_bottom; 35 | @property (nonatomic) CGFloat fs_right; 36 | 37 | @end 38 | 39 | 40 | @interface NSCalendar (FSCalendarExtensions) 41 | 42 | - (nullable NSDate *)fs_firstDayOfMonth:(NSDate *)month; 43 | - (nullable NSDate *)fs_lastDayOfMonth:(NSDate *)month; 44 | - (nullable NSDate *)fs_firstDayOfWeek:(NSDate *)week; 45 | - (nullable NSDate *)fs_lastDayOfWeek:(NSDate *)week; 46 | - (nullable NSDate *)fs_middleDayOfWeek:(NSDate *)week; 47 | - (NSInteger)fs_numberOfDaysInMonth:(NSDate *)month; 48 | 49 | @end 50 | 51 | @interface NSMapTable (FSCalendarExtensions) 52 | 53 | - (void)setObject:(nullable id)obj forKeyedSubscript:(id)key; 54 | - (id)objectForKeyedSubscript:(id)key; 55 | 56 | @end 57 | 58 | @interface NSCache (FSCalendarExtensions) 59 | 60 | - (void)setObject:(nullable id)obj forKeyedSubscript:(id)key; 61 | - (id)objectForKeyedSubscript:(id)key; 62 | 63 | @end 64 | 65 | 66 | @interface NSObject (FSCalendarExtensions) 67 | 68 | #define IVAR_DEF(SET,GET,TYPE) \ 69 | - (void)fs_set##SET##Variable:(TYPE)value forKey:(NSString *)key; \ 70 | - (TYPE)fs_##GET##VariableForKey:(NSString *)key; 71 | IVAR_DEF(Bool, bool, BOOL) 72 | IVAR_DEF(Float, float, CGFloat) 73 | IVAR_DEF(Integer, integer, NSInteger) 74 | IVAR_DEF(UnsignedInteger, unsignedInteger, NSUInteger) 75 | #undef IVAR_DEF 76 | 77 | - (void)fs_setVariable:(id)variable forKey:(NSString *)key; 78 | - (id)fs_variableForKey:(NSString *)key; 79 | 80 | - (nullable id)fs_performSelector:(SEL)selector withObjects:(nullable id)firstObject, ... NS_REQUIRES_NIL_TERMINATION; 81 | 82 | @end 83 | 84 | NS_ASSUME_NONNULL_END 85 | -------------------------------------------------------------------------------- /FSCalendar/FSCalendarHeaderView.h: -------------------------------------------------------------------------------- 1 | // 2 | // FSCalendarHeader.h 3 | // Pods 4 | // 5 | // Created by Wenchao Ding on 29/1/15. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @class FSCalendar, FSCalendarAppearance, FSCalendarHeaderLayout, FSCalendarCollectionView; 12 | 13 | @interface FSCalendarHeaderView : UIView 14 | 15 | @property (weak, nonatomic) FSCalendarCollectionView *collectionView; 16 | @property (weak, nonatomic) FSCalendarHeaderLayout *collectionViewLayout; 17 | @property (weak, nonatomic) FSCalendar *calendar; 18 | 19 | @property (assign, nonatomic) UICollectionViewScrollDirection scrollDirection; 20 | @property (assign, nonatomic) BOOL scrollEnabled; 21 | 22 | - (void)setScrollOffset:(CGFloat)scrollOffset; 23 | - (void)setScrollOffset:(CGFloat)scrollOffset animated:(BOOL)animated; 24 | - (void)reloadData; 25 | - (void)configureAppearance; 26 | 27 | @end 28 | 29 | 30 | @interface FSCalendarHeaderCell : UICollectionViewCell 31 | 32 | @property (weak, nonatomic) UILabel *titleLabel; 33 | @property (weak, nonatomic) FSCalendarHeaderView *header; 34 | 35 | @end 36 | 37 | @interface FSCalendarHeaderLayout : UICollectionViewFlowLayout 38 | 39 | @end 40 | 41 | @interface FSCalendarHeaderTouchDeliver : UIView 42 | 43 | @property (weak, nonatomic) FSCalendar *calendar; 44 | @property (weak, nonatomic) FSCalendarHeaderView *header; 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /FSCalendar/FSCalendarSeparatorDecorationView.h: -------------------------------------------------------------------------------- 1 | // 2 | // FSCalendarSeparatorDecorationView.h 3 | // FSCalendar 4 | // 5 | // Created by 丁文超 on 2018/10/10. 6 | // Copyright © 2018 wenchaoios. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface FSCalendarSeparatorDecorationView : UICollectionReusableView 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /FSCalendar/FSCalendarSeparatorDecorationView.m: -------------------------------------------------------------------------------- 1 | // 2 | // FSCalendarSeparatorDecorationView.m 3 | // FSCalendar 4 | // 5 | // Created by 丁文超 on 2018/10/10. 6 | // Copyright © 2018 wenchaoios. All rights reserved. 7 | // 8 | 9 | #import "FSCalendarSeparatorDecorationView.h" 10 | #import "FSCalendarConstants.h" 11 | 12 | @implementation FSCalendarSeparatorDecorationView 13 | 14 | - (instancetype)initWithFrame:(CGRect)frame 15 | { 16 | self = [super initWithFrame:frame]; 17 | if (self) { 18 | self.backgroundColor = FSCalendarStandardSeparatorColor; 19 | } 20 | return self; 21 | } 22 | 23 | - (void)applyLayoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes 24 | { 25 | self.frame = layoutAttributes.frame; 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /FSCalendar/FSCalendarStickyHeader.h: -------------------------------------------------------------------------------- 1 | // 2 | // FSCalendarStaticHeader.h 3 | // FSCalendar 4 | // 5 | // Created by dingwenchao on 9/17/15. 6 | // Copyright (c) 2015 Wenchao Ding. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class FSCalendar,FSCalendarAppearance; 12 | 13 | @interface FSCalendarStickyHeader : UICollectionReusableView 14 | 15 | @property (weak, nonatomic) FSCalendar *calendar; 16 | 17 | @property (weak, nonatomic) UILabel *titleLabel; 18 | 19 | @property (strong, nonatomic) NSDate *month; 20 | 21 | - (void)configureAppearance; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /FSCalendar/FSCalendarStickyHeader.m: -------------------------------------------------------------------------------- 1 | // 2 | // FSCalendarStaticHeader.m 3 | // FSCalendar 4 | // 5 | // Created by dingwenchao on 9/17/15. 6 | // Copyright (c) 2015 Wenchao Ding. All rights reserved. 7 | // 8 | 9 | #import "FSCalendarStickyHeader.h" 10 | #import "FSCalendar.h" 11 | #import "FSCalendarWeekdayView.h" 12 | #import "FSCalendarExtensions.h" 13 | #import "FSCalendarConstants.h" 14 | #import "FSCalendarDynamicHeader.h" 15 | 16 | @interface FSCalendarStickyHeader () 17 | 18 | @property (weak , nonatomic) UIView *contentView; 19 | @property (weak , nonatomic) UIView *bottomBorder; 20 | @property (weak , nonatomic) FSCalendarWeekdayView *weekdayView; 21 | 22 | @end 23 | 24 | @implementation FSCalendarStickyHeader 25 | 26 | - (instancetype)initWithFrame:(CGRect)frame 27 | { 28 | self = [super initWithFrame:frame]; 29 | if (self) { 30 | 31 | UIView *view; 32 | UILabel *label; 33 | 34 | view = [[UIView alloc] initWithFrame:CGRectZero]; 35 | view.backgroundColor = [UIColor clearColor]; 36 | [self addSubview:view]; 37 | self.contentView = view; 38 | 39 | label = [[UILabel alloc] initWithFrame:CGRectZero]; 40 | label.textAlignment = NSTextAlignmentCenter; 41 | label.numberOfLines = 0; 42 | [_contentView addSubview:label]; 43 | self.titleLabel = label; 44 | 45 | view = [[UIView alloc] initWithFrame:CGRectZero]; 46 | view.backgroundColor = FSCalendarStandardLineColor; 47 | [_contentView addSubview:view]; 48 | self.bottomBorder = view; 49 | 50 | FSCalendarWeekdayView *weekdayView = [[FSCalendarWeekdayView alloc] init]; 51 | [self.contentView addSubview:weekdayView]; 52 | self.weekdayView = weekdayView; 53 | } 54 | return self; 55 | } 56 | 57 | - (void)layoutSubviews 58 | { 59 | [super layoutSubviews]; 60 | 61 | _contentView.frame = self.bounds; 62 | 63 | CGFloat weekdayHeight = _calendar.preferredWeekdayHeight; 64 | CGFloat weekdayMargin = weekdayHeight * 0.1; 65 | CGFloat titleWidth = _contentView.fs_width; 66 | 67 | self.weekdayView.frame = CGRectMake(0, _contentView.fs_height-weekdayHeight-weekdayMargin, self.contentView.fs_width, weekdayHeight); 68 | 69 | CGFloat titleHeight = [@"1" sizeWithAttributes:@{NSFontAttributeName:self.calendar.appearance.headerTitleFont}].height*1.5 + weekdayMargin*3; 70 | 71 | _bottomBorder.frame = CGRectMake(0, _contentView.fs_height-weekdayHeight-weekdayMargin*2, _contentView.fs_width, 1.0); 72 | 73 | CGPoint titleHeaderOffset = self.calendar.appearance.headerTitleOffset; 74 | _titleLabel.frame = CGRectMake(titleHeaderOffset.x, 75 | titleHeaderOffset.y+_bottomBorder.fs_bottom-titleHeight-weekdayMargin, 76 | titleWidth, 77 | titleHeight); 78 | } 79 | 80 | #pragma mark - Properties 81 | 82 | - (void)setCalendar:(FSCalendar *)calendar 83 | { 84 | if (![_calendar isEqual:calendar]) { 85 | _calendar = calendar; 86 | _weekdayView.calendar = calendar; 87 | [self configureAppearance]; 88 | } 89 | } 90 | 91 | #pragma mark - Private methods 92 | 93 | - (void)configureAppearance 94 | { 95 | _titleLabel.font = self.calendar.appearance.headerTitleFont; 96 | _titleLabel.textColor = self.calendar.appearance.headerTitleColor; 97 | _titleLabel.textAlignment = self.calendar.appearance.headerTitleAlignment; 98 | _bottomBorder.backgroundColor = self.calendar.appearance.headerSeparatorColor; 99 | [self.weekdayView configureAppearance]; 100 | } 101 | 102 | - (void)setMonth:(NSDate *)month 103 | { 104 | _month = month; 105 | _calendar.formatter.dateFormat = self.calendar.appearance.headerDateFormat; 106 | BOOL usesUpperCase = (self.calendar.appearance.caseOptions & 15) == FSCalendarCaseOptionsHeaderUsesUpperCase; 107 | BOOL usesCapitalized = (self.calendar.appearance.caseOptions & 15) == FSCalendarCaseOptionsHeaderUsesCapitalized; 108 | 109 | NSString *text = [_calendar.formatter stringFromDate:_month]; 110 | if (usesUpperCase) { 111 | text = text.uppercaseString; 112 | } else if (usesCapitalized) { 113 | text = text.capitalizedString; 114 | } 115 | 116 | self.titleLabel.text = text; 117 | } 118 | 119 | @end 120 | 121 | 122 | -------------------------------------------------------------------------------- /FSCalendar/FSCalendarTransitionCoordinator.h: -------------------------------------------------------------------------------- 1 | // 2 | // FSCalendarTransitionCoordinator.h 3 | // FSCalendar 4 | // 5 | // Created by dingwenchao on 3/13/16. 6 | // Copyright © 2016 Wenchao Ding. All rights reserved. 7 | // 8 | 9 | #import "FSCalendar.h" 10 | #import "FSCalendarCollectionView.h" 11 | #import "FSCalendarCollectionViewLayout.h" 12 | 13 | typedef NS_ENUM(NSUInteger, FSCalendarTransitionState) { 14 | FSCalendarTransitionStateIdle, 15 | FSCalendarTransitionStateChanging, 16 | FSCalendarTransitionStateFinishing, 17 | }; 18 | 19 | @interface FSCalendarTransitionCoordinator : NSObject 20 | 21 | @property (assign, nonatomic) FSCalendarTransitionState state; 22 | 23 | @property (assign, nonatomic) CGSize cachedMonthSize; 24 | 25 | @property (readonly, nonatomic) FSCalendarScope representingScope; 26 | 27 | - (instancetype)initWithCalendar:(FSCalendar *)calendar; 28 | 29 | - (void)performScopeTransitionFromScope:(FSCalendarScope)fromScope toScope:(FSCalendarScope)toScope animated:(BOOL)animated; 30 | - (void)performBoundingRectTransitionFromMonth:(NSDate *)fromMonth toMonth:(NSDate *)toMonth duration:(CGFloat)duration; 31 | - (CGRect)boundingRectForScope:(FSCalendarScope)scope page:(NSDate *)page; 32 | 33 | - (void)handleScopeGesture:(id)sender; 34 | 35 | @end 36 | 37 | 38 | @interface FSCalendarTransitionAttributes : NSObject 39 | 40 | @property (assign, nonatomic) CGRect sourceBounds; 41 | @property (assign, nonatomic) CGRect targetBounds; 42 | @property (strong, nonatomic) NSDate *sourcePage; 43 | @property (strong, nonatomic) NSDate *targetPage; 44 | @property (assign, nonatomic) NSInteger focusedRow; 45 | @property (strong, nonatomic) NSDate *focusedDate; 46 | @property (assign, nonatomic) FSCalendarScope targetScope; 47 | 48 | - (void)revert; 49 | 50 | @end 51 | 52 | -------------------------------------------------------------------------------- /FSCalendar/FSCalendarWeekdayView.h: -------------------------------------------------------------------------------- 1 | // 2 | // FSCalendarWeekdayView.h 3 | // FSCalendar 4 | // 5 | // Created by dingwenchao on 03/11/2016. 6 | // Copyright © 2016 dingwenchao. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @class FSCalendar; 15 | 16 | @interface FSCalendarWeekdayView : UIView 17 | 18 | /** 19 | An array of UILabel objects displaying the weekday symbols. 20 | */ 21 | @property (readonly, nonatomic) NSArray *weekdayLabels; 22 | 23 | - (void)configureAppearance; 24 | 25 | @end 26 | 27 | NS_ASSUME_NONNULL_END 28 | -------------------------------------------------------------------------------- /FSCalendar/FSCalendarWeekdayView.m: -------------------------------------------------------------------------------- 1 | // 2 | // FSCalendarWeekdayView.m 3 | // FSCalendar 4 | // 5 | // Created by dingwenchao on 03/11/2016. 6 | // Copyright © 2016 Wenchao Ding. All rights reserved. 7 | // 8 | 9 | #import "FSCalendarWeekdayView.h" 10 | #import "FSCalendar.h" 11 | #import "FSCalendarDynamicHeader.h" 12 | #import "FSCalendarExtensions.h" 13 | 14 | @interface FSCalendarWeekdayView() 15 | 16 | @property (strong, nonatomic) NSPointerArray *weekdayPointers; 17 | @property (weak , nonatomic) UIView *contentView; 18 | @property (weak , nonatomic) FSCalendar *calendar; 19 | 20 | - (void)commonInit; 21 | 22 | @end 23 | 24 | @implementation FSCalendarWeekdayView 25 | 26 | - (instancetype)initWithFrame:(CGRect)frame 27 | { 28 | self = [super initWithFrame:frame]; 29 | if (self) { 30 | [self commonInit]; 31 | } 32 | return self; 33 | } 34 | 35 | - (instancetype)initWithCoder:(NSCoder *)coder 36 | { 37 | self = [super initWithCoder:coder]; 38 | if (self) { 39 | [self commonInit]; 40 | } 41 | return self; 42 | } 43 | 44 | - (void)commonInit 45 | { 46 | UIView *contentView = [[UIView alloc] initWithFrame:CGRectZero]; 47 | [self addSubview:contentView]; 48 | _contentView = contentView; 49 | 50 | _weekdayPointers = [NSPointerArray weakObjectsPointerArray]; 51 | for (int i = 0; i < 7; i++) { 52 | UILabel *weekdayLabel = [[UILabel alloc] initWithFrame:CGRectZero]; 53 | weekdayLabel.textAlignment = NSTextAlignmentCenter; 54 | [self.contentView addSubview:weekdayLabel]; 55 | [_weekdayPointers addPointer:(__bridge void * _Nullable)(weekdayLabel)]; 56 | } 57 | } 58 | 59 | - (void)layoutSubviews 60 | { 61 | [super layoutSubviews]; 62 | 63 | self.contentView.frame = self.bounds; 64 | 65 | // Position Calculation 66 | NSInteger count = self.weekdayPointers.count; 67 | size_t size = sizeof(CGFloat)*count; 68 | CGFloat *widths = malloc(size); 69 | CGFloat contentWidth = self.contentView.fs_width; 70 | FSCalendarSliceCake(contentWidth, count, widths); 71 | 72 | BOOL opposite = NO; 73 | if (@available(iOS 9.0, *)) { 74 | UIUserInterfaceLayoutDirection direction = [UIView userInterfaceLayoutDirectionForSemanticContentAttribute:self.calendar.semanticContentAttribute]; 75 | opposite = (direction == UIUserInterfaceLayoutDirectionRightToLeft); 76 | } 77 | CGFloat x = 0; 78 | for (NSInteger i = 0; i < count; i++) { 79 | CGFloat width = widths[i]; 80 | NSInteger labelIndex = opposite ? count-1-i : i; 81 | UILabel *label = [self.weekdayPointers pointerAtIndex:labelIndex]; 82 | label.frame = CGRectMake(x, 0, width, self.contentView.fs_height); 83 | x = CGRectGetMaxX(label.frame); 84 | } 85 | free(widths); 86 | } 87 | 88 | - (void)setCalendar:(FSCalendar *)calendar 89 | { 90 | _calendar = calendar; 91 | [self configureAppearance]; 92 | } 93 | 94 | - (NSArray *)weekdayLabels 95 | { 96 | return self.weekdayPointers.allObjects; 97 | } 98 | 99 | - (void)configureAppearance 100 | { 101 | BOOL useVeryShortWeekdaySymbols = (self.calendar.appearance.caseOptions & (15<<4) ) == FSCalendarCaseOptionsWeekdayUsesSingleUpperCase; 102 | NSArray *weekdaySymbols = useVeryShortWeekdaySymbols ? self.calendar.gregorian.veryShortStandaloneWeekdaySymbols : self.calendar.gregorian.shortStandaloneWeekdaySymbols; 103 | BOOL useDefaultWeekdayCase = (self.calendar.appearance.caseOptions & (15<<4) ) == FSCalendarCaseOptionsWeekdayUsesDefaultCase; 104 | 105 | for (NSInteger i = 0; i < self.weekdayPointers.count; i++) { 106 | NSInteger index = (i + self.calendar.firstWeekday-1) % 7; 107 | UILabel *label = [self.weekdayPointers pointerAtIndex:i]; 108 | label.font = self.calendar.appearance.weekdayFont; 109 | label.textColor = self.calendar.appearance.weekdayTextColor; 110 | label.text = useDefaultWeekdayCase ? weekdaySymbols[index] : [weekdaySymbols[index] uppercaseString]; 111 | } 112 | 113 | } 114 | 115 | @end 116 | -------------------------------------------------------------------------------- /FSCalendar/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | $(MARKETING_VERSION) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 282 23 | NSPrincipalClass 24 | 25 | net.goout.GoOut.groupIdentifier 26 | $(GROUP_IDENTIFIER) 27 | 28 | 29 | -------------------------------------------------------------------------------- /FSCalendar/include/FSCalendar.h: -------------------------------------------------------------------------------- 1 | ../FSCalendar.h -------------------------------------------------------------------------------- /FSCalendar/include/FSCalendarAppearance.h: -------------------------------------------------------------------------------- 1 | ../FSCalendarAppearance.h -------------------------------------------------------------------------------- /FSCalendar/include/FSCalendarCalculator.h: -------------------------------------------------------------------------------- 1 | ../FSCalendarCalculator.h -------------------------------------------------------------------------------- /FSCalendar/include/FSCalendarCell.h: -------------------------------------------------------------------------------- 1 | ../FSCalendarCell.h -------------------------------------------------------------------------------- /FSCalendar/include/FSCalendarCollectionView.h: -------------------------------------------------------------------------------- 1 | ../FSCalendarCollectionView.h -------------------------------------------------------------------------------- /FSCalendar/include/FSCalendarCollectionViewLayout.h: -------------------------------------------------------------------------------- 1 | ../FSCalendarCollectionViewLayout.h -------------------------------------------------------------------------------- /FSCalendar/include/FSCalendarConstants.h: -------------------------------------------------------------------------------- 1 | ../FSCalendarConstants.h -------------------------------------------------------------------------------- /FSCalendar/include/FSCalendarDelegationFactory.h: -------------------------------------------------------------------------------- 1 | ../FSCalendarDelegationFactory.h -------------------------------------------------------------------------------- /FSCalendar/include/FSCalendarDelegationProxy.h: -------------------------------------------------------------------------------- 1 | ../FSCalendarDelegationProxy.h -------------------------------------------------------------------------------- /FSCalendar/include/FSCalendarDynamicHeader.h: -------------------------------------------------------------------------------- 1 | ../FSCalendarDynamicHeader.h -------------------------------------------------------------------------------- /FSCalendar/include/FSCalendarExtensions.h: -------------------------------------------------------------------------------- 1 | ../FSCalendarExtensions.h -------------------------------------------------------------------------------- /FSCalendar/include/FSCalendarHeaderView.h: -------------------------------------------------------------------------------- 1 | ../FSCalendarHeaderView.h -------------------------------------------------------------------------------- /FSCalendar/include/FSCalendarSeparatorDecorationView.h: -------------------------------------------------------------------------------- 1 | ../FSCalendarSeparatorDecorationView.h -------------------------------------------------------------------------------- /FSCalendar/include/FSCalendarStickyHeader.h: -------------------------------------------------------------------------------- 1 | ../FSCalendarStickyHeader.h -------------------------------------------------------------------------------- /FSCalendar/include/FSCalendarTransitionCoordinator.h: -------------------------------------------------------------------------------- 1 | ../FSCalendarTransitionCoordinator.h -------------------------------------------------------------------------------- /FSCalendar/include/FSCalendarWeekdayView.h: -------------------------------------------------------------------------------- 1 | ../FSCalendarWeekdayView.h -------------------------------------------------------------------------------- /FSCalendar/include/module.modulemap: -------------------------------------------------------------------------------- 1 | module FSCalendar { 2 | header "FSCalendar.h" 3 | header "FSCalendarAppearance.h" 4 | header "FSCalendarCalculator.h" 5 | header "FSCalendarCell.h" 6 | header "FSCalendarCollectionView.h" 7 | header "FSCalendarCollectionViewLayout.h" 8 | header "FSCalendarConstants.h" 9 | header "FSCalendarDelegationFactory.h" 10 | header "FSCalendarDelegationProxy.h" 11 | header "FSCalendarDynamicHeader.h" 12 | header "FSCalendarExtensions.h" 13 | header "FSCalendarHeaderView.h" 14 | header "FSCalendarSeparatorDecorationView.h" 15 | header "FSCalendarStickyHeader.h" 16 | header "FSCalendarTransitionCoordinator.h" 17 | header "FSCalendarWeekdayView.h" 18 | 19 | export * 20 | } 21 | -------------------------------------------------------------------------------- /FSCalendarExamples.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /FSCalendarExamples.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013-2016 FSCalendar (https://github.com/WenchaoD/FSCalendar) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.3 2 | import PackageDescription 3 | 4 | let package = Package( 5 | name: "FSCalendar", 6 | platforms: [.iOS(.v9)], 7 | products: [ 8 | .library( 9 | name: "FSCalendar", 10 | targets: ["FSCalendar"] 11 | ), 12 | ], 13 | targets: [ 14 | .target( 15 | name: "FSCalendar", 16 | dependencies: [], 17 | path: "FSCalendar/", 18 | exclude: ["Info.plist"] 19 | ) 20 | ] 21 | ) 22 | --------------------------------------------------------------------------------