diff --git a/CalendarDateRangePickerViewController/Classes/CalendarDateRangePickerCell.swift b/CalendarDateRangePickerViewController/Classes/CalendarDateRangePickerCell.swift index b0b64cd..c6147b4 100644 --- a/CalendarDateRangePickerViewController/Classes/CalendarDateRangePickerCell.swift +++ b/CalendarDateRangePickerViewController/Classes/CalendarDateRangePickerCell.swift @@ -11,17 +11,25 @@ import UIKit class CalendarDateRangePickerCell: UICollectionViewCell { private let defaultTextColor = UIColor.darkGray - private let highlightedColor = UIColor(white: 0.9, alpha: 1.0) + var highlightedColor = UIColor(white: 0.9, alpha: 1.0) private let disabledColor = UIColor.lightGray + var font = UIFont(name: "HelveticaNeue", size: CalendarDateRangePickerViewController.defaultCellFontSize) { + didSet { + label?.font = font + } + } - var selectedColor: UIColor! - - var date: Date? - var selectedView: UIView? - var halfBackgroundView: UIView? - var roundHighlightView: UIView? + @objc var selectedColor: UIColor! + @objc var selectedLabelColor: UIColor! + @objc var highlightedLabelColor: UIColor! + @objc var disabledDates: [Date]! + @objc var disabledTimestampDates: [Int]? + @objc var date: Date? + @objc var selectedView: UIView? + @objc var halfBackgroundView: UIView? + @objc var roundHighlightView: UIView? - var label: UILabel! + @objc var label: UILabel! override init(frame: CGRect) { super.init(frame: frame) @@ -33,16 +41,16 @@ class CalendarDateRangePickerCell: UICollectionViewCell { initLabel() } - func initLabel() { + @objc func initLabel() { label = UILabel(frame: frame) label.center = CGPoint(x: frame.size.width / 2, y: frame.size.height / 2) - label.font = UIFont(name: "HelveticaNeue", size: 15.0) + label.font = font label.textColor = UIColor.darkGray label.textAlignment = NSTextAlignment.center self.addSubview(label) } - func reset() { + @objc func reset() { self.backgroundColor = UIColor.clear label.textColor = defaultTextColor label.backgroundColor = UIColor.clear @@ -60,7 +68,7 @@ class CalendarDateRangePickerCell: UICollectionViewCell { } } - func select() { + @objc func select() { let width = self.frame.size.width let height = self.frame.size.height selectedView = UIView(frame: CGRect(x: (width - height) / 2, y: 0, width: height, height: height)) @@ -69,10 +77,10 @@ class CalendarDateRangePickerCell: UICollectionViewCell { self.addSubview(selectedView!) self.sendSubview(toBack: selectedView!) - label.textColor = UIColor.white + label.textColor = selectedLabelColor } - func highlightRight() { + @objc func highlightRight() { // This is used instead of highlight() when we need to highlight cell with a rounded edge on the left let width = self.frame.size.width let height = self.frame.size.height @@ -80,11 +88,11 @@ class CalendarDateRangePickerCell: UICollectionViewCell { halfBackgroundView?.backgroundColor = highlightedColor self.addSubview(halfBackgroundView!) self.sendSubview(toBack: halfBackgroundView!) - + label.textColor = highlightedLabelColor addRoundHighlightView() } - func highlightLeft() { + @objc func highlightLeft() { // This is used instead of highlight() when we need to highlight the cell with a rounded edge on the right let width = self.frame.size.width let height = self.frame.size.height @@ -92,11 +100,12 @@ class CalendarDateRangePickerCell: UICollectionViewCell { halfBackgroundView?.backgroundColor = highlightedColor self.addSubview(halfBackgroundView!) self.sendSubview(toBack: halfBackgroundView!) - + label.textColor = highlightedLabelColor + addRoundHighlightView() } - func addRoundHighlightView() { + @objc func addRoundHighlightView() { let width = self.frame.size.width let height = self.frame.size.height roundHighlightView = UIView(frame: CGRect(x: (width - height) / 2, y: 0, width: height, height: height)) @@ -106,12 +115,15 @@ class CalendarDateRangePickerCell: UICollectionViewCell { self.sendSubview(toBack: roundHighlightView!) } - func highlight() { + @objc func highlight() { self.backgroundColor = highlightedColor + label.textColor = highlightedLabelColor + } - func disable() { + @objc func disable() { label.textColor = disabledColor + } } diff --git a/CalendarDateRangePickerViewController/Classes/CalendarDateRangePickerHeaderView.swift b/CalendarDateRangePickerViewController/Classes/CalendarDateRangePickerHeaderView.swift index c5d3b4e..f14cd4d 100644 --- a/CalendarDateRangePickerViewController/Classes/CalendarDateRangePickerHeaderView.swift +++ b/CalendarDateRangePickerViewController/Classes/CalendarDateRangePickerHeaderView.swift @@ -10,7 +10,12 @@ import UIKit class CalendarDateRangePickerHeaderView: UICollectionReusableView { - var label: UILabel! + @objc var label: UILabel! + @objc var font = UIFont(name: "HelveticaNeue-Light", size: CalendarDateRangePickerViewController.defaultHeaderFontSize) { + didSet { + label?.font = font + } + } override init(frame: CGRect) { super.init(frame: frame) @@ -22,13 +27,14 @@ class CalendarDateRangePickerHeaderView: UICollectionReusableView { initLabel() } - func initLabel() { + @objc func initLabel() { label = UILabel(frame: frame) label.center = CGPoint(x: frame.size.width / 2, y: frame.size.height / 2) - label.font = UIFont(name: "HelveticaNeue-Light", size: 17.0) + label.font = font label.textColor = UIColor.darkGray label.textAlignment = NSTextAlignment.center self.addSubview(label) } } + diff --git a/CalendarDateRangePickerViewController/Classes/CalendarDateRangePickerViewController.swift b/CalendarDateRangePickerViewController/Classes/CalendarDateRangePickerViewController.swift index 3626fdc..51149c2 100644 --- a/CalendarDateRangePickerViewController/Classes/CalendarDateRangePickerViewController.swift +++ b/CalendarDateRangePickerViewController/Classes/CalendarDateRangePickerViewController.swift @@ -11,27 +11,42 @@ import UIKit public protocol CalendarDateRangePickerViewControllerDelegate { func didCancelPickingDateRange() func didPickDateRange(startDate: Date!, endDate: Date!) + func didSelectStartDate(startDate: Date!) + func didSelectEndDate(endDate: Date!) } public class CalendarDateRangePickerViewController: UICollectionViewController { - let cellReuseIdentifier = "CalendarDateRangePickerCell" - let headerReuseIdentifier = "CalendarDateRangePickerHeaderView" + @objc let cellReuseIdentifier = "CalendarDateRangePickerCell" + @objc let headerReuseIdentifier = "CalendarDateRangePickerHeaderView" public var delegate: CalendarDateRangePickerViewControllerDelegate! - let itemsPerRow = 7 - let itemHeight: CGFloat = 40 - let collectionViewInsets = UIEdgeInsets(top: 0, left: 25, bottom: 0, right: 25) + @objc let itemsPerRow = 7 + @objc let itemHeight: CGFloat = 40 + @objc let collectionViewInsets = UIEdgeInsets(top: 0, left: 25, bottom: 0, right: 25) - public var minimumDate: Date! - public var maximumDate: Date! + @objc public var minimumDate: Date! + @objc public var maximumDate: Date! - public var selectedStartDate: Date? - public var selectedEndDate: Date? + @objc public var selectedStartDate: Date? + @objc public var selectedEndDate: Date? + @objc var selectedStartCell: IndexPath? + @objc var selectedEndCell: IndexPath? - public var selectedColor = UIColor(red: 66/255.0, green: 150/255.0, blue: 240/255.0, alpha: 1.0) - public var titleText = "Select Dates" + @objc public var disabledDates: [Date]? + + @objc public var cellHighlightedColor = UIColor(white: 0.9, alpha: 1.0) + @objc public static let defaultCellFontSize:CGFloat = 15.0 + @objc public static let defaultHeaderFontSize:CGFloat = 17.0 + @objc public var cellFont:UIFont = UIFont(name: "HelveticaNeue", size: CalendarDateRangePickerViewController.defaultCellFontSize)! + @objc public var headerFont:UIFont = UIFont(name: "HelveticaNeue-Light", size: CalendarDateRangePickerViewController.defaultHeaderFontSize)! + + + @objc public var selectedColor = UIColor(red: 66/255.0, green: 150/255.0, blue: 240/255.0, alpha: 1.0) + @objc public var selectedLabelColor = UIColor(red: 255/255.0, green: 255/255.0, blue: 255/255.0, alpha: 1.0) + @objc public var highlightedLabelColor = UIColor(red: 255/255.0, green: 255/255.0, blue: 255/255.0, alpha: 1.0) + @objc public var titleText = "Select Dates" override public func viewDidLoad() { super.viewDidLoad() @@ -58,11 +73,11 @@ public class CalendarDateRangePickerViewController: UICollectionViewController { self.navigationItem.rightBarButtonItem?.isEnabled = selectedStartDate != nil && selectedEndDate != nil } - func didTapCancel() { + @objc func didTapCancel() { delegate.didCancelPickingDateRange() } - func didTapDone() { + @objc func didTapDone() { if selectedStartDate == nil || selectedEndDate == nil { return } @@ -90,7 +105,12 @@ extension CalendarDateRangePickerViewController { override public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellReuseIdentifier, for: indexPath) as! CalendarDateRangePickerCell + + cell.highlightedColor = self.cellHighlightedColor cell.selectedColor = self.selectedColor + cell.selectedLabelColor = self.selectedLabelColor + cell.highlightedLabelColor = self.highlightedLabelColor + cell.font = self.cellFont cell.reset() let blankItems = getWeekday(date: getFirstDateForSection(section: indexPath.section)) - 1 if indexPath.item < 7 { @@ -102,7 +122,17 @@ extension CalendarDateRangePickerViewController { let date = getDate(dayOfMonth: dayOfMonth, section: indexPath.section) cell.date = date cell.label.text = "\(dayOfMonth)" - + + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "yyyy-MM-dd" + let datePreFormatted = dateFormatter.string(from: date) + let dateFormatted = dateFormatter.date(from: datePreFormatted) + + if disabledDates != nil{ + if (disabledDates?.contains(cell.date!))!{ + cell.disable() + } + } if isBefore(dateA: date, dateB: minimumDate) { cell.disable() } @@ -135,6 +165,7 @@ extension CalendarDateRangePickerViewController { case UICollectionElementKindSectionHeader: let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: headerReuseIdentifier, for: indexPath) as! CalendarDateRangePickerHeaderView headerView.label.text = getMonthLabel(date: getFirstDateForSection(section: indexPath.section)) + headerView.font = headerFont return headerView default: fatalError("Unexpected element kind") @@ -150,21 +181,35 @@ extension CalendarDateRangePickerViewController : UICollectionViewDelegateFlowLa if cell.date == nil { return } - if isBefore(dateA: cell.date!, dateB: minimumDate) { + if isBefore(dateA: cell.date!, dateB: minimumDate){ return } + + if disabledDates != nil{ + if (disabledDates?.contains(cell.date!))!{ + return + } + } + if selectedStartDate == nil { selectedStartDate = cell.date + selectedStartCell = indexPath + delegate.didSelectStartDate(startDate: selectedStartDate) } else if selectedEndDate == nil { - if isBefore(dateA: selectedStartDate!, dateB: cell.date!) { + if isBefore(dateA: selectedStartDate!, dateB: cell.date!) && !isBetween(selectedStartCell!, and: indexPath){ selectedEndDate = cell.date + delegate.didSelectEndDate(endDate: selectedEndDate) self.navigationItem.rightBarButtonItem?.isEnabled = true } else { // If a cell before the currently selected start date is selected then just set it as the new start date selectedStartDate = cell.date + selectedStartCell = indexPath + delegate.didSelectStartDate(startDate: selectedStartDate) } } else { selectedStartDate = cell.date + selectedStartCell = indexPath + delegate.didSelectStartDate(startDate: selectedStartDate) selectedEndDate = nil } collectionView.reloadData() @@ -197,23 +242,23 @@ extension CalendarDateRangePickerViewController { // Helper functions - func getFirstDate() -> Date { + @objc func getFirstDate() -> Date { var components = Calendar.current.dateComponents([.month, .year], from: minimumDate) components.day = 1 return Calendar.current.date(from: components)! } - func getFirstDateForSection(section: Int) -> Date { + @objc func getFirstDateForSection(section: Int) -> Date { return Calendar.current.date(byAdding: .month, value: section, to: getFirstDate())! } - func getMonthLabel(date: Date) -> String { + @objc func getMonthLabel(date: Date) -> String { let dateFormatter = DateFormatter() dateFormatter.dateFormat = "MMMM yyyy" return dateFormatter.string(from: date) } - func getWeekdayLabel(weekday: Int) -> String { + @objc func getWeekdayLabel(weekday: Int) -> String { var components = DateComponents() components.calendar = Calendar.current components.weekday = weekday @@ -226,26 +271,57 @@ extension CalendarDateRangePickerViewController { return dateFormatter.string(from: date!) } - func getWeekday(date: Date) -> Int { + @objc func getWeekday(date: Date) -> Int { return Calendar.current.dateComponents([.weekday], from: date).weekday! } - func getNumberOfDaysInMonth(date: Date) -> Int { + @objc func getNumberOfDaysInMonth(date: Date) -> Int { return Calendar.current.range(of: .day, in: .month, for: date)!.count } - func getDate(dayOfMonth: Int, section: Int) -> Date { + @objc func getDate(dayOfMonth: Int, section: Int) -> Date { var components = Calendar.current.dateComponents([.month, .year], from: getFirstDateForSection(section: section)) components.day = dayOfMonth return Calendar.current.date(from: components)! } - func areSameDay(dateA: Date, dateB: Date) -> Bool { + @objc func areSameDay(dateA: Date, dateB: Date) -> Bool { return Calendar.current.compare(dateA, to: dateB, toGranularity: .day) == ComparisonResult.orderedSame } - func isBefore(dateA: Date, dateB: Date) -> Bool { + @objc func isBefore(dateA: Date, dateB: Date) -> Bool { return Calendar.current.compare(dateA, to: dateB, toGranularity: .day) == ComparisonResult.orderedAscending } + @objc func isBetween(_ startDateCellIndex: IndexPath, and endDateCellIndex: IndexPath) -> Bool { + + if disabledDates == nil{ + return false + } + + var index = startDateCellIndex.row + var section = startDateCellIndex.section + var currentIndexPath: IndexPath + var cell: CalendarDateRangePickerCell? + + while !(index == endDateCellIndex.row && section == endDateCellIndex.section){ + currentIndexPath = IndexPath(row: index, section: section) + cell = collectionView?.cellForItem(at: currentIndexPath) as! CalendarDateRangePickerCell + if cell == nil{ + section = section + 1 + let blankItems = getWeekday(date: getFirstDateForSection(section: section)) - 1 + index = blankItems + 1 + currentIndexPath = IndexPath(row: index, section: section) + cell = collectionView?.cellForItem(at: currentIndexPath) as! CalendarDateRangePickerCell + } + + if (disabledDates?.contains((cell?.date)!))!{ + return true + } + index = index + 1 + } + + return false + } + } diff --git a/Example/CalendarDateRangePickerViewController.xcodeproj/project.pbxproj b/Example/CalendarDateRangePickerViewController.xcodeproj/project.pbxproj index 2525d1c..e7e3ea5 100644 --- a/Example/CalendarDateRangePickerViewController.xcodeproj/project.pbxproj +++ b/Example/CalendarDateRangePickerViewController.xcodeproj/project.pbxproj @@ -215,7 +215,7 @@ TargetAttributes = { 607FACCF1AFB9204008FA782 = { CreatedOnToolsVersion = 6.3.1; - DevelopmentTeam = 3EKA2B3YUL; + DevelopmentTeam = 3PFT3Q8CHG; LastSwiftMigration = 0900; }; 607FACE41AFB9204008FA782 = { @@ -511,14 +511,14 @@ baseConfigurationReference = 863F34A79DF14110025EE9E4 /* Pods-CalendarDateRangePickerViewController_Example.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - DEVELOPMENT_TEAM = 3EKA2B3YUL; + DEVELOPMENT_TEAM = 3PFT3Q8CHG; INFOPLIST_FILE = CalendarDateRangePickerViewController/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; MODULE_NAME = ExampleApp; - PRODUCT_BUNDLE_IDENTIFIER = "com.miraan.CalendarDateRangePickerViewController-Example"; + PRODUCT_BUNDLE_IDENTIFIER = "com.miraan.CalendarDateRangePickerViewController-Example-Ljuka"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.2; }; name = Debug; }; @@ -527,14 +527,14 @@ baseConfigurationReference = C9304EBA1ACFB048B6759598 /* Pods-CalendarDateRangePickerViewController_Example.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - DEVELOPMENT_TEAM = 3EKA2B3YUL; + DEVELOPMENT_TEAM = 3PFT3Q8CHG; INFOPLIST_FILE = CalendarDateRangePickerViewController/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; MODULE_NAME = ExampleApp; - PRODUCT_BUNDLE_IDENTIFIER = "com.miraan.CalendarDateRangePickerViewController-Example"; + PRODUCT_BUNDLE_IDENTIFIER = "com.miraan.CalendarDateRangePickerViewController-Example-Ljuka"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.2; }; name = Release; }; diff --git a/Example/CalendarDateRangePickerViewController.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Example/CalendarDateRangePickerViewController.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Example/CalendarDateRangePickerViewController.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Example/CalendarDateRangePickerViewController/AppDelegate.swift b/Example/CalendarDateRangePickerViewController/AppDelegate.swift index 8f91c84..6e63624 100644 --- a/Example/CalendarDateRangePickerViewController/AppDelegate.swift +++ b/Example/CalendarDateRangePickerViewController/AppDelegate.swift @@ -14,7 +14,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true } diff --git a/Example/CalendarDateRangePickerViewController/ViewController.swift b/Example/CalendarDateRangePickerViewController/ViewController.swift index b2b3933..730c4db 100644 --- a/Example/CalendarDateRangePickerViewController/ViewController.swift +++ b/Example/CalendarDateRangePickerViewController/ViewController.swift @@ -19,6 +19,14 @@ class ViewController: UIViewController { dateRangePickerViewController.minimumDate = Date() dateRangePickerViewController.maximumDate = Calendar.current.date(byAdding: .year, value: 2, to: Date()) dateRangePickerViewController.selectedStartDate = Date() +/* + Set disabled dates if you want. It's optional... + + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "yyyy-MM-dd" + + dateRangePickerViewController.disabledDates = [dateFormatter.date(from: "2018-11-13"), dateFormatter.date(from: "2018-11-21")] as? [Date] +*/ dateRangePickerViewController.selectedEndDate = Calendar.current.date(byAdding: .day, value: 10, to: Date()) dateRangePickerViewController.selectedColor = UIColor.red dateRangePickerViewController.titleText = "Select Date Range" @@ -41,4 +49,17 @@ extension ViewController : CalendarDateRangePickerViewControllerDelegate { self.navigationController?.dismiss(animated: true, completion: nil) } + @objc func didSelectStartDate(startDate: Date!){ +// Do something when start date is selected... + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "EEEE, MMM d, yyyy" + print(dateFormatter.string(from: startDate)) + } + + @objc func didSelectEndDate(endDate: Date!){ +// Do something when end date is selected... + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "EEEE, MMM d, yyyy" + print(dateFormatter.string(from: endDate)) + } }