How to make an UIPickerView with a Done button?

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()


}








}
113803 次浏览

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

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
}

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]


}

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.

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()
}
}

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.