Created
November 11, 2016 11:53
-
-
Save duraiganesh0/00a23e7bb81b10060554df7ad8273673 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
@objc public protocol SMDatePickerDelegate { | |
@objc optional func datePickerWillAppear(_ picker: SMDatePicker) | |
@objc optional func datePickerDidAppear(_ picker: SMDatePicker) | |
@objc optional func datePicker(_ picker: SMDatePicker, didPickDate date: Date) | |
@objc optional func datePickerDidCancel(_ picker: SMDatePicker) | |
@objc optional func datePickerWillDisappear(_ picker: SMDatePicker) | |
@objc optional func datePickerDidDisappear(_ picker: SMDatePicker) | |
} | |
@objc open class SMDatePicker: UIView { | |
/** Picker's delegate that conforms to SMDatePickerDelegate protocol */ | |
open var delegate: SMDatePickerDelegate? | |
/** UIToolbar title */ | |
open var title: String? | |
open var titleFont: UIFont = UIFont.systemFont(ofSize: 13) | |
open var titleColor: UIColor = UIColor.gray | |
/** You can define your own toolbar height. By default it's 44 pixels. */ | |
open var toolbarHeight: CGFloat = 44.0 | |
/** Specify different UIDatePicker mode. By default it's UIDatePickerMode.DateAndTime */ | |
open var pickerMode: UIDatePickerMode = UIDatePickerMode.dateAndTime { | |
didSet { picker.datePickerMode = pickerMode } | |
} | |
open var minimumDate: Date = Date(){ | |
didSet { picker.minimumDate = minimumDate } | |
} | |
open var maximumDate: Date = Date(){ | |
didSet { picker.maximumDate = maximumDate | |
} | |
} | |
/** You can set up different color for picker and toolbar. */ | |
open var toolbarBackgroundColor: UIColor? { | |
didSet { | |
toolbar.backgroundColor = toolbarBackgroundColor | |
toolbar.barTintColor = toolbarBackgroundColor | |
} | |
} | |
/** You can set up different color for picker and toolbar. */ | |
open var pickerBackgroundColor: UIColor? { | |
didSet { picker.backgroundColor = pickerBackgroundColor } | |
} | |
/** Initial picker's date */ | |
open var pickerDate: Date = Date() { | |
didSet { picker.date = pickerDate } | |
} | |
/** Array of UIBarButtonItem's that will be placed on left side of UIToolbar. By default it has only 'Cancel' bytton. */ | |
open var leftButtons: [UIBarButtonItem] = [] | |
/** Array of UIBarButtonItem's that will be placed on right side of UIToolbar. By default it has only 'Done' bytton. */ | |
open var rightButtons: [UIBarButtonItem] = [] | |
// Privates | |
fileprivate var toolbar: UIToolbar = UIToolbar() | |
fileprivate var picker: UIDatePicker = UIDatePicker() | |
// MARK: Lifecycle | |
public override init(frame: CGRect) { | |
super.init(frame: CGRect.zero) | |
addSubview(picker) | |
addSubview(toolbar) | |
setupDefaultButtons() | |
customize() | |
} | |
required public init(coder aDecoder: NSCoder) { | |
super.init(coder: aDecoder)! | |
addSubview(picker) | |
addSubview(toolbar) | |
setupDefaultButtons() | |
customize() | |
} | |
// MARK: Customization | |
fileprivate func setupDefaultButtons() { | |
let doneButton = UIBarButtonItem(title: "Done", | |
style: UIBarButtonItemStyle.plain, | |
target: self, | |
action: #selector(SMDatePicker.pressedDone(_:))) | |
let cancelButton = UIBarButtonItem(title: "Cancel", | |
style: UIBarButtonItemStyle.plain, | |
target: self, | |
action: #selector(SMDatePicker.pressedCancel(_:))) | |
leftButtons = [ cancelButton ] | |
rightButtons = [ doneButton ] | |
} | |
fileprivate func customize() { | |
toolbar.barStyle = UIBarStyle.blackTranslucent | |
toolbar.isTranslucent = false | |
backgroundColor = UIColor.white | |
if let toolbarBackgroundColor = toolbarBackgroundColor { | |
toolbar.backgroundColor = toolbarBackgroundColor | |
} else { | |
toolbar.backgroundColor = backgroundColor | |
} | |
if let pickerBackgroundColor = pickerBackgroundColor { | |
picker.backgroundColor = pickerBackgroundColor | |
} else { | |
picker.backgroundColor = backgroundColor | |
} | |
} | |
fileprivate func toolbarItems() -> [UIBarButtonItem] { | |
var items: [UIBarButtonItem] = [] | |
for button in leftButtons { | |
items.append(button) | |
} | |
if let title = toolbarTitle() { | |
let spaceLeft = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil) | |
let spaceRight = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil) | |
let titleItem = UIBarButtonItem(customView: title) | |
items.append(spaceLeft) | |
items.append(titleItem) | |
items.append(spaceRight) | |
} else { | |
let space = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil) | |
items.append(space) | |
} | |
for button in rightButtons { | |
items.append(button) | |
} | |
return items | |
} | |
fileprivate func toolbarTitle() -> UILabel? { | |
if let title = title { | |
let label = UILabel() | |
label.text = title | |
label.font = titleFont | |
label.textColor = titleColor | |
label.sizeToFit() | |
return label | |
} | |
return nil | |
} | |
// MARK: Showing and hiding picker | |
/** | |
Shows picker in view with animation if it's required. | |
:param: view is a UIView where we want to show our picker | |
:param: animated will show with animation if it's true | |
*/ | |
open func showPickerInView(_ view: UIView, animated: Bool) { | |
toolbar.items = toolbarItems() | |
toolbar.frame = CGRect(x: 0, y: 0, width: view.frame.size.width, height: toolbarHeight) | |
picker.frame = CGRect(x: 0, y: toolbarHeight, width: view.frame.size.width, height: picker.frame.size.height) | |
self.frame = CGRect(x: 0, y: view.frame.size.height - picker.frame.size.height - toolbar.frame.size.height, | |
width: view.frame.size.width, height: picker.frame.size.height + toolbar.frame.size.height) | |
view.addSubview(self) | |
becomeFirstResponder() | |
showPickerAnimation(animated) | |
} | |
/** | |
Hide visible picker anikmated. | |
:param: animated will hide with animation if `true` | |
*/ | |
open func hidePicker(_ animated: Bool) { | |
hidePickerAnimation(true) | |
} | |
// MARK: Animation | |
fileprivate func hidePickerAnimation(_ animated: Bool) { | |
delegate?.datePickerWillDisappear?(self) | |
if animated { | |
UIView.animate(withDuration: 0.2, animations: { () -> Void in | |
self.frame = self.frame.offsetBy(dx: 0, dy: self.picker.frame.size.height + self.toolbar.frame.size.height) | |
}, completion: { (finished) -> Void in | |
self.delegate?.datePickerDidDisappear?(self) | |
}) | |
} else { | |
self.frame = self.frame.offsetBy(dx: 0, dy: self.picker.frame.size.height + self.toolbar.frame.size.height) | |
delegate?.datePickerDidDisappear?(self) | |
} | |
} | |
fileprivate func showPickerAnimation(_ animated: Bool) { | |
delegate?.datePickerWillAppear?(self) | |
if animated { | |
self.frame = self.frame.offsetBy(dx: 0, dy: self.frame.size.height) | |
UIView.animate(withDuration: 0.2, animations: { () -> Void in | |
self.frame = self.frame.offsetBy(dx: 0, dy: -1 * self.frame.size.height) | |
}, completion: { (finished) -> Void in | |
self.delegate?.datePickerDidAppear?(self) | |
}) | |
} else { | |
delegate?.datePickerDidAppear?(self) | |
} | |
} | |
// MARK: Actions | |
/** | |
Default Done action for picker. It will hide picker with animation and call's delegate datePicker(:didPickDate) method. | |
*/ | |
open func pressedDone(_ sender: AnyObject) { | |
hidePickerAnimation(true) | |
delegate?.datePicker?(self, didPickDate: picker.date) | |
} | |
/** | |
Default Cancel actions for picker. | |
*/ | |
open func pressedCancel(_ sender: AnyObject) { | |
hidePickerAnimation(true) | |
delegate?.datePickerDidCancel?(self) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment