I have a UITableView with 2 components for users to enter their height in feet and inches. I would like to add a button inside of the UIPicker toolbar that will give the option to change the input from 2 components (feet and inches) to only centimeters. I have added the toolbar button on the UIPickerView however I don't know what to do to make the change back and fourth from feet and inches to cm UIPickerView.
let heightTF: UITextField = {
let tf = UITextField()
tf.placeholder = " Height"
tf.translatesAutoresizingMaskIntoConstraints = false
return tf
}()
var pickerView: UIPickerView!
let feetList = Array(3...9)
let inchList = Array(0...11)
let numberOfComponents = 4
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return numberOfComponents
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if component == 0 {
return feetList.count
}else if component == 2 {
return inchList.count
}else {
return 1
}
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if component == 0 {
return "\(feetList[row])"
}else if component == 1 {
return "ft"
}else if component == 2 {
return "\(inchList[row])"
}else {
return "in"
}
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
let feetIndex = pickerView.selectedRow(inComponent: 0)
let inchIndex = pickerView.selectedRow(inComponent: 2)
heightTF.text = "\(feetList[feetIndex])'\(inchList[inchIndex])''"
}
#objc func donePicker() {
heightTF.resignFirstResponder()
}
#objc func cmAction() {
print("cm pressed")
}
func addDoneButtonOnKeyboard(){
let doneToolbar: UIToolbar = UIToolbar(frame: CGRect.init(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 50))
doneToolbar.barStyle = .default
let cmAction: UIBarButtonItem = UIBarButtonItem(title: "CM", style: .done, target: self, action: #selector(self.cmAction))
let flexSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
let done: UIBarButtonItem = UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(self.doneButtonAction))
let items = [cmAction, flexSpace, done]
doneToolbar.items = items
doneToolbar.sizeToFit()
heightTF.inputAccessoryView = doneToolbar
}
#objc func doneButtonAction(){
heightTF.resignFirstResponder()
}
override func viewDidLoad() {
addDoneButtonOnKeyboard()
self.pickerView = UIPickerView(frame:CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 216))
self.pickerView.delegate = self
self.pickerView.dataSource = self
heightTF.inputView = self.pickerView
self.pickerView.backgroundColor = UIColor.white
heightTF.inputView = self.pickerView
}
First you need to save the type of unit you want to use :
enum UnitType {
case feetInches
case cm
}
var unitType = UnitType.feetInches
Then in the action you change the value between feetInches and cm, and reload all components of the pickerView.
#objc func cmAction() {
switch unitType {
case .feetInches:
// add code to convert from feet/inches to cm
unitType = .cm
self.pickerView.reloadAllComponents()
// add code to select cm row
case .cm:
// add code to convert from cm to feet/inches
unitType = .feetInches
self.pickerView.reloadAllComponents()
// add code to select feet and inches rows
}
}
In each pickerView delegate method you set up according to the value of unitType.
eg :
func numberOfComponents(in pickerView: UIPickerView) -> Int {
switch unitType {
case .feetInches:
return numberOfComponents /* =4 */
case .cm:
return 2 /* (number of cm) and cm */
}
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
switch unitType {
case .feetInches:
if component == 0 {
return "\(feetList[row])"
}else if component == 1 {
return "ft"
}else if component == 2 {
return "\(inchList[row])"
}else {
return "in"
}
case .cm:
if component == 0 {
return "\(cmList[row])"
}else if component == 1 {
return "cm"
}
}
}
...
Related
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)
}
I have two UIPickerviews that appear on one ViewController. I have tried to follow the following tutorial.
I have followed the suggestion in that I have tagged each of the UITextFields (I have 4 in total). See the the image.
Below is the code for the UIPickerViews.
extension DriverViewController: UIPickerViewDelegate, UIPickerViewDataSource {
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if pickerView.tag == 0 {
return tracks.count
} else {
return drivers.count
}
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if pickerView.tag == 0 {
return "\(tracks[row])"
} else {
return "\(drivers[row])"
}
}
The problem I am having is that the tracks array appear on all of the UITextfields.
Below is the code for each of the Arrays and the title of the UIPickerView.
override func viewDidLoad() {
super.viewDidLoad()
tracks = ["Melbourne", "Manama", "Shanghai", "Baku",
"Barcelona", "Monaco", "Montreal","Le Castellet","Spielberg",
"Silverstone","Hockenheim","Budapest","Francorchamps","Monza","Singapore","Sochi","Suzuka","Austin","Interlagos","Abu Dhabi"]
drivers = ["Lewis Hamilton","Antonio Giovinazzi","Kimi Raikkonen","Charles Leclerc","Sebastian Vettel","Romain Grosjean","Kevin Magnussen","Lando Norris",
"Carlos Sainz","Valtteri Bottas","Sergio Perez","Lance Stroll","Pierre Gasly","Max Verstappen","Nico Hulkenberg","Daniel Ricciardo","Alexander Albon","Daniil Kvyat","Robert Kubica","George Russell"]
createTrackPicker()
createDriverPicker()
createToolBar()
// Do any additional setup after loading the view.
}
func createTrackPicker() {
let trackPicker = UIPickerView()
trackPicker.delegate = self
TrackTextField.inputView = trackPicker
}
func createDriverPicker() {
let driverPicker = UIPickerView()
driverPicker.delegate = self
firstTextField.inputView = driverPicker
secondTextField.inputView = driverPicker
thirdTextField.inputView = driverPicker
}
func createToolBar() {
let toolBar = UIToolbar()
toolBar.sizeToFit()
let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(ViewController.dismissKeyboard))
toolBar.setItems([doneButton], animated: false)
toolBar.isUserInteractionEnabled = true
TrackTextField.inputAccessoryView = toolBar
firstTextField.inputAccessoryView = toolBar
secondTextField.inputAccessoryView = toolBar
thirdTextField.inputAccessoryView = toolBar
}
#objc func dismissKeyboard() {
view.endEditing(true)
}
You forgot the tag.
func createDriverPicker() {
let driverPicker = UIPickerView()
driverPicker.tag = 1 // <—-
Sometimes the simplest things prove the hardest to work out! The picker is displayed when users select the user location text field but the selectors are not working. Gone through SO and Apple docs but can't work out why this is.
let locationPicker = UIPickerView()
var locationData = [String]()
override func viewDidLoad() {
super.viewDidLoad()
// Set textfield delegate
userID.delegate = self
userLocation.delegate = self
// Set up picker view for location selection
locationPicker.frame = CGRect(x:0, y: self.view.bounds.height, width: self.view.bounds.width, height: 140)
locationPicker.showsSelectionIndicator = true
let doneButton = UIBarButtonItem(title: "done", style: .plain, target: self, action: #selector(self.closePicker(sender:)))
let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)
let cancelButton = UIBarButtonItem(title: "cancel", style: .plain, target: self, action: #selector(self.closePicker(sender:)))
let toolBar = UIToolbar()
toolBar.barStyle = UIBarStyle.blackOpaque
toolBar.isTranslucent = true
toolBar.setItems([cancelButton, spaceButton, doneButton], animated: false)
toolBar.isUserInteractionEnabled = true
userLocation.inputView = locationPicker
userLocation.inputAccessoryView = toolBar
// Load locations into array
let ref: FIRDatabaseReference = FIRDatabase.database().reference().child("venues")
ref.observe(.value, with: { snapshot in
// Pull out the keys to represent locations
if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot] {
for snap in snapshots {
print("snap key, \(snap.key) and snap value \(snap.value)")
let loc : String = snap.key
self.locationData.append(loc)
}
}
// Now stick the array of locations into the picker view
self.locationPicker.dataSource = self
self.locationPicker.delegate = self
self.locationPicker.reloadAllComponents()
})
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.endEditing(true)
return false
}
func closePicker(sender: AnyObject) {
print("Close picker")
self.locationPicker.isHidden = true
}
func textFieldDidBeginEditing(_ textField: UITextField) {
if let iText = userID.text, let lText = userLocation.text, !iText.isEmpty, !lText.isEmpty
{
print("We have data")
// loginButton.isUserInteractionEnabled = true
// loginButton.alpha = 1.0
}
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return locationData.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return locationData[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
userLocation.text = locationData[row]
}
I have created a UIView class in which I have declared pickerView and implement all necessary delegates. When I click on textfield, no value is shown in pickerView and warning comes in log
no index path for table cell being reused.
Please help me find out the solution of this.
import UIKit
class CustomPickerView: UIView, UIPickerViewDelegate, UIPickerViewDataSource {
var pickerView = UIPickerView()
var pickerString: String?
var pickerArray = NSArray()
class var instance: CustomPickerView
{
let pickerVC = CustomPickerView()
return pickerVC
}
override init(frame: CGRect) {
super.init(frame : frame)
pickerView.delegate = self
pickerView.dataSource = self
pickerView.backgroundColor = UIColor.yellowColor()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setValueOfPicker(text: String, array: NSArray, textField: UITextField) -> Void {
pickerString = text
pickerArray = array
setPicker(textField)
pickerView.reloadAllComponents()
pickerView.selectRow(0, inComponent: 0, animated: true)
}
//MARK:
//MARK: Piker View Delegate & DataSource
//MARK:
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return pickerArray.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if pickerString == "country" {
return pickerArray[row].valueForKey("country") as? String
}
else if pickerString == "printCoupon"
{
return pickerArray[row] as? String
}
return nil
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
}
func setPicker(dataTextField: UITextField)
{
dataTextField.inputView = pickerView;
let doneToolbar: UIToolbar = UIToolbar()
let flexSpace = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: nil, action: nil)
let done: UIBarButtonItem = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Done, target: self, action: #selector(donePickerAction))
let cancle: UIBarButtonItem = UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.Done, target: self, action: #selector(canclePickerAction))
var items = [UIBarButtonItem]()
items.append(cancle)
items.append(flexSpace)
items.append(done)
doneToolbar.sizeToFit()
doneToolbar.items = items
dataTextField.inputAccessoryView = doneToolbar
}
Try to implement this method
func pickerView(pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusingView view: UIView?) -> UIView
{
let pickerLabel = UILabel()
if pickerString == "country" {
pickerLabel.text = pickerArray[row].valueForKey("country") as? String
}
else if pickerString == "printCoupon"
{
pickerLabel.text = pickerArray[row] as? String
}
pickerLabel.textAlignment = NSTextAlignment.Center
return pickerLabel
}
I'm trying to put a done button to my picker view because, when I slide to choose an item the uipickerview automatically select the slided row, so I prefer have a button done:
#IBOutlet var tfProjet: UITextField!
var pvProjetData = ["-Choisir-", "Rachat de crédits", "Renégociation de crédits"]
override func viewDidLoad() {
super.viewDidLoad()
let pickerView = UIPickerView()
if DeviceType.IS_IPHONE_4_OR_LESS {
pickerView.frame=CGRectMake(0, 200, view.frame.width, 100)
} else if DeviceType.IS_IPHONE_5 {
pickerView.frame=CGRectMake(0, 200, view.frame.width, 200)
} else if DeviceType.IS_IPHONE_6 {
pickerView.frame=CGRectMake(0, 200, view.frame.width, 200)
} else if DeviceType.IS_IPHONE_6P {
pickerView.frame=CGRectMake(0, 200, view.frame.width, 250)
} else if UIDevice.currentDevice().userInterfaceIdiom == .Pad {
pickerView.frame=CGRectMake(0, 200, view.frame.width, 300)
}
// pickerView.backgroundColor = .whiteColor()
pickerView.showsSelectionIndicator = true
pickerView.delegate = self
pickerView.dataSource = self
self.pickerView = pickerView
let pickerToolBar = UIToolbar()
pickerToolBar.barStyle = UIBarStyle.Black //you can change the style
pickerToolBar.translucent = true
pickerToolBar.tintColor = UIColor.whiteColor() // or other colours
pickerToolBar.sizeToFit()
let spaceButtonPicker = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: nil, action: nil)
let cancelButtonPicker = UIBarButtonItem(title: "Ok", style: UIBarButtonItemStyle.Plain, target: self, action: "cancelDatePicker:")
pickerToolBar.setItems([cancelButtonPicker, spaceButtonPicker], animated: false)
pickerToolBar.userInteractionEnabled = true
tfDateNaissance.inputAccessoryView = pickerToolBar
tfProjet.inputView = pickerView
tfProjet.inputAccessoryView = pickerToolBar
}
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int{
return 1
}
func selectRow(row: Int, inComponent component: Int, animated: Bool){
}
func updatePicker(){
self.pickerView!.reloadAllComponents()
pickerView.selectRow(0, inComponent: 0, animated: false)
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if tfProjet.isFirstResponder(){
return pvProjetData.count
}
return 1
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if tfProjet.isFirstResponder(){
return pvProjetData[row]
}
return ""
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if tfProjet.isFirstResponder(){
let itemselected = pvProjetData[row]
tfProjet.text = itemselected
self.tfProjet.endEditing(true)
}
}
I see the button Ok, but it doesn't work, when I slide the row is automatically selected.