How to use UIPickerview and UIDatePicker on the same Viewcontroller? - ios

I have three TextFields in a Viewcontroller. After clicking the first I want to use UIPickerview to select something. The second TF should open the keyboard and the third one should open UIDatepicker.
import UIKit
class NewCompetitionViewController: UIViewController, UITextViewDelegate,UIPickerViewDataSource, UIPickerViewDelegate{
#IBOutlet weak var programTextField: UITextField!
let program = ["Big Target - 60 Shots",
"Big Target - 30 Shots",
"Small Target - 40 Shots"]
var selectedProgram: String?
let datePicker = UIDatePicker()
#IBOutlet weak var locationTextField: UITextField!
#IBOutlet weak var dateTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
createProgramPicker()
createDatePicker()
}
#IBAction func saveButton(_ sender: UIButton) {
dismiss(animated: true)
}
#IBAction func cancelButton(_ sender: UIButton) {
dismiss(animated: true)
}
// PROGRAM PICKER
func createProgramPicker(){
let programPicker = UIPickerView()
let toolBarPP = UIToolbar()
programPicker.delegate = self
// Customizations
programPicker.backgroundColor = .white
toolBarPP.sizeToFit()
let spaceButtonPP = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let doneButtonPP = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(dismissKeyboard))
toolBarPP.setItems([spaceButtonPP, doneButtonPP], animated: false)
//toolBarPP.isUserInteractionEnabled = true
programTextField.inputAccessoryView = toolBarPP
programTextField.inputView = programPicker
}
// DISMISS KEYBOARD
#objc func dismissKeyboard(){
self.view.endEditing(true)
}
// DATE PICKER
func createDatePicker(){
datePicker.datePickerMode = .date
datePicker.backgroundColor = .white
let toolbarDP = UIToolbar()
toolbarDP.sizeToFit()
// flexible Space Button and Done button
let spaceButtonDP = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let doneButtonDP = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(doneClicked))
toolbarDP.setItems([spaceButtonDP, doneButtonDP], animated: false)
//toolbarDP.isUserInteractionEnabled = true
dateTextField.inputAccessoryView = toolbarDP
dateTextField.inputView = datePicker
}
#objc func doneClicked(){
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd/MM/YYYY"
dateFormatter.dateStyle = .medium
dateFormatter.timeStyle = .none
dateTextField.text = dateFormatter.string(from: datePicker.date)
self.view.endEditing(true)
}
// Returns true after "Done" clicked
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
// Hide the keyboard
textField.resignFirstResponder()
return true
}
private func textFieldDidEndEditing(_ textField: UITextField){
locationTextField.text = textField.text
}
}
extension NewCompetitionViewController: UIPickerViewDelegate, UIPickerViewDataSource {
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return program.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return program[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
selectedProgram = program[row]
programTextField.text = selectedProgram
}
}
I can start the simulation and the UIPickerview works. Also the input on the keyboard at the second textfield. But if I open the datePicker and I click the done-button the display slides up from the bottom to the top with a transparent blue look.

Here are some screenshots:
Main screen
Program selection
Date selection
Bluescreen after clicking done

Related

Picker buttons do not show up

I am attempting to add "done" and "cancel" buttons in a toolbar above a pickerView that will be used to change the value of a label. The label should only be changed when "done" is clicked not when UIPicker received rowSelected.
I can't understand why my "done" and "cancel" buttons do not show above my picker? I'm sure this will be marked as duplicate, but I've done something very similar in Swift 4, and this doesn't seem to work in Swift 5.
import UIKit
class ViewController: UIViewController, UITextFieldDelegate, UIPickerViewDelegate, UIPickerViewDataSource {
#IBOutlet weak var freq: UILabel!
var freqOptions = ["Hz", "kHz", "MHz"]
var freqPicker = UIPickerView()
#IBOutlet weak var freqTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
freqPicker = UIPickerView( frame: CGRect(x: 0, y: 100, width: self.view.frame.width, height: 216) )
freqPicker.backgroundColor = UIColor.white
freqPicker.delegate = self
freqPicker.dataSource = self
freqPicker.isHidden = true
let toolBar = UIToolbar()
let cancelItem = UIBarButtonItem(
title: "Cancel",
style: .plain,
target: self,
action: #selector(cancelFreqInput)
)
let middleItem = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let doneItem = UIBarButtonItem(
title: "Done",
style: .done,
target: self,
action: #selector(confirmFreqInput)
)
toolBar.setItems( [cancelItem, middleItem, doneItem], animated : false )
toolBar.sizeToFit()
view.addSubview(freqPicker)
let freqTap = UITapGestureRecognizer(target: self, action: #selector(freqTap(gestureReconizer:)))
freq.addGestureRecognizer(freqTap)
freqTextField.inputView = freqPicker
freqTextField.inputAccessoryView = toolBar
freqTextField.isHidden = true
freq.isUserInteractionEnabled = true
}
#objc func cancelFreqInput() {
freqTextField.resignFirstResponder()
freq.text = "Hz"
freqTextField.isHidden = true
}
#objc func confirmFreqInput() {
freqTextField.resignFirstResponder()
freqTextField.isHidden = true
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return freqOptions.count
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
freq.text = freqOptions[row]
self.view.endEditing(true)
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return freqOptions[row]
}
#objc func freqTap(gestureReconizer: UITapGestureRecognizer) {
freqPicker.isHidden = false
}
}
you don't need to add a picker as a subview. You just need to set it Like an input view (and you already done it). I modified you code. You can just compare and check what was wrong there
class ViewController: UIViewController, UITextFieldDelegate, UIPickerViewDelegate, UIPickerViewDataSource {
#IBOutlet weak var freq: UILabel!
var freqOptions = ["Hz", "kHz", "MHz"]
var freqPicker = UIPickerView()
#IBOutlet weak var freqTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
freqPicker = UIPickerView()
freqPicker.backgroundColor = UIColor.white
freqPicker.delegate = self
freqPicker.dataSource = self
// freqPicker.isHidden = true
let toolBar = UIToolbar()
let cancelItem = UIBarButtonItem(
title: "Cancel",
style: .plain,
target: self,
action: #selector(cancelFreqInput)
)
let middleItem = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let doneItem = UIBarButtonItem(
title: "Done",
style: .done,
target: self,
action: #selector(confirmFreqInput)
)
toolBar.setItems( [cancelItem, middleItem, doneItem], animated : false )
toolBar.sizeToFit()
// view.addSubview(freqPicker)
let freqTap = UITapGestureRecognizer(target: self, action: #selector(freqTap(gestureReconizer:)))
freq.addGestureRecognizer(freqTap)
freqTextField.inputView = freqPicker
freqTextField.inputAccessoryView = toolBar
freqTextField.isHidden = true
freq.isUserInteractionEnabled = true
freqPicker.reloadComponent(0)
}
#objc func cancelFreqInput() {
freqTextField.resignFirstResponder()
freq.text = "Hz"
freqTextField.isHidden = true
}
#objc func confirmFreqInput() {
freq.text = freqOptions[freqPicker.selectedRow(inComponent: 0)]
self.view.endEditing(true)
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return freqOptions.count
}
// func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
// freq.text = freqOptions[row]
// self.view.endEditing(true)
// }
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return freqOptions[row]
}
#objc func freqTap(gestureReconizer: UITapGestureRecognizer) {
freqTextField.becomeFirstResponder()
}
}

Error in setting textfield with Date UIPicker and Normal Picker, I tried a lot of things but getting error

I am setting up text fields with Datepicker and Normal Picker but getting error for the same , I am unable to do it. below is the code
class SetupViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
#IBOutlet weak var genderPickerInput: UITextField!
#IBOutlet weak var datePickerInput: UITextField!
private var datepicker: UIDatePicker?
var genderPickerData: [String] = [String]()
override func viewDidLoad() {
super.viewDidLoad()
let genderPicker = UIPickerView()
genderPickerInput.inputView = genderPicker
genderPicker.delegate = self
datepicker = UIDatePicker()
datepicker?.datePickerMode = .date
datepicker?.addTarget(self, action: #selector(ViewController.dateChanged(datepicker)), for: .valueChanged)
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(ViewController.viewTapped(UITapGestureRecognizer)))
view.addGestureRecognizer(tapGesture)
datePickerInput.inputView = datepicker
genderPickerData = ["Male", "Female", "Other"]
// Do any additional setup after loading the view.
}
// MARK: UIPickerView Delegation
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView( _ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return genderPickerData.count
}
func pickerView( _ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return genderPickerData[row]
}
func pickerView( pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
genderPickerInput.text = genderPickerData[row]
}
func dateChanged(datepicker : UIDatePicker){
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MM/dd/yyyy"
datePickerInput.text = dateFormatter.string(from: datepicker.date)
view.endEditing(true)
}
func viewTapped(gestureRecognizer: UITapGestureRecognizer){
view.endEditing(true)
}
}
Error 1
Type 'ViewController' has no member 'dateChanged'
Error 2
Type 'ViewController' has no member 'viewTapped', did you mean 'viewLoaded'
You need to remove ViewController. or replace it with self.
datepicker?.addTarget(self, action: #selector(self.dateChanged), for: .valueChanged)
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.viewTapped))
func dateChanged(_ datepicker : UIDatePicker){}
func viewTapped(_ gestureRecognizer: UITapGestureRecognizer){}

Swift - Programmatically create UIPickerView

I created PickerView, but this does not open the PickerView I created. Where do I make a mistake? Why PickerView doesn't open. I added picker view in the text field but it doesn't work. I added it to viewDidLoad, but when I click a text field, picker view does not open.
class EnergyChart: UIViewController , UIPickerViewDelegate, UIPickerViewDataSource {
var picker = UIPickerView()
var gradePickerValues1 : [String] = ["...", ...]
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return gradePickerValues1.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return gradePickerValues1[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int){
getDevice.text = gradePickerValues1[row]
switch row {
case 0: break
default: break
}
self.view.endEditing(true)
}
#objc func cancelTapped() {
self.view.endEditing(true)
}
let getDevice: UITextField = {
let textFieldframe = CGRect()
let textField2 = SkyFloatingLabelTextFieldWithIcon(frame: textFieldframe, iconType: .image)
...
return textField2
}()
#objc func GetDevice() {
self.getDevice.text = self.gradePickerValues1[0]
}
override func viewDidLoad() {
super.viewDidLoad()
picker.backgroundColor = .white
picker.showsSelectionIndicator = true
picker.delegate = self
picker.dataSource = self
getDevice.inputView = picker
GetDevice()
let toolBar = UIToolbar()
toolBar.barStyle = UIBarStyle.default
toolBar.isTranslucent = true
toolBar.tintColor = UIColor(..)
toolBar.sizeToFit()
let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: nil, action: nil)
let cancelButton = UIBarButtonItem(title: "İptal", style: UIBarButtonItem.Style.plain, target: self, action: #selector(cancelTapped))
toolBar.setItems([cancelButton, spaceButton], animated: false)
toolBar.isUserInteractionEnabled = true
getDevice.inputAccessoryView = toolBar
view.addSubview(getDevice)
getDevice.snp.makeConstraints { (make) in
make.centerX.equalTo(view).offset(50)
make.top.equalTo(view).offset(510)
make.height.equalTo(50)
make.width.equalTo(200)
}

how do i show date picker when clicked on textfield

this is my code
- #IBOutlet weak var txt1: UITextField!
#IBOutlet weak var txt2: UITextField!
#IBOutlet weak var txt3: UITextField!
#IBOutlet weak var txt4: UITextField!
#IBOutlet weak var txt5: UITextField!
#IBOutlet weak var txt6: UITextField!
#IBOutlet weak var txt7: UITextField!
#IBOutlet weak var picker: UIPickerView!
var category = ["Male", "Female", "Others"]
let datePicker = UIDatePicker()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
picker.isHidden = true
txt3.delegate = self
self.txt3.inputView = picker
//txt3.inputView = category[row]
}
// returns the # of rows in each component..
func pickerView(pickerView: UIPickerView!, numberOfRowsInComponent component: Int) -> Int{
return category.count
}
func pickerView(pickerView: UIPickerView!, titleForRow row: Int, forComponent component: Int) -> String! {
return category[row]
}
func pickerView(pickerView: UIPickerView!, didSelectRow row: Int, inComponent component: Int)
{
txt3.text = category[row]
// category.isHidden = true;
}
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
if textField == txt3 {
//resignFirstResponder()
//picker.isHidden = true
}
return true
}
}
#IBAction func txt3(_ sender: Any) {
func showDatePicker(){
//Formate Date
datePicker.datePickerMode = .date
//ToolBar
let toolbar = UIToolbar();
toolbar.sizeToFit()
//done button & cancel button
let doneButton = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.bordered, target: self, action:
Selector(("donedatePicker")))
//let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)
// let cancelButton = UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.bordered, target: self, action:
Selector("cancelDatePicker"))
toolbar.setItems([doneButton], animated: false)
// add toolbar to textField
txt3.inputAccessoryView = toolbar
// add datepicker to textField
txt3.inputView = datePicker
}
func donedatePicker(){
//For date formate
let formatter = DateFormatter()
formatter.dateFormat = "dd/MM/yyyy"
txt3.text = formatter.string(from: datePicker.date)
//dismiss date picker dialog
self.view.endEditing(true)
}
func cancelDatePicker(){
//cancel button dismiss datepicker dialog
self.view.endEditing(true)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
Blockquote
override func viewDidLoad(){
super.viewDidLoad()
picker.isHidden = true
txt3.delegate = self
//self.txt3.inputView = picker // don't do this
self.txt3.inputView = datePicker // do like this.
let doneButton = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.plain, target: self, action: #selector(self.doneButton))
let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)
let cancelButton = UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.plain, target: self, action: #selector(self.doneButton)
toolBar.setItems([cancelButton, spaceButton, doneButton], animated: false)
toolBar.isUserInteractionEnabled = true
txt3.inputAccessoryView = toolBar
}
func doneButton(){
let selectedDate = datePicker.date
print(selectedDate)
txt3.resignFirstResponder()
}
It will automatically open the date picker.
txt3.inputView = picker
and remove
picker.isHidden = true
This should do the trick!
first, you add this..
txt3.inputView = picker
then you add
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
if textField == txt3 {
picker.isHidden = false
}
else {
picker.isHidden = true
}
return true
}

Setting UITextField's inputView property to a UIPicker not working in Swift

Hello I am trying to pop a UIPickerView view programmatically when user clicks on textfield. I have tried this but it doesn't doing anything, it isn't working. Nothing is happening when I click the textfield
class UserProfileTableViewController: UITableViewController,UITextFieldDelegate,UIPickerViewDelegate,UIPickerViewDataSource {
var itemPicker: UIPickerView! = UIPickerView()
#IBOutlet weak var genderTxtField: UITextField!
var gender = ["MALE","FEMALE"]
override func viewDidLoad() {
super.viewDidLoad()
genderTxtField.delegate = self
itemPicker!.delegate = self
itemPicker!.dataSource = self
itemPicker!.backgroundColor = UIColor.blackColor()
self.genderTxtField.inputView = itemPicker
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int{
return 1
}
// returns the # of rows in each component..
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int{
return gender.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return gender[row]
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int)
{
genderTxtField.text = gender[row]
//.hidden = true;
}
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
itemPicker.hidden = false
return false
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
The issue in your current code is in this method:
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
itemPicker.hidden = false
return false // <--- this is not letting the textField become editable
}
I would suggest removing this method entirely.
Ok so I have dug out something similar I wrote, It uses a datepicker but the general code is the same.
var datePicker: UIDatePicker!
#IBOutlet var dateFrom: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
self.setUpDatePicker()
}
func setUpDatePicker() {
datePicker.datePickerMode = UIDatePickerMode.Date
let toolBar = UIToolbar(frame: CGRect(x: 0, y: 0, width: 0, height: 44))
let doneBtn = UIBarButtonItem(title: "Select", style: UIBarButtonItemStyle.Done, target: self, action: "selectDate")
let space = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: nil, action: nil)
toolBar.setItems([space, doneBtn], animated: false)
YOURTEXTFIELD.inputAccessoryView = toolBar
YOURTEXTFIELD.inputView = datePicker
}
Then you add in a function to handle the done button press
func selectDate() {
let formatter = NSDateFormatter()
formatter.dateFormat = "dd-MM-yyyy";
YOURTEXTFIELD.text = formatter.stringFromDate(datePicker.date)
YOURTEXTFIELD.resignFirstResponder()
}
Just replace YOURTEXTFIELD with your version genderTxtField and change the date picker to your picker.
Dont forget to check if everything is linked up
itemPicker!.backgroundColor = UIColor.blackColor()
change to
itemPicker!.backgroundColor = UIColor.whiteColor()
then remove
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
itemPicker.hidden = false
return false
}
good luck!
func textFieldShouldBeginEditing(textField: UITextField) -> Bool
{
itemPicker.hidden = false
return true
}
You just have to change false to true in func textFieldShouldBeginEditing.

Resources