Comments (5)
@iAj43 this code help you for single selection and also for multiple date range
isSingleDateSelect = true // you have to set true when open your calendar action
//
// CalendarDateRangePickerViewController.swift
// CalendarDateRangePickerViewController
//
// Created by Miraan on 15/10/2017.
// Copyright © 2017 Miraan. All rights reserved.
//
import UIKit
public protocol CalendarDateRangePickerViewControllerDelegate {
func didTapCancel()
func didTapDoneWithDateRange(startDate: Date!, endDate: Date!)
func dismissWhenSingleSelect(date: Date!)
}
@available(iOS 9.0, *)
public class CalendarDateRangePickerViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
let cellReuseIdentifier = "CalendarDateRangePickerCell"
let headerReuseIdentifier = "CalendarDateRangePickerHeaderView"
public var delegate: CalendarDateRangePickerViewControllerDelegate!
let itemsPerRow = 7
let itemHeight: CGFloat = 40
var didScrollToDate = false
public var isSingleDateSelect:Bool = false
public var minimumDate: Date!
public var maximumDate: Date!
public var selectedStartDate: Date?
public var selectedEndDate: Date?
var collectionViewInsets = UIEdgeInsets(top: 0, left: 25, bottom: 0, right: 25)
var screenwidth = UIScreen.main.bounds.size.width
/*--------------------*/
@available(iOS 9.0, *)
lazy var collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.sectionHeadersPinToVisibleBounds = false
let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
cv.backgroundColor = .white
cv.dataSource = self
cv.delegate = self
cv.translatesAutoresizingMaskIntoConstraints = false
cv.register(CalendarDateRangePickerCell.self, forCellWithReuseIdentifier: cellReuseIdentifier)
cv.register(CalendarDateRangePickerHeaderView.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: headerReuseIdentifier)
cv.showsVerticalScrollIndicator = false
return cv
}()
/*--------------------*/
override public func viewDidLoad() {
super.viewDidLoad()
self.title = "Calendar"
view.backgroundColor = .white
view.addSubview(collectionView)
if minimumDate == nil {
minimumDate = Date()
}
if maximumDate == nil {
maximumDate = Calendar.current.date(byAdding: .year, value: 3, to: minimumDate)
}
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(CalendarDateRangePickerViewController.didTapDone))
self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(CalendarDateRangePickerViewController.didTapCancel))
//self.navigationItem.rightBarButtonItem?.isEnabled = selectedStartDate != nil && selectedEndDate != nil
setupAutolayout()
}
@objc func didTapCancel() {
delegate.didTapCancel()
}
@objc func didTapDone() {
if isSingleDateSelect {
delegate.dismissWhenSingleSelect(date:selectedEndDate!)
} else {
if selectedStartDate == nil || selectedEndDate == nil {
if selectedEndDate == nil {
delegate.didTapDoneWithDateRange(startDate: selectedStartDate!, endDate: selectedEndDate!)
}
return
}
}
}
//Mark:------------
func setupAutolayout() {
// UIApplication.shared.statusBarFrame.height + 44
collectionView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 25).isActive = true
collectionView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -25).isActive = true
collectionView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
if #available(iOS 11, *) {
let guide = view.safeAreaLayoutGuide
collectionView.bottomAnchor.constraint(equalTo: guide.bottomAnchor).isActive = true
} else {
collectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
}
}
}
@available(iOS 9.0, *)
extension CalendarDateRangePickerViewController {
// UICollectionViewDataSource
public func numberOfSections(in collectionView: UICollectionView) -> Int {
let difference = Calendar.current.dateComponents([.month], from: minimumDate, to: maximumDate)
return difference.month! + 1
}
public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
let firstDateForSection = getFirstDateForSection(section: section)
let weekdayRowItems = 7
let blankItems = getWeekday(date: firstDateForSection) - 1
let daysInMonth = getNumberOfDaysInMonth(date: firstDateForSection)
return weekdayRowItems + blankItems + daysInMonth
}
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellReuseIdentifier, for: indexPath) as! CalendarDateRangePickerCell
cell.reset()
let blankItems = getWeekday(date: getFirstDateForSection(section: indexPath.section)) - 1
if indexPath.item < 7 {
cell.label.text = getWeekdayLabel(weekday: indexPath.item + 1)
} else if indexPath.item < 7 + blankItems {
cell.label.text = ""
} else {
let dayOfMonth = indexPath.item - (7 + blankItems) + 1
let date = getDate(dayOfMonth: dayOfMonth, section: indexPath.section)
cell.date = date
cell.label.text = "\(dayOfMonth)"
if isBefore(dateA: date, dateB: minimumDate) {
cell.disable()
}
if isSingleDateSelect {
if selectedEndDate != nil && areSameDay(dateA: date, dateB: selectedEndDate!) {
cell.select()
}
} else {
if selectedStartDate != nil && selectedEndDate != nil && isBefore(dateA: selectedStartDate!, dateB: date) && isBefore(dateA: date, dateB: selectedEndDate!) {
// Cell falls within selected range
if dayOfMonth == 1 {
cell.highlightRight()
} else if dayOfMonth == getNumberOfDaysInMonth(date: date) {
cell.highlightLeft()
} else {
cell.highlight()
}
} else if selectedStartDate != nil && areSameDay(dateA: date, dateB: selectedStartDate!) {
// Cell is selected start date
cell.select()
if selectedEndDate != nil {
cell.highlightRight()
}
} else if selectedEndDate != nil && areSameDay(dateA: date, dateB: selectedEndDate!) {
cell.select()
cell.highlightLeft()
}
}
}
return cell
}
public func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
switch kind {
case UICollectionElementKindSectionHeader:
let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: headerReuseIdentifier, for: indexPath) as! CalendarDateRangePickerHeaderView
headerView.label.text = getMonthLabel(date: getFirstDateForSection(section: indexPath.section))
return headerView
default:
fatalError("Unexpected element kind")
}
}
public func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
if !didScrollToDate {
collectionView.scrollToItem(at: getIndexPathForDate(date:selectedStartDate!), at: .centeredVertically, animated: false)
didScrollToDate = true
}
}
}
@available(iOS 9.0, *)
extension CalendarDateRangePickerViewController : UICollectionViewDelegateFlowLayout {
public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell = collectionView.cellForItem(at: indexPath) as! CalendarDateRangePickerCell
if cell.date == nil {
return
}
if isBefore(dateA: cell.date!, dateB: minimumDate) {
return
}
if isSingleDateSelect {
selectedStartDate = cell.date
selectedEndDate = selectedStartDate
}else{
if selectedStartDate == nil {
selectedStartDate = cell.date
} else if selectedEndDate == nil {
if isBefore(dateA: selectedStartDate!, dateB: cell.date!) {
selectedEndDate = cell.date
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
}
} else {
selectedStartDate = cell.date
selectedEndDate = nil
}
}
collectionView.reloadData()
}
public func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
let padding = collectionViewInsets.left + collectionViewInsets.right
let availableWidth = screenwidth - padding
let itemWidth = availableWidth / CGFloat(itemsPerRow)
return CGSize(width: itemWidth, height: itemHeight)
}
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
return CGSize(width: screenwidth, height: 50)
}
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 5
}
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func getIndexPathForDate(date: Date) -> IndexPath {
var sectionMonht = Calendar.current.dateComponents([.month], from: minimumDate, to: date).month!
let itemDay = Calendar.current.component(.day, from: date) - 1
if(itemDay == 0) {
sectionMonht += 1 // Fix 1th day appereace
}
let indexPath = IndexPath(item:itemDay, section: sectionMonht)
return indexPath
}
}
@available(iOS 9.0, *)
extension CalendarDateRangePickerViewController {
// Helper functions
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 {
return Calendar.current.date(byAdding: .month, value: section, to: getFirstDate())!
}
func getMonthLabel(date: Date) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMMM yyyy"
return dateFormatter.string(from: date)
}
func getWeekdayLabel(weekday: Int) -> String {
var components = DateComponents()
components.calendar = Calendar.current
components.weekday = weekday
let date = Calendar.current.nextDate(after: Date(), matching: components, matchingPolicy: Calendar.MatchingPolicy.strict)
if date == nil {
return "E"
}
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "EEEEE"
return dateFormatter.string(from: date!)
}
func getWeekday(date: Date) -> Int {
return Calendar.current.dateComponents([.weekday], from: date).weekday!
}
func getNumberOfDaysInMonth(date: Date) -> Int {
return Calendar.current.range(of: .day, in: .month, for: date)!.count
}
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 {
return Calendar.current.compare(dateA, to: dateB, toGranularity: .day) == ComparisonResult.orderedSame
}
func isBefore(dateA: Date, dateB: Date) -> Bool {
return Calendar.current.compare(dateA, to: dateB, toGranularity: .day) == ComparisonResult.orderedAscending
}
}
from calendardaterangepickerviewcontroller.
yes but need to change framework file i don't know how to pull request so i can't do that
change CalendarDateRangePickerViewController to this code
import UIKit
public enum Selected {
case single
case multiple
}
public protocol CalendarDateRangePickerViewControllerDelegate {
func didTapCancel()
func didTapDoneWithDateRange(startDate: Date!, endDate: Date!)
}
public class CalendarDateRangePickerViewController: UICollectionViewController {
let cellReuseIdentifier = "CalendarDateRangePickerCell"
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)
public var minimumDate: Date!
public var maximumDate: Date!
public var selectedStartDate: Date?
public var selectedEndDate: Date?
public var choice:Selected!
override public func viewDidLoad() {
super.viewDidLoad()
self.title = "Select Dates"
collectionView?.dataSource = self
collectionView?.delegate = self
collectionView?.backgroundColor = UIColor.white
collectionView?.register(CalendarDateRangePickerCell.self, forCellWithReuseIdentifier: cellReuseIdentifier)
collectionView?.register(CalendarDateRangePickerHeaderView.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: headerReuseIdentifier)
collectionView?.contentInset = collectionViewInsets
if minimumDate == nil {
minimumDate = Date()
}
if maximumDate == nil {
maximumDate = Calendar.current.date(byAdding: .year, value: 3, to: minimumDate)
}
self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(CalendarDateRangePickerViewController.didTapCancel))
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(CalendarDateRangePickerViewController.didTapDone))
if choice == Selected.multiple {
self.navigationItem.rightBarButtonItem?.isEnabled = selectedStartDate != nil && selectedEndDate != nil
}else{
self.navigationItem.rightBarButtonItem?.isEnabled = true
}
}
@objc func didTapCancel() {
delegate.didTapCancel()
}
@objc func didTapDone() {
if selectedStartDate == nil || selectedEndDate == nil {
return
}
if choice == Selected.single {
selectedEndDate = selectedStartDate
}
delegate.didTapDoneWithDateRange(startDate: selectedStartDate!, endDate: selectedEndDate!)
}
}
extension CalendarDateRangePickerViewController {
// UICollectionViewDataSource
override public func numberOfSections(in collectionView: UICollectionView) -> Int {
let difference = Calendar.current.dateComponents([.month], from: minimumDate, to: maximumDate)
return difference.month! + 1
}
override public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
let firstDateForSection = getFirstDateForSection(section: section)
let weekdayRowItems = 7
let blankItems = getWeekday(date: firstDateForSection) - 1
let daysInMonth = getNumberOfDaysInMonth(date: firstDateForSection)
return weekdayRowItems + blankItems + daysInMonth
}
override public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellReuseIdentifier, for: indexPath) as! CalendarDateRangePickerCell
cell.reset()
let blankItems = getWeekday(date: getFirstDateForSection(section: indexPath.section)) - 1
if indexPath.item < 7 {
cell.label.text = getWeekdayLabel(weekday: indexPath.item + 1)
} else if indexPath.item < 7 + blankItems {
cell.label.text = ""
} else {
let dayOfMonth = indexPath.item - (7 + blankItems) + 1
let date = getDate(dayOfMonth: dayOfMonth, section: indexPath.section)
cell.date = date
cell.label.text = "\(dayOfMonth)"
if isBefore(dateA: date, dateB: minimumDate) {
cell.disable()
}
if selectedStartDate != nil && selectedEndDate != nil && isBefore(dateA: selectedStartDate!, dateB: date) && isBefore(dateA: date, dateB: selectedEndDate!) && choice != Selected.single{
// Cell falls within selected range
if dayOfMonth == 1 {
cell.highlightRight()
} else if dayOfMonth == getNumberOfDaysInMonth(date: date) {
cell.highlightLeft()
} else {
cell.highlight()
}
} else if selectedStartDate != nil && areSameDay(dateA: date, dateB: selectedStartDate!) {
// Cell is selected start date
cell.select()
if selectedEndDate != nil {
cell.highlightRight()
}
} else if selectedEndDate != nil && areSameDay(dateA: date, dateB: selectedEndDate!) && choice != Selected.single {
cell.select()
cell.highlightLeft()
}
}
return cell
}
override public func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
switch kind {
case UICollectionElementKindSectionHeader:
let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: headerReuseIdentifier, for: indexPath) as! CalendarDateRangePickerHeaderView
headerView.label.text = getMonthLabel(date: getFirstDateForSection(section: indexPath.section))
return headerView
default:
fatalError("Unexpected element kind")
}
}
}
extension CalendarDateRangePickerViewController : UICollectionViewDelegateFlowLayout {
override public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell = collectionView.cellForItem(at: indexPath) as! CalendarDateRangePickerCell
if cell.date == nil {
return
}
if isBefore(dateA: cell.date!, dateB: minimumDate) {
return
}
if selectedStartDate == nil {
selectedStartDate = cell.date
} else if selectedEndDate == nil {
if isBefore(dateA: selectedStartDate!, dateB: cell.date!) {
selectedEndDate = cell.date
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
}
} else {
selectedStartDate = cell.date
selectedEndDate = nil
}
collectionView.reloadData()
}
public func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize {
let padding = collectionViewInsets.left + collectionViewInsets.right
let availableWidth = view.frame.width - padding
let itemWidth = round(availableWidth / CGFloat(itemsPerRow))
return CGSize(width: itemWidth, height: itemHeight)
}
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
return CGSize(width: view.frame.size.width, height: 50)
}
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 5
}
public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
}
extension CalendarDateRangePickerViewController {
// Helper functions
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 {
return Calendar.current.date(byAdding: .month, value: section, to: getFirstDate())!
}
func getMonthLabel(date: Date) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMMM yyyy"
return dateFormatter.string(from: date)
}
func getWeekdayLabel(weekday: Int) -> String {
var components = DateComponents()
components.calendar = Calendar.current
components.weekday = weekday
let date = Calendar.current.nextDate(after: Date(), matching: components, matchingPolicy: Calendar.MatchingPolicy.strict)
if date == nil {
return "E"
}
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "EEEEE"
return dateFormatter.string(from: date!)
}
func getWeekday(date: Date) -> Int {
return Calendar.current.dateComponents([.weekday], from: date).weekday!
}
func getNumberOfDaysInMonth(date: Date) -> Int {
return Calendar.current.range(of: .day, in: .month, for: date)!.count
}
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 {
return Calendar.current.compare(dateA, to: dateB, toGranularity: .day) == ComparisonResult.orderedSame
}
func isBefore(dateA: Date, dateB: Date) -> Bool {
return Calendar.current.compare(dateA, to: dateB, toGranularity: .day) == ComparisonResult.orderedAscending
}
}
from calendardaterangepickerviewcontroller.
I hope next update they add this code
yes but need to change framework file i don't know how to pull request so i can't do that
change CalendarDateRangePickerViewController to this codeimport UIKit public enum Selected { case single case multiple } public protocol CalendarDateRangePickerViewControllerDelegate { func didTapCancel() func didTapDoneWithDateRange(startDate: Date!, endDate: Date!) } public class CalendarDateRangePickerViewController: UICollectionViewController { let cellReuseIdentifier = "CalendarDateRangePickerCell" 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) public var minimumDate: Date! public var maximumDate: Date! public var selectedStartDate: Date? public var selectedEndDate: Date? public var choice:Selected! override public func viewDidLoad() { super.viewDidLoad() self.title = "Select Dates" collectionView?.dataSource = self collectionView?.delegate = self collectionView?.backgroundColor = UIColor.white collectionView?.register(CalendarDateRangePickerCell.self, forCellWithReuseIdentifier: cellReuseIdentifier) collectionView?.register(CalendarDateRangePickerHeaderView.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: headerReuseIdentifier) collectionView?.contentInset = collectionViewInsets if minimumDate == nil { minimumDate = Date() } if maximumDate == nil { maximumDate = Calendar.current.date(byAdding: .year, value: 3, to: minimumDate) } self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(CalendarDateRangePickerViewController.didTapCancel)) self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(CalendarDateRangePickerViewController.didTapDone)) if choice == Selected.multiple { self.navigationItem.rightBarButtonItem?.isEnabled = selectedStartDate != nil && selectedEndDate != nil }else{ self.navigationItem.rightBarButtonItem?.isEnabled = true } } @objc func didTapCancel() { delegate.didTapCancel() } @objc func didTapDone() { if selectedStartDate == nil || selectedEndDate == nil { return } if choice == Selected.single { selectedEndDate = selectedStartDate } delegate.didTapDoneWithDateRange(startDate: selectedStartDate!, endDate: selectedEndDate!) } } extension CalendarDateRangePickerViewController { // UICollectionViewDataSource override public func numberOfSections(in collectionView: UICollectionView) -> Int { let difference = Calendar.current.dateComponents([.month], from: minimumDate, to: maximumDate) return difference.month! + 1 } override public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { let firstDateForSection = getFirstDateForSection(section: section) let weekdayRowItems = 7 let blankItems = getWeekday(date: firstDateForSection) - 1 let daysInMonth = getNumberOfDaysInMonth(date: firstDateForSection) return weekdayRowItems + blankItems + daysInMonth } override public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellReuseIdentifier, for: indexPath) as! CalendarDateRangePickerCell cell.reset() let blankItems = getWeekday(date: getFirstDateForSection(section: indexPath.section)) - 1 if indexPath.item < 7 { cell.label.text = getWeekdayLabel(weekday: indexPath.item + 1) } else if indexPath.item < 7 + blankItems { cell.label.text = "" } else { let dayOfMonth = indexPath.item - (7 + blankItems) + 1 let date = getDate(dayOfMonth: dayOfMonth, section: indexPath.section) cell.date = date cell.label.text = "\(dayOfMonth)" if isBefore(dateA: date, dateB: minimumDate) { cell.disable() } if selectedStartDate != nil && selectedEndDate != nil && isBefore(dateA: selectedStartDate!, dateB: date) && isBefore(dateA: date, dateB: selectedEndDate!){ // Cell falls within selected range if dayOfMonth == 1 { cell.highlightRight() } else if dayOfMonth == getNumberOfDaysInMonth(date: date) { cell.highlightLeft() } else { cell.highlight() } } else if selectedStartDate != nil && areSameDay(dateA: date, dateB: selectedStartDate!) { // Cell is selected start date cell.select() if selectedEndDate != nil { cell.highlightRight() } } else if selectedEndDate != nil && areSameDay(dateA: date, dateB: selectedEndDate!) && choice != Selected.single { cell.select() cell.highlightLeft() } } return cell } override public func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { switch kind { case UICollectionElementKindSectionHeader: let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: headerReuseIdentifier, for: indexPath) as! CalendarDateRangePickerHeaderView headerView.label.text = getMonthLabel(date: getFirstDateForSection(section: indexPath.section)) return headerView default: fatalError("Unexpected element kind") } } } extension CalendarDateRangePickerViewController : UICollectionViewDelegateFlowLayout { override public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { let cell = collectionView.cellForItem(at: indexPath) as! CalendarDateRangePickerCell if cell.date == nil { return } if isBefore(dateA: cell.date!, dateB: minimumDate) { return } if selectedStartDate == nil { selectedStartDate = cell.date } else if selectedEndDate == nil { if isBefore(dateA: selectedStartDate!, dateB: cell.date!) { selectedEndDate = cell.date 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 } } else { selectedStartDate = cell.date selectedEndDate = nil } collectionView.reloadData() } public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { let padding = collectionViewInsets.left + collectionViewInsets.right let availableWidth = view.frame.width - padding let itemWidth = round(availableWidth / CGFloat(itemsPerRow)) return CGSize(width: itemWidth, height: itemHeight) } public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { return CGSize(width: view.frame.size.width, height: 50) } public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { return 5 } public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { return 0 } } extension CalendarDateRangePickerViewController { // Helper functions 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 { return Calendar.current.date(byAdding: .month, value: section, to: getFirstDate())! } func getMonthLabel(date: Date) -> String { let dateFormatter = DateFormatter() dateFormatter.dateFormat = "MMMM yyyy" return dateFormatter.string(from: date) } func getWeekdayLabel(weekday: Int) -> String { var components = DateComponents() components.calendar = Calendar.current components.weekday = weekday let date = Calendar.current.nextDate(after: Date(), matching: components, matchingPolicy: Calendar.MatchingPolicy.strict) if date == nil { return "E" } let dateFormatter = DateFormatter() dateFormatter.dateFormat = "EEEEE" return dateFormatter.string(from: date!) } func getWeekday(date: Date) -> Int { return Calendar.current.dateComponents([.weekday], from: date).weekday! } func getNumberOfDaysInMonth(date: Date) -> Int { return Calendar.current.range(of: .day, in: .month, for: date)!.count } 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 { return Calendar.current.compare(dateA, to: dateB, toGranularity: .day) == ComparisonResult.orderedSame } func isBefore(dateA: Date, dateB: Date) -> Bool { return Calendar.current.compare(dateA, to: dateB, toGranularity: .day) == ComparisonResult.orderedAscending } }
from calendardaterangepickerviewcontroller.
@sooryaraj kindly share sample file or code changes because above code not working
from calendardaterangepickerviewcontroller.
I just created my own custom class that inherits from CalendarDateRangePickerViewController overriding didTapDone() func
public protocol MyCustomCalendarDateRangePickerViewControllerDelegate: CalendarDateRangePickerViewControllerDelegate {
func didTapDoneWithSingleDate(date: Date!)
}
class MyCustomCalendarDateRangePickerViewController: CalendarDateRangePickerViewController {
var singleDateSelection = false
override func didTapDone() {
if let selectedStartDate = selectedStartDate {
if let selectedEndDate = selectedEndDate {
delegate.didTapDoneWithDateRange(startDate: selectedStartDate, endDate: selectedEndDate)
} else if singleDateSelection, let delegate = delegate as? MyCustomCalendarDateRangePickerViewControllerDelegate {
delegate.didTapDoneWithSingleDate(date: selectedStartDate)
}
}
return
}
}
So when I want single data selection I set the singleDateSelection property to true and implements MyCustomCalendarDateRangePickerViewControllerDelegate with didTapDoneWithSingleDate func
from calendardaterangepickerviewcontroller.
Related Issues (20)
- remove space between two selected date
- Show current date HOT 2
- dates selection
- just some fixes
- Reset Selected Dates
- Localize Calendar according to Countries (For ex spanish,Portugese)
- Current date to previous one i need to displaying but when appearing first time it is not showing current day and month ?
- feature: add change locale
- UI alignment issue in 4 inch screen device iPhone 5s iPhone SE
- White color when button is selected
- Not able to set additional options to override the defaults HOT 1
- How to change the first day of the week HOT 2
- Allow same date selection for From Date and To Date HOT 3
- Crash Issue HOT 2
- No option for highlighting today in calendar
- Horizontal scrolling
- How to change start date and end date?
- How to scroll to specific/selected date? HOT 5
- Swift 5 support HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from calendardaterangepickerviewcontroller.