Reputation: 1084
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
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
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