magali
magali

Reputation: 3

Opening UIDatePicker under UITextView

I am writing an app, where when clicking on a UITexView an UIDatePicker opens. I want the UIDatePicker to pop up underneath the UITextView and not to come up as the keyboard from the bottom.

I am just starting with IOS app development and I hope someone can help me.

datePicker = UIDatePicker

and

inputTextfield = UITextField

myCode:

//Function to create the datepicker
func createDatePicker(){
            //create instance of the datepicker
            datePicker = UIDatePicker()
            //sets format, so only day month and year can be selected
            //datePicker?.datePickerMode = .date
            datePicker?.backgroundColor = .white
            datePicker?.addTarget(self, action: #selector(ViewController.dateChanged(datePicker:)), for: .valueChanged)
            //to limit the datepicker, you can not pick a date older than yesterday
            let yesterday = Calendar.current.date(byAdding: .day, value: -1, to: Date())
            datePicker?.minimumDate = yesterday
            datePicker?.minuteInterval = 30
            let loc = Locale(identifier: "de")
            datePicker?.locale = loc

            let tapGesture = UITapGestureRecognizer(target: self, action: #selector(ViewController.viewTapped(gesturRecognizer:)))

            view.addGestureRecognizer(tapGesture)

            inputTextfield.inputView = datePicker


            //create a toolbar
            let toolbar = UIToolbar()
            toolbar.sizeToFit()

            //add done button to the toolbar
            let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: #selector(doneClicked))
            toolbar.setItems([doneButton], animated: true)


            inputTextfield.inputAccessoryView = toolbar
        }


        //function to select a date
        @objc func dateChanged(datePicker: UIDatePicker){

            //selected date by the user
            let dateFormate = DateFormatter()
            //Jonas das ist vllt für dich relevant, man kann es so verändern wie man will
            dateFormate.dateFormat = "MM/dd/yyyy"
            inputTextfield.text = dateFormate.string(from: datePicker.date)
        }

        //function to close the datepicker, when tapping on the inputText again -handler method
        @objc func viewTapped(gesturRecognizer: UITapGestureRecognizer){
            view.endEditing(true)
        }

        //function to close the datepicker when clicking on the done button
        @objc func doneClicked(){
            self.view.endEditing(true)
        }

Upvotes: 0

Views: 1413

Answers (4)

iOS_MIB
iOS_MIB

Reputation: 1895

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()
    }

}

enter image description here

Upvotes: 1

Prabhat Pandey
Prabhat Pandey

Reputation: 277

let dateFormatter = DateFormatter()
let locale = NSLocale.current
var datePicker : UIDatePicker!
let toolBar = UIToolbar()

func doDatePicker() {
    // DatePicker
    self.datePicker = UIDatePicker(frame:CGRect(x: 0, y: UIScreen.main.bounds.height - 200.0, width: UIScreen.main.bounds.width, height: 200))
    self.datePicker?.backgroundColor = UIColor.white
    self.datePicker?.datePickerMode = UIDatePickerMode.dateAndTime
    datePicker.center = view.center
    view.addSubview(self.datePicker)
    // ToolBar
    toolBar.frame = CGRect(x: 0, y: UIScreen.main.bounds.height - 240.0, width: UIScreen.main.bounds.width, height: 44.0)
    toolBar.barStyle = .default
    toolBar.isTranslucent = true
    toolBar.tintColor = UIColor(red: 92/255, green: 216/255, blue: 255/255, alpha: 1)
    toolBar.sizeToFit()
    // Adding Button ToolBar
    let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(doneClick))
    let spaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
    let cancelButton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(cancelClick))
    toolBar.setItems([cancelButton, spaceButton, doneButton], animated: true)
    self.view.addSubview(toolBar)
    self.toolBar.isHidden = false
}

@objc func doneClick() {
    let dateFormatter1 = DateFormatter()
    dateFormatter1.dateStyle = .medium
    dateFormatter1.timeStyle = .none
    //self.datePicker.resignFirstResponder()
    datePicker.isHidden = true
    self.toolBar.isHidden = true
}

@objc func cancelClick() {
    datePicker.isHidden = true
    self.toolBar.isHidden = true
}

Upvotes: 0

Sumit Jain
Sumit Jain

Reputation: 156

See this: This would be helpfull for you. https://blog.apoorvmote.com/change-textfield-input-to-datepicker/

Upvotes: 0

BhargavR
BhargavR

Reputation: 1133

Here is a third party library which I guess will meet your expectation :

https://github.com/angelopino/APJTextPickerView

This subclasses the UITextField and very useful. Refer the example for more details.

Upvotes: 0

Related Questions