如何使用 Swift 在 iOS 中添加“完成”按钮到 Numpad?

它与默认键盘工作良好,但我不能让它与数字键盘工作。

有什么想法吗?

87905 次浏览

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

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.

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

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
}

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

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];
}

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

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

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.

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

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
}

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