如何使用Swift在iOS中为数字键盘添加“完成”按钮?

98

默认键盘可以正常工作,但无法使用小键盘。

有什么想法?


请查看此链接:http://www.weheartswift.com/make-custom-keyboard-ios-8-using-swift/ - Deepesh
2
我不想创建一个新的键盘,我只想在UIToolBar中添加一个按钮,然后将其作为inputAccessoryView添加到textField中,就像这里所示:https://dev59.com/zXRB5IYBdhLWcg3wkH9N#11382044,但我还没有弄清楚如何在Swift中实现它。 - Dejan Skledar
我们可以通过向默认键盘添加自定义按钮来实现,而不是使用自定义键盘或工具栏。请参考此答案 - Nazik
使用故事板的解决方案https://dev59.com/F3nZa4cB1Zd3GeqPlRLt#37896351。 - Irshad Mohamed
12个回答

119
据我所知,无法在键盘部分添加“完成”按钮;您需要向UITextFieldUITextView添加一个inputAccessoryView(如果您正在使用它)。请查阅文档了解更多信息编辑: 可以查看此问题的示例编辑2: Swift中类似的示例编辑3: 编辑2中的代码,因为链接可能会过期。
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()
    }

完美运作。实现快速简便。谢谢! - Octavio Antonio Cedeño
5
你可以更改为以下内容,这样你就不需要本地化按钮: let done: UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.done, target: self, action: #selector(self.doneButtonAction)) - Zeezer

79

Swift 5解决方案使用@IBInspectable和扩展。在项目中的每个UITextField下,属性检查器下将出现一个下拉菜单。

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

4
非常棒的回答。我希望每个人都会往下滑到这里。 - biomiker
正是我所需要的。谢谢。 - knig_T
多么优雅的解决方案,美丽。 - Nicholas Farmer

60

Swift-3版本Marko的解决方案 - 在我的情况中可行

(在我的情况中,我有一个被标识为textfield的UITextField)

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

15

您可以将带有“完成”按钮的工具栏添加到键盘中。

可以使用文本框的InputAccessoryView属性设置此工具栏。

以下是我在我的情况下使用的代码:

//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

屏幕截图


8
我能找到的最简单的解决方案 - 适用于Swift 4.2 - 希望这有所帮助 :)
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
   }
}

接着,您可以在textFieldDidEndEditing委托方法中处理完成操作,或者只需添加自定义方法到扩展中并将其设置为doneButton选择器中的方法。


优秀、简单而优雅的解决方案! - Benjamin RD

6
如果你的“完成”按钮只是用于关闭数字键盘,那么最简单的实现方式就是像下面这样将“resignFirstResponder”作为选择器进行调用:
UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Done, target: textField, action: #selector(UITextField.resignFirstResponder))

这段代码适用于iOS9和Swift 2,在我的应用中使用它:

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
}

3

首先,让我告诉你一件事:你可以在默认键盘上添加一个“完成”按钮。今天我遇到了这个问题并解决了它。这是现成的代码,只需将其放置在您的 .swift 类中即可。我正在使用 Xcode 7 并在 iPad Retina (iOS 9) 上进行测试。

无论如何,不再多说,这就是代码。

  //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
   }
}

这给了我解决方案...

enter image description here

我还想告诉你的一件事是,这是我最近项目中使用的有效解决方案。我发布了这篇文章,因为目前没有可用的有效解决方案。代码和说明如承诺。

编辑:-

让它更专业……如果您遵循以上代码,它也会给您提供有效解决方案,但在这里,我正在尝试将其更加专业化。请注意代码MOD。我留下了先前未使用的带引号代码。

变化。

  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
    }
    
现在它给我以下提示...此外,尝试匹配图片并找到更改。

enter image description here

感谢您的信任。希望这篇文章对您有所帮助。很抱歉我的回答有点长。

3

我会使用一个叫做IQKeyboardManagerSwift的库。

你只需要在AppDelegate的didFinishWithLaunching方法中插入一行代码,它就会为所有的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
}

3
因为Xcode 11及以上版本中,像UIToolbar()这样的初始工具栏每次运行时都会在控制台上抛出一个破坏性约束,如here,所以请改用UIToolbar(frame: CGRect(x: 0, y: 0, width: view.frame.size.width, height: 35))
示例代码
            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

这个可行,但你是怎么想到35的框架的? - geohei
1
我认为这是默认高度,也许您可以配置更改它。 - SuryaKantSharma
您可以设置任何数字(尝试了0到999)。似乎这似乎没有改变任何东西。 - geohei

2

根据Marko Nikolovski的回答:

以下是Objective-C的答案:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接