JBDatePicker is a subclass of UIView, written in Swift 4, that shows a calendarmonth in which the user can select a date. It allows the user to swipe between months, and to preselect a specific date. It's appearance is largely customizable. See usage for more information.
- ARC
- iOS9
- Swift 4
pod 'JBDatePicker'
github "Tuslareb/JBDatePicker"
JBDatePicker can be implemented in your project in two ways:
- Storyboard setup
- Manual setup
Important: whatever setup you choose, JBDatePicker needs one thing to work correctly:
- Your viewController needs to adopt the JBDatePickerDelegate protocol.
Besides that, you need to integrate JBDatePicker with your project through CocoaPods. If you don’t know how to do this, please follow this tutorial. Alternatively you can use Carthage or drag the JBDatePicker classes into your project manually.
Add a UIView to your storyboard, go to the identity inspector and select JBDatePickerView as the custom class for your new view. Next, open the assistant editor and control drag to your viewController to create an outlet like this:
@IBOutlet weak var datePicker: JBDatePickerView!
Next, make sure that you import JBDatePicker and that you adopt the ‘JBDatePickerViewDelegate’ protocol:
import JBDatePicker
class ViewController: UIViewController, JBDatePickerViewDelegate {
}
Don't forget to set your viewController as the delegate of JBDatePicker, for example in viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
datePicker.delegate = self
}
Adopting the JBDatePickerViewDelegate protocol requires the implementation of a method called didSelectDay(dayView:):
// MARK: - JBDatePickerViewDelegate implementation
func didSelectDay(_ dayView: JBDatePickerDayView) {
print("date selected: \(String(describing: dayView.date))")
}
Running the app should show JBDatePicker and tapping a date should print a statement in the console. If not, double check that you’ve set the delegate and that you called the updateLayout method. If you want to customize the looks of JBDatePicker, keep reading.
It is also possible to setup JBDatePicker without using Interface Builder. This is a code example:
class ViewController: UIViewController, JBDatePickerViewDelegate {
var datePicker: JBDatePickerView!
override func viewDidLoad() {
super.viewDidLoad()
datePicker = JBDatePickerView()
view.addSubview(datePicker)
datePicker.delegate = self
//add constraints
datePicker.translatesAutoresizingMaskIntoConstraints = false
datePicker.heightAnchor.constraint(equalToConstant: 250).isActive = true
datePicker.widthAnchor.constraint(equalToConstant: view.bounds.width).isActive = true
if #available(iOS 11.0, *) {
datePicker.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor).isActive = true
datePicker.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
} else {
datePicker.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
let topguideBottom = self.topLayoutGuide.bottomAnchor
datePicker.topAnchor.constraint(equalTo: topguideBottom).isActive = true
}
}
// MARK: - JBDatePickerViewDelegate
func didSelectDay(_ dayView: JBDatePickerDayView) {
print("date selected: \(String(describing: dayView.date))")
}
Besides the only required method, the delegate offers several optional methods and properties to implement:
/**
Is called when the user swiped (or manually moved) to another month
- parameter monthView: the monthView that is now 'on screen'
*/
func didPresentOtherMonth(_ monthView: JBDatePickerMonthView) {
print(“month selected: \(monthView.monthDescription)”)
}
/**
Is called to check if any particular date is selectable by the picker
- parameter date: the date to be checked on selectability
*/
func shouldAllowSelectionOfDay(_ date: Date?) -> Bool {
//this code example disables selection for dates older then today
guard let date = date else {return true}
let comparison = NSCalendar.current.compare(date, to: Date().stripped()!, toGranularity: .day)
if comparison == .orderedAscending {
return false
}
return true
}
///Sets the day that determines which month is shown on initial load. Defaults to the current date.
var dateToShow: Date { return a Date object}
It is possible to customize the appearance of several parts of JBDatePicker by implementing the following optional properties:
///Sets the first day of the week. Defaults to the local preference.
var firstWeekDay: JBWeekDay { return .wednesday }
///Determines if a month should also show the dates of the previous and next month. Defaults to true.
var shouldShowMonthOutDates: Bool { return false }
///Determines if the weekday symbols and the month description should follow available localizations. Defaults to false.
///This means that the weekday symbols and the month description will be in the same language as the device language.
///If you want it to conform to the localization of your app, return true here.
///If you return true and your app is not localized, the weekday symbols and the month description will be in the development language.
var shouldLocalize: Bool { return true }
///Determines the height ratio of the weekDaysView compared to the total height. Defaults to 0.1 (10%).
var weekDaysViewHeightRatio: CGFloat { return 0.2 }
/**
Customizes the weekday symbols. Defaults to 'shortStandaloneWeekdaySymbols', but any Calendar API value can be used. It is also possible to return a custom string array.
- parameter calendar: calendar instance used by the calendar view
*/
func weekdaySymbols(for calendar: Calendar) -> [String]
///Determines the shape that is used to indicate a selected date. Defaults to a circular shape.
var selectionShape: JBSelectionShape { return .roundedRect }
///Font to be used in dayLabel. Defaults to systemFont of a regular size.
var fontForDayLabel: JBFont { return JBFont(name: "Avenir", size: .medium) }
///Font to be used in the bar which shows the 'mon' to 'sun' labels (weekdaysView). Defaults to systemFont of a regular size.
var fontForWeekDaysViewText: JBFont { return JBFont(name: "Avenir", size: .medium) }
///Color of any date label text that falls within the presented month
var colorForDayLabelInMonth: UIColor { return UIColor of choice }
///Color of any date label text that falls out of the presented month and is part of the next or previous (but not presented) month
var colorForDayLabelOutOfMonth: UIColor { return UIColor of choice }
///Color of any date label text that falls within the presented month but is unavailable because it's selection is now allowed
var colorForUnavaibleDay: UIColor { return UIColor of choice }
///Color of the 'today' date label text
var colorForCurrentDay: UIColor { return UIColor of choice }
///Color of any label text that is selected
var colorForSelelectedDayLabel: UIColor { return UIColor of choice }
///Color of the bar which shows the 'mon' to 'sun' labels. Defaults to green.
var colorForWeekDaysViewBackground: UIColor { return UIColor of choice }
///Color of the labels in the WeekdaysView bar that say 'mon' to 'sun'. Defaults to white.
var colorForWeekDaysViewText: UIColor { return UIColor of choice }
///Color of the selection circle for dates that aren't today
var colorForSelectionCircleForOtherDate: UIColor { return UIColor of choice }
///Color of the selection circle for today
var colorForSelectionCircleForToday: UIColor { return UIColor of choice }
///Color of the semi selected selection circle (that shows on a long press)
var colorForSemiSelectedSelectionCircle: UIColor { return UIColor of choice }
An example project is included with this repo. To run the example project, clone the repo, and run pod install
from the Example directory first.
Joost van Breukelen
JBDatePicker is available under the MIT license. See the LICENSE file for more info.