19

I want to add a Done button within a popped up datePickerView in Swift.

Here is the code:

@IBOutlet var datePicker: UITextField!

@IBAction func dateTextInputPressed(sender: UITextField) {

    var datePickerView = UIDatePicker()
    datePickerView.datePickerMode = UIDatePickerMode.Date

    sender.inputView = datePickerView
    datePickerView.addTarget(self, action: Selector("handleDatePicker:"), forControlEvents: UIControlEvents.ValueChanged)
}

func handleDatePicker(sender: UIDatePicker) {
    var dateFormatter = NSDateFormatter()
    dateFormatter.dateFormat = "yyyy-MM-dd"
    datePicker.text = dateFormatter.stringFromDate(sender.date)
}

I can use this code to pop up a datePickerView successfully.

result of datePickerView

But after I've selected the date, it does not have a "Done" button to dismiss it.

So how can I add the Done button into it?

Naresh
  • 16,698
  • 6
  • 112
  • 113
He Yifei 何一非
  • 2,592
  • 4
  • 38
  • 69
  • in Swift 5 https://stackoverflow.com/questions/27050988/uidatepicker-with-done-button/58023152#58023152 – Naresh Sep 20 '19 at 06:52

5 Answers5

41

I made this extension to close the picker. Swift 2

extension UIToolbar {

 func ToolbarPiker(mySelect : Selector) -> UIToolbar {

    let toolBar = UIToolbar()

    toolBar.barStyle = UIBarStyle.Default
    toolBar.translucent = true
    toolBar.tintColor = UIColor.blackColor()
    toolBar.sizeToFit()

    let doneButton = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Plain, target: self, action: mySelect)
    let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: nil, action: nil)

    toolBar.setItems([ spaceButton, doneButton], animated: false)
    toolBar.userInteractionEnabled = true

    return toolBar
}

}

Swift 3 - 4

extension UIToolbar {

func ToolbarPiker(mySelect : Selector) -> UIToolbar {

    let toolBar = UIToolbar()

    toolBar.barStyle = UIBarStyle.default
    toolBar.isTranslucent = true
    toolBar.tintColor = UIColor.black
    toolBar.sizeToFit()

    let doneButton = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.plain, target: self, action: mySelect)
    let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)

    toolBar.setItems([ spaceButton, doneButton], animated: false)
    toolBar.isUserInteractionEnabled = true

    return toolBar
}

}

And you can use it simply in your viewController:

  override func viewDidLoad() {
    super.viewDidLoad()

 //SWIFT2
 /*
let toolBar = UIToolbar().ToolbarPiker(#selector(MyViewController.dismissPicker))

 */
// Swift3 - 4
    let toolBar = UIToolbar().ToolbarPiker(mySelect: #selector(MyViewController.dismissPicker))

    myTextField.inputAccessoryView = toolBar


}

 // Swift 2 - 3
 func dismissPicker() { 

    view.endEditing(true)

}

 // Swift 4
 @objc func dismissPicker() { 

    view.endEditing(true)

}
Rob
  • 2,649
  • 3
  • 27
  • 34
  • 1
    Excellent solution. One small correction about the swift 3 code: let toolBar = UIToolbar().ToolbarPiker(mySelect: #selector – Night Warrier Jan 08 '17 at 05:50
  • @JUL2791 after the before code myTextField.inputView = myPikerView where you want, for example inside Editing Did Begin function of UITextField (myTextField) – Rob Mar 22 '18 at 15:26
  • 1
    I want to display picker on tap of button and selecting after selecting from Picker assign it to button title. So inputAccessoryView won't work for UIButton. Any other solution? – Jayprakash Dubey May 08 '18 at 11:41
15

You can use a generic UIView for the inputView property of the UITextField. We can add the UIDatePicker and UIButton to this UIView.

@IBAction func dateTextInputPressed(sender: UITextField) {

    //Create the view
    let inputView = UIView(frame: CGRectMake(0, 0, self.view.frame.width, 240))


    var datePickerView  : UIDatePicker = UIDatePicker(frame: CGRectMake(0, 40, 0, 0))
    datePickerView.datePickerMode = UIDatePickerMode.Date
    inputView.addSubview(datePickerView) // add date picker to UIView

    let doneButton = UIButton(frame: CGRectMake((self.view.frame.size.width/2) - (100/2), 0, 100, 50))
    doneButton.setTitle("Done", forState: UIControlState.Normal)
    doneButton.setTitle("Done", forState: UIControlState.Highlighted)
    doneButton.setTitleColor(UIColor.blackColor(), forState: UIControlState.Normal)
    doneButton.setTitleColor(UIColor.grayColor(), forState: UIControlState.Highlighted)

    inputView.addSubview(doneButton) // add Button to UIView

    doneButton.addTarget(self, action: "doneButton:", forControlEvents: UIControlEvents.TouchUpInside) // set button click event

    sender.inputView = inputView
    datePickerView.addTarget(self, action: Selector("handleDatePicker:"), forControlEvents: UIControlEvents.ValueChanged)

    handleDatePicker(datePickerView) // Set the date on start.
}

func handleDatePicker(sender: UIDatePicker) {
    var dateFormatter = NSDateFormatter()
    dateFormatter.dateFormat = "yyyy-MM-dd"
    datePicker.text = dateFormatter.stringFromDate(sender.date)
}

func doneButton(sender:UIButton)
{
    datePicker.resignFirstResponder() // To resign the inputView on clicking done.
}
He Yifei 何一非
  • 2,592
  • 4
  • 38
  • 69
rakeshbs
  • 24,392
  • 7
  • 73
  • 63
6

if you are using a button instead of text field:

/** * MARK - Advance booking action */

@IBAction func advanceBookingAction(sender: UIButton) {

    var datePicker : UIDatePicker = UIDatePicker()
    var datePickerContainer = UIView()

    datePickerContainer.frame = CGRectMake(0.0, self.view.frame.height/2, 320.0, 300.0)
    datePickerContainer.backgroundColor = UIColor.whiteColor()

    var pickerSize : CGSize = datePicker.sizeThatFits(CGSizeZero)
    datePicker.frame = CGRectMake(0.0, 20, pickerSize.width, 460)
    datePicker.setDate(NSDate(), animated: true)
    datePicker.maximumDate = NSDate()
    datePicker.datePickerMode = UIDatePickerMode.DateAndTime
    datePicker.addTarget(self, action: "dateChangedInDate:", forControlEvents: UIControlEvents.ValueChanged)
    datePickerContainer.addSubview(datePicker)

    var doneButton = UIButton()
    doneButton.setTitle("Done", forState: UIControlState.Normal)
    doneButton.setTitleColor(UIColor.blueColor(), forState: UIControlState.Normal)
    doneButton.addTarget(self, action: Selector("dismissPicker:"), forControlEvents: UIControlEvents.TouchUpInside)
    doneButton.frame    = CGRectMake(250.0, 5.0, 70.0, 37.0)

    datePickerContainer.addSubview(doneButton)

    self.view.addSubview(datePickerContainer)

}// end advanceBookingAction

/**
* MARK - observer to get the change in date
*/

func dateChangedInDate(sender:UIDatePicker){

    var dateFormatter = NSDateFormatter()
    dateFormatter.dateStyle = NSDateFormatterStyle.LongStyle
    dateFormatter.timeStyle = NSDateFormatterStyle.NoStyle
    objMethodInc.printvj("date selected \(datePicker.date)")

}// end dateChangedInDate

/*
* MARK - dismiss the date picker value
*/
func dismissPicker(sender: UIButton) {
    objMethodInc.printvj("dismiss date picker")
    datePickerContainer.removeFromSuperview()
}// end dismissPicker
Vinod Joshi
  • 7,696
  • 1
  • 50
  • 51
1

In Swift 5

If you want only Done button on DatePicker use my code

//Write toolbar code for done button
let toolBar = UIToolbar()
toolBar.barStyle = .default
toolBar.isTranslucent = true
let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let doneButton = UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(onClickDoneButton))
toolBar.setItems([space, doneButton], animated: false)
toolBar.isUserInteractionEnabled = true
toolBar.sizeToFit()
dobTF.inputAccessoryView = toolBar //Change your TextField name here

@objc func onClickDoneButton() {
    self.view.endEditing(true)
}
Naresh
  • 16,698
  • 6
  • 112
  • 113
1
@IBOutlet weak var txtDate: UITextField!
override func viewDidLoad() {
    super.viewDidLoad()
    
    //Write toolbar code for done button
    let toolBar = UIToolbar()
    toolBar.barStyle = .default
    toolBar.isTranslucent = true
    let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
    let doneButton = UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(onClickDoneButton))
    toolBar.setItems([space, doneButton], animated: false)
    toolBar.isUserInteractionEnabled = true
    toolBar.sizeToFit()
    txtDate.inputAccessoryView = toolBar //Change your TextField name here
    
    let datePickerView = UIDatePicker()
    datePickerView.datePickerMode = UIDatePicker.Mode.date
    
    txtDate.inputView = datePickerView
    datePickerView.addTarget(self, action: #selector(handleDatePicker(sender:)), for: UIControl.Event.valueChanged)
    
}

@objc func onClickDoneButton() {
    self.view.endEditing(true)
}

@objc func handleDatePicker(sender: UIDatePicker) {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "yyyy-MM-dd"
    txtDate.text = dateFormatter.string(from: sender.date)
}
Hemanshu Liya
  • 611
  • 6
  • 10