How to add "Done" button to Numpad in iOS using Swift?

IosSwiftNumpad

Ios Problem Overview


It works fine with the default keyboard, but I cant get it working with the numpad.

Any ideas?

Ios Solutions


Solution 1 - Ios

As far as I know, you can't add the Done button on the keyboard part; you'd have add a inputAccessoryView to the UITextField or UITextView (if that's what you're using).

Check the documentation for more info.

Edit: Check this question for an example on how to do that.

Edit 2: Similar example in Swift.

Edit 3: Code from edit 2, as link may expire.

override func viewDidLoad()
{
    super.viewDidLoad()
     
    //--- add UIToolBar on keyboard and Done button on UIToolBar ---//
    self.addDoneButtonOnKeyboard()
}

//--- *** ---//

func addDoneButtonOnKeyboard()
{
    var doneToolbar: UIToolbar = UIToolbar(frame: CGRectMake(0, 0, 320, 50))
    doneToolbar.barStyle = UIBarStyle.BlackTranslucent
   
    var flexSpace = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: nil, action: nil)
    var done: UIBarButtonItem = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Done, target: self, action: Selector("doneButtonAction"))
    
    var items = NSMutableArray()
    items.addObject(flexSpace)
    items.addObject(done)
  
    doneToolbar.items = items
    doneToolbar.sizeToFit()
    
    self.textView.inputAccessoryView = doneToolbar
    self.textField.inputAccessoryView = doneToolbar
    
}

func doneButtonAction()
{
    self.textViewDescription.resignFirstResponder()
}

Swift 4.2

func addDoneButtonOnKeyboard(){
        let doneToolbar: UIToolbar = UIToolbar(frame: CGRect.init(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 50))
        doneToolbar.barStyle = .default
        
        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 = [flexSpace, done]
        doneToolbar.items = items
        doneToolbar.sizeToFit()
        
        txtMobileNumber.inputAccessoryView = doneToolbar
    }
    
    @objc func doneButtonAction(){
        txtMobileNumber.resignFirstResponder()
    }

Solution 2 - Ios

Swift 5 solution using @IBInpectable and extension. A dropdown will appear under the Attribute Inspector in the Interface Builder for every UITextField in the project.

extension UITextField{    
    @IBInspectable var doneAccessory: Bool{
        get{
            return self.doneAccessory
        }
        set (hasDone) {
            if hasDone{
                addDoneButtonOnKeyboard()
            }
        }
    }

    func addDoneButtonOnKeyboard()
    {
        let doneToolbar: UIToolbar = UIToolbar(frame: CGRect.init(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 50))
        doneToolbar.barStyle = .default
        
        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 = [flexSpace, done]
        doneToolbar.items = items
        doneToolbar.sizeToFit()
        
        self.inputAccessoryView = doneToolbar
    }
    
    @objc func doneButtonAction()
    {
        self.resignFirstResponder()
    }
}

Solution 3 - Ios

A Swift-3 Version (of Marko's solution - which worked for me)

(in my case, I have a UITextField identified as textfield)

func addDoneButtonOnKeyboard() {
    let doneToolbar: UIToolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: 320, height: 50))
    doneToolbar.barStyle       = UIBarStyle.default        
    let flexSpace              = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)
    let done: UIBarButtonItem  = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.done, target: self, action: #selector(ViewController.doneButtonAction))
    
    var items = [UIBarButtonItem]()
    items.append(flexSpace)
    items.append(done)
    
    doneToolbar.items = items
    doneToolbar.sizeToFit()
    
    self.textfield.inputAccessoryView = doneToolbar
}

func doneButtonAction() {
    self.textfield.resignFirstResponder()
}

Solution 4 - Ios

You can add toolbar with Done button to keyboard. InputAccessoryView property of textfield can be used to set this toolbar.

Below is code that I’ve used in my case

//Add done button to numeric pad keyboard
 let toolbarDone = UIToolbar.init()
 toolbarDone.sizeToFit()
 let barBtnDone = UIBarButtonItem.init(barButtonSystemItem: UIBarButtonSystemItem.Done,
         target: self, action: #selector(VerifyCardViewController.doneButton_Clicked(_:)))
        
 toolbarDone.items = [barBtnDone] // You can even add cancel button too
 txtCardDetails3.inputAccessoryView = toolbarDone

Screenshot

Solution 5 - Ios

The simplest solution I could find - works with Swift 4.2 - hope this helps :)

extension UITextField {

   func addDoneButtonOnKeyboard() {
       let keyboardToolbar = UIToolbar()
       keyboardToolbar.sizeToFit()
       let flexibleSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace,
           target: nil, action: nil)
       let doneButton = UIBarButtonItem(barButtonSystemItem: .done,
           target: self, action: #selector(resignFirstResponder))
       keyboardToolbar.items = [flexibleSpace, doneButton]
       self.inputAccessoryView = keyboardToolbar
   }
}

Then you can handle the done action in the textFieldDidEndEditing delegate method or just add a custom method to the extension and set it in the selector of the doneButton.

Solution 6 - Ios

If your Done button is supposed to just close the numberpad, then the simplest version would be to call resignFirstResponder as the selector like this:

UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Done, target: textField, action: #selector(UITextField.resignFirstResponder))

This code works in iOS9 and Swift 2, I am using it in my app:

func addDoneButtonOnNumpad(textField: UITextField) {

  let keypadToolbar: UIToolbar = UIToolbar()

  // add a done button to the numberpad
  keypadToolbar.items=[
    UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Done, target: textField, action: #selector(UITextField.resignFirstResponder)),
    UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: self, action: nil)
  ]
  keypadToolbar.sizeToFit()
  // add a toolbar with a done button above the number pad
  textField.inputAccessoryView = keypadToolbar
}

Solution 7 - Ios

First of all let me tell you one thing that You Can ADD A Done Button On Your Default KeyBoard. Actually today I just went through this problem and solved. Ready Made Code, just place this on your .swift class. I am using Xcode 7 and testing this using iPad Retina(ios 9).

Anyway no more talk here is the code.

  //Creating an outlet for the textfield
  @IBOutlet weak var outletTextFieldTime: UITextField!

  //Adding the protocol of UITextFieldDelegate      
  class ReservationClass: UIViewController, UITextFieldDelegate { 
  
  func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
  //Making A toolbar        
  let keyboardDoneButtonShow = UIToolbar(frame: CGRectMake(0, 0,  self.view.frame.size.width, self.view.frame.size.height/17))
  //Setting the style for the toolbar
    keyboardDoneButtonShow.barStyle = UIBarStyle .BlackTranslucent        
  //Making the done button and calling the textFieldShouldReturn native method for hidding the keyboard.
  let doneButton = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Done, target: self, action: Selector("textFieldShouldReturn:"))
  //Calculating the flexible Space.
    let flexSpace = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: nil, action: nil)
  //Setting the color of the button.
    item.tintColor = UIColor .yellowColor()
  //Making an object using the button and space for the toolbar        
  let toolbarButton = [flexSpace,doneButton]
  //Adding the object for toolbar to the toolbar itself
  keyboardDoneButtonShow.setItems(toolbarButton, animated: false)
  //Now adding the complete thing against the desired textfield
    outletTextFieldTime.inputAccessoryView = keyboardDoneButtonShow
    return true

}

//Function for hidding the keyboard.
func textFieldShouldReturn(textField: UITextField) -> Bool {
    self.view.endEditing(true)
    return false
   }
}

Which is giving me the solution as...

enter image description here

One more thing I just wanna tell you that this is the working solution which I have used on my recent project. I have posted this because there is no working solution available for this problem. Working Code and explanation as promised.

EDIT :-

Making it more professional...If you are following the above code then also it will give you the working solution but here I am trying to make it more Professional. Please notice the code MOD. I left the previous unused code with quote.

Changes..

  1. Creating an Individual Button object

  2. Setting it to the toolbar

  3. Reducing the size of the toolbar which was created previously

  4. Positioning the custom button to the left of the screen using FlexSpace and NegativeSpace.

     func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
     let keyboardDoneButtonShow = UIToolbar(frame: CGRectMake(200,200, self.view.frame.size.width,30))
     
     // self.view.frame.size.height/17
     keyboardDoneButtonShow.barStyle = UIBarStyle .BlackTranslucent
     let button: UIButton = UIButton()
     button.frame = CGRectMake(0, 0, 65, 20)
     button.setTitle("Done", forState: UIControlState .Normal)
     button.addTarget(self, action: Selector("textFieldShouldReturn:"), forControlEvents: UIControlEvents .TouchUpInside)
     button.backgroundColor = UIColor .clearColor()
     // let doneButton = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Done, target: self, action: Selector("textFieldShouldReturn:"))
     let doneButton: UIBarButtonItem = UIBarButtonItem()
     doneButton.customView = button
     let negativeSpace = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FixedSpace, target: nil, action: nil)
     negativeSpace.width = -10.0
     let flexSpace = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: nil, action: nil)
     //doneButton.tintColor = UIColor .yellowColor()
     let toolbarButton = [flexSpace,doneButton,negativeSpace]
     keyboardDoneButtonShow.setItems(toolbarButton, animated: false)
     outletTextFieldTime.inputAccessoryView = keyboardDoneButtonShow
     return true
     }
    

It is now giving me the following...Moreover try to match the pictures and find the changes.

enter image description here

Thanks.

Hope this helped. Sorry for the long answer.

Solution 8 - Ios

I would use a library calles IQKeyboardManagerSwift.

You simplay have to insert one line of code into AppDelegates didFinishWithLaunching method and it applies all necessary features to all TextFields.

import IQKeyboardManagerSwift

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.
    //Following line is all you need and it applies for all TextFields
    IQKeyboardManager.shared.enable = true
    return true
}

Solution 9 - Ios

Because above answers are old in Xcode 11 and above initial toolBar like UIToolbar() will throw a breaking constraint on console every time like here you run so use UIToolbar(frame: CGRect(x: 0, y: 0, width: view.frame.size.width, height: 35)) instead

Sample code

            let toolBar =  UIToolbar(frame: CGRect(x: 0, y: 0, width: view.frame.size.width, height: 35))
            toolBar.barStyle = .default
            toolBar.sizeToFit()
    
            // Adding Button ToolBar
            let doneButton = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(doneButtonTapped))
            toolBar.items = [doneButton]
            toolBar.isUserInteractionEnabled = true
            textField.inputAccessoryView = toolBar

Solution 10 - Ios

According to Marko Nikolovski answer

Here is objective-C answer :

- (void)ViewDidLoad {
[self addDoneButtonOnKeyboard];
}

- (void)addDoneButtonOnKeyboard {
UIToolbar *toolBarbutton = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 320, 50)];
toolBarbutton.barStyle = UIBarStyleBlackTranslucent;

UIBarButtonItem *barBtnItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *done = [[UIBarButtonItem alloc] initWithTitle:@"Done" style:UIBarButtonItemStyleDone target:self action:@selector(doneButtonAction)];

NSMutableArray *items = [[NSMutableArray alloc] init];
[items addObject:barBtnItem];
[items addObject:done];

toolBarbutton.items = items;
[toolBarbutton sizeToFit];

self.timeoutTextField.inputAccessoryView = toolBarbutton;
}

- (void)doneButtonAction {
[self.view endEditing:YES];
}

Solution 11 - Ios

You can create a custom class. I'm using Swift 4:

class UITextFieldWithDoneButton: UITextField {
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.addDoneButtonOnKeyboard()
    }
    
    fileprivate func addDoneButtonOnKeyboard() {
        let doneToolbar: UIToolbar = UIToolbar(frame: CGRect.init(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 50))
        doneToolbar.barStyle = .default
        
        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 = [flexSpace, done]
        doneToolbar.items = items
        doneToolbar.sizeToFit()
        
        self.inputAccessoryView = doneToolbar
    }
    
    @objc fileprivate func doneButtonAction() {
        self.resignFirstResponder()
    }
}

Solution 12 - Ios

simple and easy way to add "DONE" button on any keyboard is add universal library

IQKeyboardManager

add below code in appdelegate at application(_ application: UIApplication, didFinishLaunchingWithOptions.

IQKeyboardManager.shared.enable = true
IQKeyboardManager.shared.enableAutoToolbar = true
IQKeyboardManager.shared.keyboardDistanceFromTextField = 15
IQKeyboardManager.shared.shouldResignOnTouchOutside = true

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
QuestionDejan SkledarView Question on Stackoverflow
Solution 1 - IosnikolovskiView Answer on Stackoverflow
Solution 2 - IosDejan AtanasovView Answer on Stackoverflow
Solution 3 - IosAdam StollerView Answer on Stackoverflow
Solution 4 - IosJayprakash DubeyView Answer on Stackoverflow
Solution 5 - IosMitemmetimView Answer on Stackoverflow
Solution 6 - IosCoder1224View Answer on Stackoverflow
Solution 7 - IosonCompletionView Answer on Stackoverflow
Solution 8 - Iosilija.trkuljaView Answer on Stackoverflow
Solution 9 - IosSuryaKantSharmaView Answer on Stackoverflow
Solution 10 - IosdicleView Answer on Stackoverflow
Solution 11 - IosKirill KudaevView Answer on Stackoverflow
Solution 12 - IosHitesh VoraView Answer on Stackoverflow