How to make an UIPickerView with a Done button?

IosSwiftUipickerview

Ios Problem Overview


I am having difficulties to make an UIPickerView with a done button to appear when the users taps a UITextField. This is my code so far. Everything builds fine, but when I tap the text field, the keyboard appears, not the picker.

class ViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {


@IBOutlet var textField1: UITextField!

let pickerData = ["11", "12", "13"]





@IBAction func textButton(sender: AnyObject) {
    
    let picker: UIPickerView
    picker = UIPickerView(frame: CGRectMake(0, 200, view.frame.width, 300))
    picker.backgroundColor = .whiteColor()
    
    picker.showsSelectionIndicator = true
    picker.delegate = self
    picker.dataSource = self
    
    let toolBar = UIToolbar()
    toolBar.barStyle = UIBarStyle.Default
    toolBar.translucent = true
    toolBar.tintColor = UIColor(red: 76/255, green: 217/255, blue: 100/255, alpha: 1)
    toolBar.sizeToFit()
    
    let doneButton = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Plain, target: self, action: "donePicker")
    let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: nil, action: nil)
    let cancelButton = UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.Plain, target: self, action: "donePicker")
    
    toolBar.setItems([cancelButton, spaceButton, doneButton], animated: false)
    toolBar.userInteractionEnabled = true
    
    textField1.inputView = picker
    textField1.inputAccessoryView = toolBar
    
    

    
}



override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
    return 1
}

func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
    return pickerData.count
}

func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
    return pickerData[row]
}

func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
    textField1.text = pickerData[row]
}

func donePicker() {
    
    textField1.resignFirstResponder()
    
}




}

Ios Solutions


Solution 1 - Ios

Add this code to your viewDidLoad() instead of method

let picker: UIPickerView
picker = UIPickerView(frame: CGRectMake(0, 200, view.frame.width, 300))
picker.backgroundColor = .whiteColor()

picker.showsSelectionIndicator = true
picker.delegate = self
picker.dataSource = self

let toolBar = UIToolbar()
toolBar.barStyle = UIBarStyle.default
toolBar.isTranslucent = true
toolBar.tintColor = UIColor(red: 76/255, green: 217/255, blue: 100/255, alpha: 1)
toolBar.sizeToFit()

let doneButton = UIBarButtonItem(title: "Done", style: UIBarButtonItem.Style.done, target: self, action: #selector(self. donePicker))
let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: nil, action: nil)
let cancelButton = UIBarButtonItem(title: "Cancel", style: UIBarButtonItem.Style.plain, target: self, action: #selector(self. donePicker))

toolBar.setItems([cancelButton, spaceButton, doneButton], animated: false)
toolBar.userInteractionEnabled = true

textField1.inputView = picker
textField1.inputAccessoryView = toolBar

Solution 2 - Ios

I think it's better to make a custom class to remove code from controller.

Swift 4/5 example:

import Foundation
import UIKit

protocol ToolbarPickerViewDelegate: class {
    func didTapDone()
    func didTapCancel()
}

class ToolbarPickerView: UIPickerView {
    
    public private(set) var toolbar: UIToolbar?
    public weak var toolbarDelegate: ToolbarPickerViewDelegate?
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.commonInit()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.commonInit()
    }
    
    private func commonInit() {
        let toolBar = UIToolbar()
        toolBar.barStyle = UIBarStyle.default
        toolBar.isTranslucent = true
        toolBar.tintColor = .black
        toolBar.sizeToFit()
        
        let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(self.doneTapped))
        let spaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
        let cancelButton = UIBarButtonItem(title: "Cancel", style: .plain, target: self, action: #selector(self.cancelTapped))
        
        toolBar.setItems([cancelButton, spaceButton, doneButton], animated: false)
        toolBar.isUserInteractionEnabled = true
        
        self.toolbar = toolBar
    }
    
    @objc func doneTapped() {
        self.toolbarDelegate?.didTapDone()
    }
    
    @objc func cancelTapped() {
        self.toolbarDelegate?.didTapCancel()
    }
}

Usage example:

class MyViewController: UIViewController {
    
    @IBOutlet weak var textField: UITextField!
    fileprivate let pickerView = ToolbarPickerView()
    fileprivate let titles = ["0", "1", "2", "3"]

    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.textField.inputView = self.pickerView
        self.textField.inputAccessoryView = self.pickerView.toolbar
        
        self.pickerView.dataSource = self
        self.pickerView.delegate = self
        self.pickerView.toolbarDelegate = self
        
        self.pickerView.reloadAllComponents()
    }
}

extension MyViewController: UIPickerViewDataSource, UIPickerViewDelegate {
    
    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return self.titles.count
    }
    
    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 1
    }
    
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        return self.titles[row]
    }
    
    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        self.textField.text = self.titles[row]
    }
}

extension MyViewController: ToolbarPickerViewDelegate {
    
    func didTapDone() {
        let row = self.pickerView.selectedRow(inComponent: 0)
        self.pickerView.selectRow(row, inComponent: 0, animated: false)
        self.textView.text = self.titles[row]
        self.textField.resignFirstResponder()
    }
    
    func didTapCancel() {
        self.textField.text = nil
        self.textField.resignFirstResponder()
    }
}

Solution 3 - Ios

UIPickerView with a Done button? Swift4

Step 1 : Adding one textFiled named txt_pickUpData in ViewController and give IBOutlet connection and delegate. also take one UIDatePicker variable. and take an Array with string value which is display on picker wheel.

@IBOutlet weak var txt_pickUpData: UITextField!
var myPickerView : UIPickerView!
var pickerData = ["Hitesh Modi" , "Kirit Modi" , "Ganesh Modi" , "Paresh Modi"]

Step 2 : Also adding the delegate of UIPickerView and UITextFiled.

class ViewController: UIViewController , UIPickerViewDelegate, UIPickerViewDataSource, UITextFieldDelegate{

Step 3 : The function pickUp to create UIPickerView with ToolBar.

func pickUp(_ textField : UITextField){

// UIPickerView
self.myPickerView = UIPickerView(frame:CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: 216))
self.myPickerView.delegate = self
self.myPickerView.dataSource = self
self.myPickerView.backgroundColor = UIColor.white
textField.inputView = self.myPickerView

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

 }

Step 4 : Adding the delegate and datasource methods of UIPickerView to display data on UIPickerView wheel.

//MARK:- PickerView Delegate & DataSource
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
 }
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return pickerData.count
 }
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return pickerData[row]
  }
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
self.txt_pickUpData.text = pickerData[row]
 }
 //MARK:- TextFiled Delegate

 func textFieldDidBeginEditing(_ textField: UITextField) {
self.pickUp(txt_pickUpData)
 }

Step 5 : Adding two buttons method which which is in ToolBar. One is doneClick and other is cancelClick. Which is dismiss the UIPickerView.

@objc func doneClick() {
  txt_pickUpData.resignFirstResponder()
 }
@objc func cancelClick() {
  txt_pickUpData.resignFirstResponder()
}

Step 6 : Calling the pickUp function in UITextField delegate method.

func textFieldDidBeginEditing(_ textField: UITextField) {
self.pickUp(txt_pickUpData)
}

Just copy and paste in Your code.

Solution 4 - Ios

People seem to be using the code here to other questions to ask the same thing that VBaarathi asked

In Swift3

let doneButton = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.plain, target: self, action: #selector(donePicker))
let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)
let cancelButton = UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.plain, target: self, action: #selector(donePicker))

Then you can put the following in the same swift file

func donePicker (sender:UIBarButtonItem)
{
     // Put something here
}

Solution 5 - Ios

Swift 3x:

The awesome answer is already given but here is the different approach, just make a pickerView and give the inputView and inputAccessoryView like this:

YOUR_TEXTFIELD_NAME.inputView = picker


func addKeyboardToolBar() {

  var nextButton: UIBarButtonItem?
  var keyboardToolBar = UIToolbar(frame: CGRect(x: CGFloat(0), y: 
  CGFloat(0), width: CGFloat(pickerView.frame.size.width), height: CGFloat(25)))
  keyboardToolBar.sizeToFit()
  keyboardToolBar.barStyle = .default
  daysHourTextField.inputAccessoryView = keyboardToolBar
  nextButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(self.textFieldShouldReturn))
  keyboardToolBar.items = [UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil), nextButton]

}

Solution 6 - Ios

Use the IQKeyboardManager library. After setting it up, it will automatically add the Done button for you. Check it out here: github

First install the pod with

pod 'IQKeyboardManagerSwift'

Then In AppDelegate.swift, just import IQKeyboardManagerSwift framework and enable IQKeyboardManager.

 import IQKeyboardManagerSwift

 @UIApplicationMain
 class AppDelegate: UIResponder, UIApplicationDelegate {

   var window: UIWindow?

   func application(_ application: UIApplication, 
    didFinishLaunchingWithOptions launchOptions: 
    [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

    IQKeyboardManager.shared.enable = true

    return true
  }
}

This library will automatically add the Done button in the Keyboard for you.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAlberto O.View Question on Stackoverflow
Solution 1 - IosiAnuragView Answer on Stackoverflow
Solution 2 - IosEridanaView Answer on Stackoverflow
Solution 3 - IosNil RathodView Answer on Stackoverflow
Solution 4 - IosLongmangView Answer on Stackoverflow
Solution 5 - IosAnurag SharmaView Answer on Stackoverflow
Solution 6 - IosDominic TabuView Answer on Stackoverflow