USER9561
USER9561

Reputation: 1084

DatePicker opening on second click on TextField

I have a TextField on click of which a custom date picker should open. But on first click keyboard opens and on second click the date picker opens. Please help me how to show date picker on first click. eodDateTime my TextField here where i want date picker to show on click of textfield and show the selected date time in the same textfield

Here is my code:

import UIKit

class ATMDiscrepancyViewController: UIViewController, UIScrollViewDelegate,UITextFieldDelegate
{
var datePicker : UIDatePicker!

@IBOutlet weak var remarks: UITextField!
@IBOutlet weak var lastTransaction: UITextField!
@IBOutlet weak var eodDateTime: UITextField!

var atmData : SelectedATM! 
@IBOutlet weak var scrollView: UIScrollView!
var activeField: UITextField?

var selectedDate : String = ""
var alertControllerScanCode:CustViewController!
let button = UIButton(type: UIButtonType.custom)
}

@IBOutlet weak var saveAction: UIButton!

func datePickerValuechanged (sender : UIDatePicker)
{
    let dateFormatter = DateFormatter()
    dateFormatter.dateStyle = DateFormatter.Style.medium
    dateFormatter.timeStyle = DateFormatter.Style.none
    eodDateTime.text = dateFormatter.string(from: sender.date)
    selectedDate = dateFormatter.string(from: sender.date)
    self.view.endEditing(true)
}


@IBAction func eodAction(_ sender: UITextField) {

    deregisterFromKeyboardNotifications()
    self.button.isHidden=true
    self.pickUpDate(eodDateTime)
}
func pickUpDate(_ textField : UITextField){
    deregisterFromKeyboardNotifications()
    self.button.isHidden=true
    self.button.isEnabled = false
     NotificationCenter.default.addObserver(self, selector: #selector(ATMDiscrepancyViewController.keyboardRemoveReturn(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    // DatePicker
    self.datePicker = UIDatePicker(frame:CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 216))
    self.datePicker.backgroundColor = UIColor.white
    self.datePicker.datePickerMode = UIDatePickerMode.dateAndTime
    textField.inputView = self.datePicker

    // ToolBar
    let toolBar = UIToolbar()
    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(ATMDiscrepancyViewController.doneClick))
    let spaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
    let cancelButton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(ATMDiscrepancyViewController.cancelClick))
    toolBar.setItems([cancelButton, spaceButton, doneButton], animated: false)
    toolBar.isUserInteractionEnabled = true
    textField.inputAccessoryView = toolBar
}


func doneClick() {
    let dateFormatter1 = DateFormatter()
   // let timeFormatter = DateFormatter()
    dateFormatter1.dateStyle = .medium
    dateFormatter1.timeStyle = .none
    dateFormatter1.dateFormat = "yyyy-MM-dd HH:mm:SS"
    eodDateTime.text = dateFormatter1.string(from: datePicker.date)

    eodDateTime.resignFirstResponder()
}
func cancelClick() {
    eodDateTime.resignFirstResponder()
}

func handleDatePicker(sender: UIDatePicker) {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "yyyy-MM-dd"
    eodDateTime.text = dateFormatter.string(from: sender.date)
    selectedDate = dateFormatter.string(from: sender.date) 
}

func doneButton(sender:UIButton)
{
    eodDateTime.resignFirstResponder() // To resign the inputView on clicking done.
    eodDateTime.text = selectedDate
}

override func viewDidLoad() {
    super.viewDidLoad()
    self.navigationItem.title = "Discrepancy"

    registerForKeyboardNotifications()

    button.setTitle("Return", for: UIControlState())
    button.setTitleColor(UIColor.black, for: UIControlState())
    button.frame = CGRect(x: 0, y: 163, width: 106, height: 53)
    button.adjustsImageWhenHighlighted = false
    button.addTarget(self, action: #selector(ATMDiscrepancyViewController.Done(_:)), for: UIControlEvents.touchUpInside)

    let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(ATMDiscrepancyViewController.dismissKeyboard))
    view.addGestureRecognizer(tap)

    self.remarks.delegate = self
    self.lastTransaction.delegate = self
    self.eodDateTime.delegate = self 
}


override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    self.view.endEditing(true)
}

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

    if textField == self.lastTransaction || textField == self.remarks {

         let textString = (textField.text as! NSString).replacingCharacters(in: range, with: string)

         return true
    }
    let allowedCharacters = CharacterSet.decimalDigits
    let characterSet = CharacterSet(charactersIn: string)
    return allowedCharacters.isSuperset(of: characterSet)
}

func textFieldShouldReturn(_ textField: UITextField) -> Bool {

    self.lastTransaction.resignFirstResponder()
    self.remarks.resignFirstResponder()

        self.button.isHidden=true
         self.lastTransaction.becomeFirstResponder()
        dismissKeyboard()

        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)

    }
    if textField == self.lastTransaction
    {
        if isEmptyValidate(edit: self.lastTransaction) == true
        {
            return false
        }
        self.button.isHidden = true
        self.remarks.becomeFirstResponder()
    }

    if textField == self.remarks
    {
        if isEmptyValidate(edit: self.remarks)
        {
            return false
        }
    }
    return true
}

 func valid() -> Bool
{

    if isEmptyValidate(edit: eodDateTime) == true
    {
        return false
    }
    return true
}

func isEmptyValidate(edit : UITextField) ->Bool
{
    if edit.text?.isEmpty ?? true
    {
        edit.attributedPlaceholder = NSAttributedString(string: "Enter value", attributes: [NSForegroundColorAttributeName : UIColor.red])
        return true
    }
    return false
}


func registerForKeyboardNotifications(){

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)

}


func deregisterFromKeyboardNotifications(){
    //Removing notifies on keyboard appearing
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}

func keyboardWasShown(notification: NSNotification){
    //Need to calculate keyboard exact size due to Apple suggestions
    self.scrollView.isScrollEnabled = true
    var info = notification.userInfo!
    let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
    let contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize!.height, 0.0)

    self.scrollView.contentInset = contentInsets
    self.scrollView.scrollIndicatorInsets = contentInsets

    var aRect : CGRect = self.view.frame
    aRect.size.height -= keyboardSize!.height
    if let activeField = self.activeField{
        if (!aRect.contains(activeField.frame.origin)){
            self.scrollView.scrollRectToVisible(activeField.frame, animated: true)
        }
    }
}

func keyboardWillBeHidden(notification: NSNotification){
    //Once keyboard disappears, restore original positions
    var info = notification.userInfo!
    self.view.endEditing(true)
    self.scrollView.isScrollEnabled = true
}

func textFieldDidBeginEditing(_ textField: UITextField){
    if textField == self.lastTransaction  {
        //self.button.isHidden = true;

         NotificationCenter.default.addObserver(self, selector: #selector(ATMDiscrepancyViewController.keyboardRemoveReturn(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    }

    activeField = textField

    NotificationCenter.default.addObserver(self, selector: #selector(ATMDiscrepancyViewController.keyboardWillShow(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
}

func textFieldDidEndEditing(_ textField: UITextField){
    activeField = nil
}
func dismissKeyboard() {
    view.endEditing(true)
}


func keyboardWillShow(_ note : Notification) -> Void{
    DispatchQueue.main.async { () -> Void in
        self.button.isHidden = false
        self.scrollView.isScrollEnabled = true
        var info = note.userInfo!
        let keyBoardWindow = UIApplication.shared.windows.last
        self.button.frame = CGRect(x: 0, y: (keyBoardWindow?.frame.size.height)!-53, width: 106, height: 53)
        keyBoardWindow?.addSubview(self.button)
        keyBoardWindow?.bringSubview(toFront: self.button)
        let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
        let contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize!.height, 0.0)

        self.scrollView.contentInset = contentInsets
        self.scrollView.scrollIndicatorInsets = contentInsets

        var aRect : CGRect = self.view.frame
        aRect.size.height -= keyboardSize!.height
        if let activeField = self.activeField {
            if (!aRect.contains(activeField.frame.origin)){
                self.scrollView.scrollRectToVisible(activeField.frame, animated: true)
            }
        }

        UIView.animate(withDuration: (((note.userInfo! as NSDictionary).object(forKey: UIKeyboardAnimationCurveUserInfoKey) as AnyObject).doubleValue)!, delay: 0, options: UIViewAnimationOptions.curveEaseIn, animations: { () -> Void in
            self.view.frame = self.view.frame.offsetBy(dx: 0, dy: 0)
        }, completion: { (complete) -> Void in

        })   
    }
}

func Done(_ sender : UIButton){

    DispatchQueue.main.async { () -> Void in

        self.textFieldShouldReturn(self.activeField!)
    }    
}

func keyboardRemoveReturn(_ note : Notification) -> Void{
    DispatchQueue.main.async { () -> Void in
        self.button.isHidden = true

        UIView.animate(withDuration: (((note.userInfo! as NSDictionary).object(forKey: UIKeyboardAnimationCurveUserInfoKey) as AnyObject).doubleValue)!, delay: 0, options: UIViewAnimationOptions.curveEaseIn, animations: { () -> Void in
            self.view.frame = self.view.frame.offsetBy(dx: 0, dy: 0)
        }, completion: { (complete) -> Void in

        })
    }

}

}

Thanks

Upvotes: 0

Views: 1301

Answers (2)

Mahendra
Mahendra

Reputation: 8904

Make first responder on button click

@IBAction func eodAction(_ sender: UITextField) {

    deregisterFromKeyboardNotifications()
    self.button.isHidden=true
    eodDateTime.becomeFirstResponder()
//        self.pickUpDate(eodDateTime)
}

And implement textFieldShouldBeginEditing method to show date picket in input view

extension ATMDiscrepancyViewController: UITextFieldDelegate {

func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
    if textField == eodDateTime {
        self.pickUpDate(eodDateTime)
    }
}
}

Upvotes: 1

Nitish
Nitish

Reputation: 14113

I could not understand the whole code but the best way to fix this would be to assign the picker as inputView in viewDidLoad. So place the following code, you are using, in viewDidLoad and it should work fine :

self.datePicker = UIDatePicker(frame:CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 216))
self.datePicker.backgroundColor = UIColor.white
self.datePicker.datePickerMode = UIDatePickerMode.dateAndTime
textField.inputView = self.datePicker

Upvotes: 1

Related Questions