Add a Done Button Within a Pop-Up Datepickerview in Swift

Add a Done button within a pop-up datePickerView in Swift?

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)

}

UIDatePicker with done button

Create a date picker, then add it as the input view of the field in question (self.fieldInQuestion.inputView = datePicker). Next, create a UIToolBar (height 44) with UIBarButton Item on it with the title "Done", target of self, and a selector (ex. @selector(done)). Add this as the input accessory view of the same field you made the date picker an input view for (self.fieldInQuestion.inputAccessoryView = UIToolbarInstance). In the selector method (-(void)done in the example above), make sure you use [self.fieldInQuestion resignFirstResponder] and it will dismiss it.

Swift: Popup DatePicker on textbox with done button

I believe the datePickerValueChanged function isnt being called becasue you have not set the delegate of the dateSampledPickerView.

So simply enter

dateSampledPickerView.delegate = self

*********EDIT****************

Ok so after looking closer I believe you have set the action call incorrectly. Replace this line

    dateSampledPickerView.addTarget(self, action: Selector("datePickerValueChanged"), forControlEvents: UIControlEvents.ValueChanged)

with

dateSampledPickerView.addTarget(self, action: "datePickerValueChanged", forControlEvents: UIControlEvents.ValueChanged)

removing the Selector()

How to make an UIPickerView with a Done button?

Add this code to your viewDidLoad() instead of method

let picker: UIPickerView
picker = UIPickerView(frame: CGRectMake(0, 200, view.frame.width, 300))
picker.backgroundColor = .whiteColor()

picker.showsSelectionIndicator = true
picker.delegate = self
picker.dataSource = self

let toolBar = UIToolbar()
toolBar.barStyle = UIBarStyle.default
toolBar.isTranslucent = true
toolBar.tintColor = UIColor(red: 76/255, green: 217/255, blue: 100/255, alpha: 1)
toolBar.sizeToFit()

let doneButton = UIBarButtonItem(title: "Done", style: UIBarButtonItem.Style.done, target: self, action: #selector(self. donePicker))
let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: nil, action: nil)
let cancelButton = UIBarButtonItem(title: "Cancel", style: UIBarButtonItem.Style.plain, target: self, action: #selector(self. donePicker))

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

textField1.inputView = picker
textField1.inputAccessoryView = toolBar

Open DatePicker popup directly on button tap

Here is a very simple example of embedding the date picker in a view, then showing / hiding that view on a button tap:

class MyDatePicker: UIView {

var changeClosure: ((Date)->())?
var dismissClosure: (()->())?

let dPicker: UIDatePicker = {
let v = UIDatePicker()
return v
}()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() -> Void {
let blurEffect = UIBlurEffect(style: .dark)
let blurredEffectView = UIVisualEffectView(effect: blurEffect)

let pickerHolderView: UIView = {
let v = UIView()
v.backgroundColor = .white
v.layer.cornerRadius = 8
return v
}()

[blurredEffectView, pickerHolderView, dPicker].forEach { v in
v.translatesAutoresizingMaskIntoConstraints = false
}

addSubview(blurredEffectView)
pickerHolderView.addSubview(dPicker)
addSubview(pickerHolderView)

NSLayoutConstraint.activate([

blurredEffectView.topAnchor.constraint(equalTo: topAnchor),
blurredEffectView.leadingAnchor.constraint(equalTo: leadingAnchor),
blurredEffectView.trailingAnchor.constraint(equalTo: trailingAnchor),
blurredEffectView.bottomAnchor.constraint(equalTo: bottomAnchor),

pickerHolderView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 20.0),
pickerHolderView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -20.0),
pickerHolderView.centerYAnchor.constraint(equalTo: centerYAnchor),

dPicker.topAnchor.constraint(equalTo: pickerHolderView.topAnchor, constant: 20.0),
dPicker.leadingAnchor.constraint(equalTo: pickerHolderView.leadingAnchor, constant: 20.0),
dPicker.trailingAnchor.constraint(equalTo: pickerHolderView.trailingAnchor, constant: -20.0),
dPicker.bottomAnchor.constraint(equalTo: pickerHolderView.bottomAnchor, constant: -20.0),

])

if #available(iOS 14.0, *) {
dPicker.preferredDatePickerStyle = .inline
} else {
// use default
}

dPicker.addTarget(self, action: #selector(didChangeDate(_:)), for: .valueChanged)

let t = UITapGestureRecognizer(target: self, action: #selector(tapHandler(_:)))
blurredEffectView.addGestureRecognizer(t)
}

@objc func tapHandler(_ g: UITapGestureRecognizer) -> Void {
dismissClosure?()
}

@objc func didChangeDate(_ sender: UIDatePicker) -> Void {
changeClosure?(sender.date)
}

}

class ViewController: UIViewController {

let myPicker: MyDatePicker = {
let v = MyDatePicker()
return v
}()
let myButton: UIButton = {
let v = UIButton()
v.setTitle("Show Picker", for: [])
v.setTitleColor(.white, for: .normal)
v.setTitleColor(.lightGray, for: .highlighted)
v.backgroundColor = .blue
return v
}()

override func viewDidLoad() {
super.viewDidLoad()

[myButton, myPicker].forEach { v in
v.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(v)
}
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([

// custom picker view should cover the whole view
myPicker.topAnchor.constraint(equalTo: g.topAnchor),
myPicker.leadingAnchor.constraint(equalTo: g.leadingAnchor),
myPicker.trailingAnchor.constraint(equalTo: g.trailingAnchor),
myPicker.bottomAnchor.constraint(equalTo: g.bottomAnchor),

myButton.centerXAnchor.constraint(equalTo: g.centerXAnchor),
myButton.topAnchor.constraint(equalTo: g.topAnchor, constant: 40.0),
myButton.widthAnchor.constraint(equalTo: g.widthAnchor, multiplier: 0.75),

])

// hide custom picker view
myPicker.isHidden = true

// add closures to custom picker view
myPicker.dismissClosure = { [weak self] in
guard let self = self else {
return
}
self.myPicker.isHidden = true
}
myPicker.changeClosure = { [weak self] val in
guard let self = self else {
return
}
print(val)
// do something with the selected date
}

// add button action
myButton.addTarget(self, action: #selector(tap(_:)), for: .touchUpInside)
}

@objc func tap(_ sender: Any) {
myPicker.isHidden = false
}

}

Here's how it looks on start:

Sample Image

tapping the button will show the custom view:

Sample Image

and here's how it looks on iOS 13 (prior to the new UI):

Sample Image

Opening UIDatePicker under UITextView

No need to use any third party library. This can be achieved very easily. What I understand is that you want the picker to be displayed below the textfield and not as the input view instead of keyboard. Follow the following code to achieve what you want.

Here, name of my ViewController is TextFieldWithDatePickerVC. Don't get confused with name. With following code you would be able to do this very easily without using any third part library. I am attaching a output video also along with the code.

class TextFieldWithDatePickerVC: UIViewController {

lazy var inputTextfield: UITextField = {
let txtField = UITextField()
txtField.backgroundColor = .white
txtField.borderStyle = .roundedRect
txtField.translatesAutoresizingMaskIntoConstraints = false
txtField.placeholder = "Click me to open date picker"
return txtField
}()

lazy var datePicker: UIDatePicker = {
let picker = UIDatePicker()
picker.backgroundColor = .white
picker.addTarget(self, action: #selector(TextFieldWithDatePickerVC.dateChanged(_:)), for: .valueChanged)

let yesterday = Calendar.current.date(byAdding: .day, value: -1, to: Date())
picker.minimumDate = yesterday
picker.minuteInterval = 30
let loc = Locale(identifier: "de")
picker.locale = loc
picker.translatesAutoresizingMaskIntoConstraints = false
return picker
}()

lazy var doneToolBar: UIToolbar = {
let toolbar = UIToolbar()
toolbar.sizeToFit()
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: #selector(doneClicked))
toolbar.setItems([doneButton], animated: true)
toolbar.translatesAutoresizingMaskIntoConstraints = false
return toolbar
}()

lazy var pickerContainer: UIView = {
let view = UIView()
view.backgroundColor = .white
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()

override func viewDidLoad() {
super.viewDidLoad()
setupAutoLayout()
pickerContainer.isHidden = true
inputTextfield.delegate = self
hideDatePicker()
}

func showDatePickerView() {
DispatchQueue.main.async {
self.pickerContainer.isHidden = false
}
}

func hideDatePicker() {
DispatchQueue.main.async {
self.pickerContainer.isHidden = true
}
}

func setupAutoLayout() {
self.view.addSubview(inputTextfield)
self.view.addSubview(pickerContainer)
self.view.bringSubview(toFront: pickerContainer)
pickerContainer.addSubview(doneToolBar)
pickerContainer.addSubview(datePicker)
NSLayoutConstraint.activate([
inputTextfield.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 30),
inputTextfield.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -30),
inputTextfield.topAnchor.constraint(equalTo: view.topAnchor, constant: 60),

pickerContainer.topAnchor.constraint(equalTo: inputTextfield.bottomAnchor, constant: 5),
pickerContainer.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 30),
pickerContainer.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -30),
pickerContainer.heightAnchor.constraint(equalToConstant: datePicker.intrinsicContentSize.height + doneToolBar.intrinsicContentSize.height),

doneToolBar.topAnchor.constraint(equalTo: pickerContainer.topAnchor, constant: 0),
doneToolBar.leftAnchor.constraint(equalTo: pickerContainer.leftAnchor, constant: 0),
doneToolBar.rightAnchor.constraint(equalTo: pickerContainer.rightAnchor, constant: 0),

datePicker.bottomAnchor.constraint(equalTo: pickerContainer.bottomAnchor, constant: 0),
datePicker.leftAnchor.constraint(equalTo: pickerContainer.leftAnchor, constant: 0),
datePicker.rightAnchor.constraint(equalTo: pickerContainer.rightAnchor, constant: 0)
])

}

@objc func dateChanged(_ sender: UIDatePicker) {
print(sender.date)
inputTextfield.text = sender.date.description
}

@objc func doneClicked() {
hideDatePicker()
}

}

extension TextFieldWithDatePickerVC: UITextFieldDelegate {

func textFieldDidBeginEditing(_ textField: UITextField) {
textField.resignFirstResponder()
showDatePickerView()
}

}

Sample Image

How to add datepickerview on IQKeyboardManagerSwift in swift

Add your code of inputView in viewDidLoad() method.

override func viewDidLoad() {
super.viewDidLoad()
let picker = UIDatePicker()
picker.datePickerMode = .date
picker.addTarget(self, action: #selector(updateDateField(sender:)), for: .valueChanged)

// If the date field has focus, display a date picker instead of keyboard.
// Set the text to the date currently displayed by the picker.
self.dischargeDateTextField.inputView = picker
}

and remove that same lines of code from textFieldDidBeginEditing method.

The other methods have been correctly written by you.

@objc func updateDateField(sender: UIDatePicker) {
dischargeDateTextField?.text = formatDateForDisplay(date: sender.date)
}

// Formats the date chosen with the date picker.
fileprivate func formatDateForDisplay(date: Date) -> String {
let formatter = DateFormatter()
formatter.dateFormat = "dd MMM yyyy"
return formatter.string(from: date)
}

UIDatePicker Click done and display text

Change your doneBtnForDate like below

func doneBtnForDate(){

if (dobTxt.text == "Please select your DOB"){
//let selectedDate = How to get picker date without scroll it?
dobTxt.text = selectedDate
}

// IF you want to change date formatting then you need to change in "DateFormatter" below
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .full
dateFormatter.timeStyle = .full
let strDate = dateFormatter.string(from: yourPicker.date)
dobTxt.text = strDate

picker.isHidden = true
toolBar2.isHidden = true
datePicker.isHidden = true
}


Related Topics



Leave a reply



Submit