Multiple Selection

Use `allowsMultipleSelection` to enable this feature
This commit is contained in:
dingwenchao 2015-09-09 09:59:36 +08:00
parent a6b91c443a
commit 8bbc309c35
14 changed files with 287 additions and 99 deletions

View File

@ -33,6 +33,26 @@
<sections>
<tableViewSection id="OKx-qF-6aM">
<cells>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" textLabel="vsl-87-uJv" detailTextLabel="HDn-MC-Z72" style="IBUITableViewCellStyleValue1" id="9BE-p1-W4Y">
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="9BE-p1-W4Y" id="yDZ-FN-3hk">
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Multiple Selection Example" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="vsl-87-uJv">
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Feature!" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="HDn-MC-Z72">
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<color key="textColor" red="0.0" green="0.47843137250000001" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" textLabel="sRI-B1-vbS" style="IBUITableViewCellStyleDefault" id="hX9-bB-aHp">
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="hX9-bB-aHp" id="Mhd-Y2-O2b">

View File

@ -22,7 +22,6 @@
30B0BAD61B8D8E23004B9476 /* NSDate+FSExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = 30B0BACC1B8D8E22004B9476 /* NSDate+FSExtension.m */; };
30B0BAD71B8D8E23004B9476 /* UIView+FSExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = 30B0BACE1B8D8E22004B9476 /* UIView+FSExtension.m */; };
30B0BAF41B8D9AC1004B9476 /* FSCalendar+IBExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = 30B0BABE1B8D8E22004B9476 /* FSCalendar+IBExtension.m */; };
30B0BAF51B8D9AC1004B9476 /* FSCalendar.m in Sources */ = {isa = PBXBuildFile; fileRef = 30B0BAC01B8D8E22004B9476 /* FSCalendar.m */; };
30B0BAF61B8D9AC1004B9476 /* FSCalendarAppearance.m in Sources */ = {isa = PBXBuildFile; fileRef = 30B0BAC21B8D8E22004B9476 /* FSCalendarAppearance.m */; };
30B0BAF71B8D9AC1004B9476 /* FSCalendarCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 30B0BAC41B8D8E22004B9476 /* FSCalendarCell.m */; };
30B0BAF81B8D9AC1004B9476 /* FSCalendarHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 30B0BAC71B8D8E22004B9476 /* FSCalendarHeader.m */; };
@ -38,6 +37,8 @@
30B0BB051B8D9B6D004B9476 /* FSCalendarHeaderTouchDeliver.h in Headers */ = {isa = PBXBuildFile; fileRef = 30B0BAC81B8D8E22004B9476 /* FSCalendarHeaderTouchDeliver.h */; settings = {ATTRIBUTES = (Private, ); }; };
30B0BB061B8D9B6D004B9476 /* NSDate+FSExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = 30B0BACB1B8D8E22004B9476 /* NSDate+FSExtension.h */; settings = {ATTRIBUTES = (Private, ); }; };
30B0BB071B8D9B6D004B9476 /* UIView+FSExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = 30B0BACD1B8D8E22004B9476 /* UIView+FSExtension.h */; settings = {ATTRIBUTES = (Private, ); }; };
30F5D8561B9FC33400C1C201 /* FSCalendar.m in Sources */ = {isa = PBXBuildFile; fileRef = 30B0BAC01B8D8E22004B9476 /* FSCalendar.m */; };
30F5D85A1B9FC4BB00C1C201 /* MultipleSelectionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 30F5D8591B9FC4BB00C1C201 /* MultipleSelectionViewController.m */; };
EE52AE181B91E68A00016662 /* FSCalendarScopeExampleViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = EE52AE171B91E68A00016662 /* FSCalendarScopeExampleViewController.m */; };
EE638CB21B89DB450006DD1A /* LunarDateFormatter.strings in Resources */ = {isa = PBXBuildFile; fileRef = EE638C911B89DB450006DD1A /* LunarDateFormatter.strings */; };
EE638CB31B89DB450006DD1A /* libLunar.c in Sources */ = {isa = PBXBuildFile; fileRef = EE638C941B89DB450006DD1A /* libLunar.c */; };
@ -113,6 +114,8 @@
30B0BACC1B8D8E22004B9476 /* NSDate+FSExtension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDate+FSExtension.m"; sourceTree = "<group>"; };
30B0BACD1B8D8E22004B9476 /* UIView+FSExtension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+FSExtension.h"; sourceTree = "<group>"; };
30B0BACE1B8D8E22004B9476 /* UIView+FSExtension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+FSExtension.m"; sourceTree = "<group>"; };
30F5D8581B9FC4BB00C1C201 /* MultipleSelectionViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MultipleSelectionViewController.h; sourceTree = SOURCE_ROOT; };
30F5D8591B9FC4BB00C1C201 /* MultipleSelectionViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MultipleSelectionViewController.m; sourceTree = SOURCE_ROOT; };
EE0D7FC71B89C5D3003C287B /* FSCalendarExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FSCalendarExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
EE0D7FCB1B89C5D3003C287B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
EE52AE161B91E68A00016662 /* FSCalendarScopeExampleViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FSCalendarScopeExampleViewController.h; sourceTree = SOURCE_ROOT; };
@ -229,6 +232,15 @@
name = "Supporting Files";
sourceTree = "<group>";
};
30F5D8571B9FC48C00C1C201 /* MultipleSelection Example */ = {
isa = PBXGroup;
children = (
30F5D8581B9FC4BB00C1C201 /* MultipleSelectionViewController.h */,
30F5D8591B9FC4BB00C1C201 /* MultipleSelectionViewController.m */,
);
name = "MultipleSelection Example";
sourceTree = "<group>";
};
EE0D7FBE1B89C5D3003C287B = {
isa = PBXGroup;
children = (
@ -257,6 +269,7 @@
EE638CD01B89DBE90006DD1A /* AppDelegate.m */,
EE638CD11B89DBE90006DD1A /* FSTableViewController.h */,
EE638CD21B89DBE90006DD1A /* FSTableViewController.m */,
30F5D8571B9FC48C00C1C201 /* MultipleSelection Example */,
EE52AE151B91E65D00016662 /* FSCalendarScope Example */,
EE0D80241B89C868003C287B /* Storyboard Example */,
EE0D80231B89C853003C287B /* LoadView Example */,
@ -502,6 +515,7 @@
30B0BAD01B8D8E23004B9476 /* FSCalendar.m in Sources */,
EE638CD31B89DBE90006DD1A /* AppDelegate.m in Sources */,
3092253B1B905C4300123031 /* FSCalendarConstance.m in Sources */,
30F5D85A1B9FC4BB00C1C201 /* MultipleSelectionViewController.m in Sources */,
EE638CBC1B89DB450006DD1A /* SSHolidayWest.m in Sources */,
EE638CBB1B89DB450006DD1A /* SSHolidayUS.m in Sources */,
30B0BAD21B8D8E23004B9476 /* FSCalendarCell.m in Sources */,
@ -533,15 +547,15 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
30F5D8561B9FC33400C1C201 /* FSCalendar.m in Sources */,
30B0BAF41B8D9AC1004B9476 /* FSCalendar+IBExtension.m in Sources */,
30B0BAF51B8D9AC1004B9476 /* FSCalendar.m in Sources */,
EE89AFA01B9162B90001B657 /* NSString+FSExtension.m in Sources */,
30B0BAF61B8D9AC1004B9476 /* FSCalendarAppearance.m in Sources */,
30B0BAF71B8D9AC1004B9476 /* FSCalendarCell.m in Sources */,
30B0BAF81B8D9AC1004B9476 /* FSCalendarHeader.m in Sources */,
30B0BAF91B8D9AC1004B9476 /* FSCalendarHeaderTouchDeliver.m in Sources */,
3092253C1B905C4300123031 /* FSCalendarConstance.m in Sources */,
30B0BAFA1B8D9AC1004B9476 /* NSDate+FSExtension.m in Sources */,
EE89AFA01B9162B90001B657 /* NSString+FSExtension.m in Sources */,
30B0BAFB1B8D9AC1004B9476 /* UIView+FSExtension.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;

View File

@ -7,6 +7,7 @@
//
#import "FSCalendarScopeExampleViewController.h"
#import "NSDate+FSExtension.h"
@implementation FSCalendarScopeExampleViewController
@ -23,6 +24,18 @@
[self.view layoutIfNeeded];
}
- (void)calendar:(FSCalendar *)calendar didSelectDate:(NSDate *)date
{
NSLog(@"did select date %@",[date fs_stringWithFormat:@"yyyy/MM/dd"]);
NSMutableArray *selectedDates = [NSMutableArray arrayWithCapacity:calendar.selectedDates.count];
[calendar.selectedDates enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[selectedDates addObject:[obj fs_stringWithFormat:@"yyyy/MM/dd"]];
}];
NSLog(@"selected dates is %@",selectedDates);
}
#pragma mark - <UITableViewDataSource>
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

View File

@ -9,6 +9,7 @@
#import "FSTableViewController.h"
#import "LoadViewExampleViewController.h"
#import "ViewDidLoadExampleViewController.h"
#import "MultipleSelectionViewController.h"
@implementation FSTableViewController
@ -22,24 +23,25 @@
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 0) {
MultipleSelectionViewController *viewController = [[MultipleSelectionViewController alloc] init];
[self.navigationController pushViewController:viewController animated:YES];
} else if (indexPath.row == 1) {
// FSCalendarScope Example
return;
} else if (indexPath.row == 1) {
} else if (indexPath.row == 2) {
// Storyboard Example
return;
} else if (indexPath.row == 2) {
} else if (indexPath.row == 3) {
// LoadView Example
LoadViewExampleViewController *viewController = [[LoadViewExampleViewController alloc] init];
viewController.title = @"FSCalendar";
[self.navigationController pushViewController:viewController animated:YES];
} else if (indexPath.row == 3) {
} else if (indexPath.row == 4) {
// ViewDidLoad Example
ViewDidLoadExampleViewController *viewController = [[ViewDidLoadExampleViewController alloc] init];
viewController.title = @"FSCalendar";
[self.navigationController pushViewController:viewController animated:YES];
}
}

View File

@ -16,6 +16,15 @@
NSLog(@"%@:%s", self.class.description, __FUNCTION__);
}
- (instancetype)init
{
self = [super init];
if (self) {
self.title = @"FSCalendar";
}
return self;
}
- (void)loadView
{
UIView *view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
@ -26,7 +35,7 @@
calendar.dataSource = self;
calendar.delegate = self;
calendar.scrollDirection = FSCalendarScrollDirectionVertical;
calendar.selectedDate = [NSDate fs_dateWithYear:2015 month:2 day:1];
[calendar selectDate:[NSDate fs_dateWithYear:2015 month:2 day:1]];
[view addSubview:calendar];
self.calendar = calendar;
}

View File

@ -0,0 +1,17 @@
//
// MultipleSelectionViewController.h
// FSCalendar
//
// Created by dingwenchao on 9/9/15.
// Copyright (c) 2015 wenchaoios. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "FSCalendar.h"
#import "NSDate+FSExtension.h"
@interface MultipleSelectionViewController : UIViewController <FSCalendarDataSource,FSCalendarDelegate>
@property (weak, nonatomic) FSCalendar *calendar;
@end

View File

@ -0,0 +1,47 @@
//
// MultipleSelectionViewController.m
// FSCalendar
//
// Created by dingwenchao on 9/9/15.
// Copyright (c) 2015 wenchaoios. All rights reserved.
//
#import "MultipleSelectionViewController.h"
@implementation MultipleSelectionViewController
- (instancetype)init
{
self = [super init];
if (self) {
self.title = @"FSCalendar";
}
return self;
}
- (void)loadView
{
UIView *view = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds];
view.backgroundColor = [UIColor colorWithRed:0.95 green:0.95 blue:0.95 alpha:1.0];
self.view = view;
FSCalendar *calendar = [[FSCalendar alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(self.navigationController.navigationBar.frame), view.bounds.size.width, 300)];
calendar.dataSource = self;
calendar.delegate = self;
calendar.backgroundColor = [UIColor whiteColor];
calendar.allowsMultipleSelection = YES;
[self.view addSubview:calendar];
self.calendar = calendar;
}
- (void)calendar:(FSCalendar *)calendar didSelectDate:(NSDate *)date
{
NSMutableArray *selectedDates = [NSMutableArray arrayWithCapacity:calendar.selectedDates.count];
[calendar.selectedDates enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[selectedDates addObject:[obj fs_stringWithFormat:@"yyyy/MM/dd"]];
}];
NSLog(@"selected dates is %@",selectedDates);
}
@end

View File

@ -99,6 +99,7 @@
- (void)calendar:(FSCalendar *)calendar didSelectDate:(NSDate *)date
{
NSLog(@"did select date %@",[date fs_stringWithFormat:@"yyyy/MM/dd"]);
}
- (void)calendarCurrentMonthDidChange:(FSCalendar *)calendar
@ -192,7 +193,7 @@
- (void)setSelectedDate:(NSDate *)selectedDate
{
_calendar.selectedDate = selectedDate;
[_calendar selectDate:selectedDate];
}
- (void)setFirstWeekday:(NSUInteger)firstWeekday

View File

@ -16,6 +16,15 @@
NSLog(@"%@:%s", self.class.description, __FUNCTION__);
}
- (instancetype)init
{
self = [super init];
if (self) {
self.title = @"FSCalendar";
}
return self;
}
- (void)loadView
{
UIView *view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
@ -30,8 +39,7 @@
FSCalendar *calendar = [[FSCalendar alloc] initWithFrame:CGRectMake(0, 64, self.view.frame.size.width, 300)];
calendar.dataSource = self;
calendar.delegate = self;
// calendar.flow = FSCalendarFlowVertical;
calendar.selectedDate = [NSDate fs_dateWithYear:2015 month:2 day:1];
[calendar selectDate:[NSDate fs_dateWithYear:2015 month:2 day:1]];
[self.view addSubview:calendar];
self.calendar = calendar;

View File

@ -1,10 +1,10 @@
Pod::Spec.new do |s|
s.name = "FSCalendar"
s.version = "1.1.4"
s.summary = "A powerful calendar which supports Appearance, Infinite Scrolling and Subtitle"
s.version = "1.2.0"
s.summary = "The fastest, most beautiful and most convenient calendar control, https://www.cocoacontrols.com/controls/fscalendar"
s.homepage = "https://github.com/f33chobits/FSCalendar"
s.homepage = "https://github.com/WenchaoIOS/FSCalendar"
s.screenshots = "https://cloud.githubusercontent.com/assets/5186464/6655324/213a814a-cb36-11e4-9add-f80515a83291.png","https://cloud.githubusercontent.com/assets/5186464/6652191/f11d5242-caa1-11e4-9cc2-8a7c0cc9ef02.gif","https://cloud.githubusercontent.com/assets/5186464/6652193/19e7f92a-caa2-11e4-92af-0639dc0c2d79.gif","https://cloud.githubusercontent.com/assets/5186464/6680012/4af05080-cc8c-11e4-863a-59cd3507192d.gif"
s.license = 'MIT'
s.author = { "Wenchao Ding" => "f33chobits@gmail.com" }

View File

@ -9,6 +9,8 @@
#import <UIKit/UIKit.h>
#import "FSCalendarAppearance.h"
#define FSCalendarDeprecated(message) __attribute((deprecated(message)))
//! Project version number for FSCalendar.
FOUNDATION_EXPORT double FSCalendarVersionNumber;
@ -17,7 +19,7 @@ FOUNDATION_EXPORT const unsigned char FSCalendarVersionString[];
@class FSCalendar;
__attribute((deprecated("use \'FSCalendarScrollDirection\' instead")))
FSCalendarDeprecated("use \'FSCalendarScrollDirection\' instead")
typedef NS_ENUM(NSInteger, FSCalendarFlow) {
FSCalendarFlowVertical,
FSCalendarFlowHorizontal
@ -50,7 +52,7 @@ typedef NS_ENUM(NSInteger, FSCalendarCellState) {
- (void)calendarCurrentPageDidChange:(FSCalendar *)calendar;
- (void)calendarCurrentScopeWillChange:(FSCalendar *)calendar animated:(BOOL)animated;
- (void)calendarCurrentMonthDidChange:(FSCalendar *)calendar __attribute((deprecated("use \'calendarCurrentPageDidChange\' instead")));
- (void)calendarCurrentMonthDidChange:(FSCalendar *)calendar FSCalendarDeprecated("use \'calendarCurrentPageDidChange\' instead");
@end
@ -72,7 +74,6 @@ IB_DESIGNABLE
@property (weak, nonatomic) IBOutlet id<FSCalendarDataSource> dataSource;
@property (strong, nonatomic) NSDate *today;
@property (strong, nonatomic) NSDate *selectedDate;
@property (strong, nonatomic) NSDate *currentPage;
@property (strong, nonatomic) NSLocale *locale;
@ -80,24 +81,33 @@ IB_DESIGNABLE
@property (assign, nonatomic) FSCalendarScope scope;
@property (assign, nonatomic) IBInspectable NSUInteger firstWeekday;
@property (assign, nonatomic) IBInspectable CGFloat headerHeight;
@property (assign, nonatomic) IBInspectable BOOL allowsMultipleSelection;
@property (readonly, nonatomic) FSCalendarAppearance *appearance;
@property (readonly, nonatomic) NSDate *minimumDate;
@property (readonly, nonatomic) NSDate *maximumDate;
@property (readonly, nonatomic) NSDate *selectedDate;
@property (readonly, nonatomic) NSArray *selectedDates;
- (void)reloadData;
- (CGSize)sizeThatFits:(CGSize)size;
- (void)setSelectedDate:(NSDate *)selectedDate animate:(BOOL)animate;
- (void)setScope:(FSCalendarScope)scope animated:(BOOL)animated;
- (void)selectDate:(NSDate *)date;
- (void)selectDate:(NSDate *)date scrollToDate:(BOOL)scrollToDate;
@end
@interface FSCalendar (Deprecated)
@property (strong, nonatomic) NSDate *currentMonth __attribute((deprecated("use \'currentPage\' instead")));
@property (assign, nonatomic) FSCalendarFlow flow __attribute((deprecated("use \'scrollDirection\' instead")));
@property (strong, nonatomic) NSDate *currentMonth FSCalendarDeprecated("use \'currentPage\' instead");
@property (assign, nonatomic) FSCalendarFlow flow FSCalendarDeprecated("use \'scrollDirection\' instead");
- (void)setSelectedDate:(NSDate *)selectedDate FSCalendarDeprecated("use \'selectDate:\' instead");
- (void)setSelectedDate:(NSDate *)selectedDate animate:(BOOL)animate FSCalendarDeprecated("use \'selectDate:scrollToDate:\' instead");
@end

View File

@ -15,6 +15,7 @@
#import "NSString+FSExtension.h"
#import "FSCalendarDynamicHeader.h"
#import "FSCalendarHeaderTouchDeliver.h"
#import "FSCalendarConstance.h"
static BOOL FSCalendarInInterfaceBuilder = NO;
@ -36,6 +37,7 @@ static BOOL FSCalendarInInterfaceBuilder = NO;
@interface FSCalendar ()<UICollectionViewDataSource, UICollectionViewDelegate>
{
FSCalendarAppearance *_appearance;
NSMutableArray *_selectedDates;
NSDate *_minimumDate;
NSDate *_maximumDate;
}
@ -58,6 +60,7 @@ static BOOL FSCalendarInInterfaceBuilder = NO;
@property (assign, nonatomic) BOOL needsAdjustingMonthPosition;
@property (assign, nonatomic) BOOL needsAdjustingViewFrame;
@property (assign, nonatomic) BOOL needsAdjustingTextSize;
@property (assign, nonatomic) BOOL needsReloadingSelectingDates;
@property (assign, nonatomic) BOOL supressEvent;
@property (readonly, nonatomic) NSInteger currentSection;
@ -73,7 +76,7 @@ static BOOL FSCalendarInInterfaceBuilder = NO;
- (BOOL)isDateInRange:(NSDate *)date;
- (void)setSelectedDate:(NSDate *)selectedDate animate:(BOOL)animate forPlaceholder:(BOOL)forPlaceholder;
- (void)selectDate:(NSDate *)date scrollToDate:(BOOL)scrollToDate forPlaceholder:(BOOL)forPlaceholder;
- (void)adjustRowHeight;
@ -81,7 +84,7 @@ static BOOL FSCalendarInInterfaceBuilder = NO;
@implementation FSCalendar
@dynamic locale;
@dynamic locale, selectedDate;
@synthesize scrollDirection = _scrollDirection, firstWeekday = _firstWeekday;
#pragma mark - Life Cycle && Initialize
@ -119,6 +122,7 @@ static BOOL FSCalendarInInterfaceBuilder = NO;
_scrollDirection = FSCalendarScrollDirectionHorizontal;
_firstWeekday = [_calendar firstWeekday];
_scope = FSCalendarScopeMonth;
_selectedDates = [NSMutableArray array];
_rowHeight = -1;
@ -186,12 +190,12 @@ static BOOL FSCalendarInInterfaceBuilder = NO;
collectionView.delaysContentTouches = NO;
collectionView.canCancelContentTouches = YES;
collectionView.scrollsToTop = NO;
collectionView.allowsMultipleSelection = NO;
[collectionView registerClass:[FSCalendarCell class] forCellWithReuseIdentifier:@"cell"];
[daysContainer addSubview:collectionView];
self.collectionView = collectionView;
self.collectionViewLayout = collectionViewLayout;
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
view.backgroundColor = [[UIColor lightGrayColor] colorWithAlphaComponent:0.25];
[self addSubview:view];
@ -272,6 +276,13 @@ static BOOL FSCalendarInInterfaceBuilder = NO;
[_appearance adjustTitleIfNecessary];
}
if (_needsReloadingSelectingDates) {
_needsReloadingSelectingDates = NO;
[self.selectedDates enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[self selectDate:obj scrollToDate:NO];
}];
}
if (_needsAdjustingMonthPosition) {
_needsAdjustingMonthPosition = NO;
[self scrollToDate:_currentPage];
@ -311,7 +322,7 @@ static BOOL FSCalendarInInterfaceBuilder = NO;
{
FSCalendarInInterfaceBuilder = YES;
NSDate *date = [NSDate date];
self.selectedDate = [NSDate fs_dateWithYear:date.fs_year month:date.fs_month day:_appearance.fakedSelectedDay?:1];
[self selectDate:[NSDate fs_dateWithYear:date.fs_year month:date.fs_month day:_appearance.fakedSelectedDay?:1]];
}
- (CGSize)sizeThatFits:(CGSize)size
@ -375,8 +386,9 @@ static BOOL FSCalendarInInterfaceBuilder = NO;
cell.image = [self imageForDate:cell.date];
cell.subtitle = [self subtitleForDate:cell.date];
cell.hasEvent = [self hasEventForDate:cell.date];
cell.dateIsSelected = [cell.date fs_isEqualToDateForDay:_selectedDate];
cell.dateIsSelected = [self.selectedDates containsObject:cell.date];
cell.dateIsToday = [cell.date fs_isEqualToDateForDay:_today];
cell.selected &= cell.dateIsSelected&&!cell.dateIsPlaceholder;
switch (_scope) {
case FSCalendarScopeMonth: {
NSDate *month = [_minimumDate.fs_firstDayOfMonth fs_dateByAddingMonths:indexPath.section].fs_dateByIgnoringTimeComponents;
@ -399,25 +411,24 @@ static BOOL FSCalendarInInterfaceBuilder = NO;
{
FSCalendarCell *cell = (FSCalendarCell *)[collectionView cellForItemAtIndexPath:indexPath];
if (cell.dateIsPlaceholder) {
[self setSelectedDate:cell.date animate:YES forPlaceholder:YES];
return;
[self selectDate:cell.date scrollToDate:YES forPlaceholder:YES];
} else {
_daysContainer.clipsToBounds = NO;
[cell performSelecting];
_selectedDate = [self dateForIndexPath:indexPath];
if (!_supressEvent) {
[self didSelectDate:_selectedDate];
[self didSelectDate:[self dateForIndexPath:indexPath]];
}
[collectionView.visibleCells enumerateObjectsUsingBlock:^(FSCalendarCell *cell, NSUInteger idx, BOOL *stop) {
if (cell.dateIsPlaceholder) {
cell.dateIsSelected = [self.selectedDates containsObject:cell.date];
cell.dateIsToday = [cell.date fs_isEqualToDateForDay:_today];
[cell setNeedsLayout];
}
}];
}
// CollectionViewplaceholder''
// There is no stored 'selection' state for placeholder cell, so the 'simulated selection' state needs to be recalculated.
[collectionView.visibleCells enumerateObjectsUsingBlock:^(FSCalendarCell *cell, NSUInteger idx, BOOL *stop) {
if (cell.dateIsPlaceholder) {
cell.dateIsSelected = [cell.date fs_isEqualToDateForDay:_selectedDate];
cell.dateIsToday = [cell.date fs_isEqualToDateForDay:_today];
[cell setNeedsLayout];
}
}];
}
@ -426,14 +437,14 @@ static BOOL FSCalendarInInterfaceBuilder = NO;
FSCalendarCell *cell = (FSCalendarCell *)[collectionView cellForItemAtIndexPath:indexPath];
if (cell.dateIsPlaceholder) {
if ([self isDateInRange:cell.date]) {
[self setSelectedDate:cell.date animate:YES forPlaceholder:YES];
[self selectDate:cell.date scrollToDate:YES forPlaceholder:YES];
} else if (![cell.date fs_isEqualToDateForMonth:_currentPage]) {
[self scrollToPageForDate:cell.date animated:YES];
}
return NO;
}
if ([collectionView.indexPathsForSelectedItems containsObject:indexPath]) {
[self didSelectDate:_selectedDate];
[self didSelectDate:self.selectedDate];
return NO;
}
BOOL shouldSelect = YES;
@ -448,6 +459,7 @@ static BOOL FSCalendarInInterfaceBuilder = NO;
FSCalendarCell *cell = (FSCalendarCell *)[collectionView cellForItemAtIndexPath:indexPath];
_daysContainer.clipsToBounds = NO;
[cell performDeselecting];
[_selectedDates removeObject:cell.date];
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
@ -583,44 +595,6 @@ static BOOL FSCalendarInInterfaceBuilder = NO;
}
}
- (void)setSelectedDate:(NSDate *)selectedDate
{
[self setSelectedDate:selectedDate animate:NO];
}
- (void)setSelectedDate:(NSDate *)selectedDate animate:(BOOL)animate forPlaceholder:(BOOL)forPlaceholder
{
if (![self isDateInRange:selectedDate]) {
[NSException raise:@"selectedDate out of range" format:nil];
}
NSDate *targetDate = selectedDate;
targetDate = [selectedDate fs_daysFrom:_minimumDate] < 0 ? _minimumDate.copy : selectedDate;
targetDate = [selectedDate fs_daysFrom:_maximumDate] > 0 ? _maximumDate.copy : selectedDate;
targetDate = selectedDate.fs_dateByIgnoringTimeComponents;
NSIndexPath *selectedIndexPath = [self indexPathForDate:targetDate];
BOOL shouldSelect = YES;
if (forPlaceholder) {
shouldSelect &= !_supressEvent;
shouldSelect &= [self shouldSelectDate:targetDate];
if (!shouldSelect) return;
} else {
shouldSelect = [self collectionView:_collectionView shouldSelectItemAtIndexPath:selectedIndexPath];
}
if (shouldSelect) {
if (_collectionView.indexPathsForSelectedItems.count && _selectedDate) {
NSIndexPath *currentIndexPath = [self indexPathForDate:_selectedDate];
[_collectionView deselectItemAtIndexPath:currentIndexPath animated:YES];
[self collectionView:_collectionView didDeselectItemAtIndexPath:currentIndexPath];
}
[_collectionView selectItemAtIndexPath:selectedIndexPath animated:NO scrollPosition:UICollectionViewScrollPositionNone];
[self collectionView:_collectionView didSelectItemAtIndexPath:selectedIndexPath];
}
[self scrollToPageForDate:targetDate animated:animate];
}
- (void)setToday:(NSDate *)today
{
if (![self isDateInRange:today]) {
@ -721,6 +695,26 @@ static BOOL FSCalendarInInterfaceBuilder = NO;
return 0;
}
- (void)setAllowsMultipleSelection:(BOOL)allowsMultipleSelection
{
_collectionView.allowsMultipleSelection = allowsMultipleSelection;
}
- (BOOL)allowsMultipleSelection
{
return _collectionView.allowsMultipleSelection;
}
- (NSDate *)selectedDate
{
return self.selectedDates.lastObject;
}
- (NSArray *)selectedDates
{
return _selectedDates;
}
#pragma mark - Public
- (void)reloadData
@ -746,22 +740,11 @@ static BOOL FSCalendarInInterfaceBuilder = NO;
width,
height);
}];
_needsReloadingSelectingDates = YES;
[_collectionView reloadData];
if (_selectedDate) {
_supressEvent = YES;
NSIndexPath *selectedIndexPath = [self indexPathForDate:_selectedDate];
[_collectionView selectItemAtIndexPath:selectedIndexPath animated:NO scrollPosition:UICollectionViewScrollPositionNone];
[self collectionView:_collectionView didSelectItemAtIndexPath:selectedIndexPath];
_supressEvent = NO;
}
[_header reloadData];
}
- (void)setSelectedDate:(NSDate *)selectedDate animate:(BOOL)animate
{
[self setSelectedDate:selectedDate animate:animate forPlaceholder:NO];
}
- (void)setScope:(FSCalendarScope)scope animated:(BOOL)animated
{
if (_scope != scope) {
@ -918,6 +901,51 @@ static BOOL FSCalendarInInterfaceBuilder = NO;
}
}
- (void)selectDate:(NSDate *)date
{
[self selectDate:date scrollToDate:YES];
}
- (void)selectDate:(NSDate *)date scrollToDate:(BOOL)scrollToDate
{
[self selectDate:date scrollToDate:scrollToDate forPlaceholder:NO];
}
- (void)selectDate:(NSDate *)date scrollToDate:(BOOL)scrollToDate forPlaceholder:(BOOL)forPlaceholder
{
if (![self isDateInRange:date]) {
[NSException raise:@"selectedDate out of range" format:nil];
}
NSDate *targetDate = date;
targetDate = [date fs_daysFrom:_minimumDate] < 0 ? _minimumDate.copy : date;
targetDate = [date fs_daysFrom:_maximumDate] > 0 ? _maximumDate.copy : date;
targetDate = date.fs_dateByIgnoringTimeComponents;
NSIndexPath *selectedIndexPath = [self indexPathForDate:targetDate];
BOOL shouldSelect = YES;
if (forPlaceholder) {
shouldSelect &= !_supressEvent;
shouldSelect &= [self shouldSelectDate:targetDate];
if (!shouldSelect) return;
} else {
shouldSelect = [self collectionView:_collectionView shouldSelectItemAtIndexPath:selectedIndexPath];
}
if (shouldSelect) {
if (_collectionView.indexPathsForSelectedItems.count && self.selectedDate && !self.allowsMultipleSelection) {
NSIndexPath *currentIndexPath = [self indexPathForDate:self.selectedDate];
[_collectionView deselectItemAtIndexPath:currentIndexPath animated:YES];
[self collectionView:_collectionView didDeselectItemAtIndexPath:currentIndexPath];
}
[_collectionView selectItemAtIndexPath:selectedIndexPath animated:NO scrollPosition:UICollectionViewScrollPositionNone];
[self collectionView:_collectionView didSelectItemAtIndexPath:selectedIndexPath];
}
if (scrollToDate) {
[self scrollToPageForDate:targetDate animated:YES];
}
}
#pragma mark - Private methods
- (void)scrollToDate:(NSDate *)date
@ -1104,6 +1132,12 @@ static BOOL FSCalendarInInterfaceBuilder = NO;
- (void)didSelectDate:(NSDate *)date
{
if (![_selectedDates containsObject:date]) {
[_selectedDates addObject:date];
}
[_selectedDates sortUsingComparator:^NSComparisonResult(NSDate *d1, NSDate *d2) {
return [d1 compare:d2] == NSOrderedDescending;
}];
if (_delegate && [_delegate respondsToSelector:@selector(calendar:didSelectDate:)]) {
[_delegate calendar:self didSelectDate:date];
}
@ -1195,6 +1229,16 @@ static BOOL FSCalendarInInterfaceBuilder = NO;
return (FSCalendarFlow)self.scrollDirection;
}
- (void)setSelectedDate:(NSDate *)selectedDate
{
[self selectDate:selectedDate];
}
- (void)setSelectedDate:(NSDate *)selectedDate animate:(BOOL)animate
{
[self selectDate:selectedDate scrollToDate:animate];
}
@end

View File

@ -89,11 +89,6 @@
[CATransaction setDisableActions:YES];
}
- (BOOL)isSelected
{
return [super isSelected] || (_dateIsSelected && !_deselecting);
}
#pragma mark - Public
- (void)performSelecting
@ -154,7 +149,7 @@
_titleLabel.frame = CGRectMake(0, 0, self.fs_width, floor(self.contentView.fs_height*5.0/6.0));
_subtitleLabel.hidden = YES;
}
_backgroundLayer.hidden = !self.selected && !self.dateIsToday;
_backgroundLayer.hidden = !self.selected && !self.dateIsToday && !self.dateIsSelected;
_backgroundLayer.path = _appearance.cellStyle == FSCalendarCellStyleCircle ?
[UIBezierPath bezierPathWithOvalInRect:_backgroundLayer.bounds].CGPath :
[UIBezierPath bezierPathWithRect:_backgroundLayer.bounds].CGPath;
@ -178,7 +173,7 @@
- (UIColor *)colorForCurrentStateInDictionary:(NSDictionary *)dictionary
{
if (self.isSelected) {
if (self.isSelected || (self.dateIsSelected && !_deselecting)) {
if (self.dateIsToday) {
return dictionary[@(FSCalendarCellStateSelected|FSCalendarCellStateToday)] ?: dictionary[@(FSCalendarCellStateSelected)];
}

View File

@ -49,7 +49,7 @@ Only the methods marked "👍" support IBInspectable / IBDesignable feature. [Ha
4. Finally, you should implement `FSCalendarDataSource` and `FSCalendarDelegate` in ViewController.m
## Code
## Or use code
```objective-c
@property (weak , nonatomic) FSCalendar *calendar;
@ -145,6 +145,14 @@ calendar.scope = .Month
![fscalendarscope](https://cloud.githubusercontent.com/assets/5186464/9562222/b0318d40-4e98-11e5-97dc-1694cbd26a74.gif)
### To select more than one date
```objective-c
_calendar.allowsMultipleSelection = YES;
```
![fscalendar-mulipleselection](https://cloud.githubusercontent.com/assets/5186464/9751497/368f55f6-56d8-11e5-9af5-0d09ba13f0eb.png)
### If you want `FSCalendar` to use `Monday` as the first column (or any other weekday)
```objective-c