如何显示iPhone数字键盘上的“完成”button

数字键盘上没有“完成”button。 当用户在文本字段中input数字信息时,如何使数字键盘消失?

我可以通过使用默认的键盘得到一个“完成”button,但用户将不得不切换到数字键才能input数字。 有没有办法在数字键盘上显示“完成”button?

解决scheme 如果屏幕上还有其他非数字键盘文本字段,则是完美的。

inputAccessoryView

- (void)viewDidLoad { [super viewDidLoad]; UIToolbar* numberToolbar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, 320, 50)]; numberToolbar.barStyle = UIBarStyleBlackTranslucent; numberToolbar.items = @[[[UIBarButtonItem alloc]initWithTitle:@"Cancel" style:UIBarButtonItemStyleBordered target:self action:@selector(cancelNumberPad)], [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil], [[UIBarButtonItem alloc]initWithTitle:@"Apply" style:UIBarButtonItemStyleDone target:self action:@selector(doneWithNumberPad)]]; [numberToolbar sizeToFit]; numberTextField.inputAccessoryView = numberToolbar; } -(void)cancelNumberPad{ [numberTextField resignFirstResponder]; numberTextField.text = @""; } -(void)doneWithNumberPad{ NSString *numberFromTheKeyboard = numberTextField.text; [numberTextField resignFirstResponder]; } 

这里是卢达对斯威夫特的回答的改编:

在您的UIViewController子类放置的声明

 let numberToolbar: UIToolbar = UIToolbar() 

在ViewDidLoad中把:

  numberToolbar.barStyle = UIBarStyle.BlackTranslucent numberToolbar.items=[ UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.Bordered, target: self, action: "hoopla"), UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: self, action: nil), UIBarButtonItem(title: "Apply", style: UIBarButtonItemStyle.Bordered, target: self, action: "boopla") ] numberToolbar.sizeToFit() textField.inputAccessoryView = numberToolbar //do it for every relevant textfield if there are more than one 

并添加hoopla和hoopla函数(随意select其他名称,只需在ViewDidLoad中相应地更改select器名称

 func boopla () { textField.resignFirstResponder() } func hoopla () { textField.text="" textField.resignFirstResponder() } 

我见过的诀窍是使整个视图的大小自定义透明button,然后在其点击方法,让文本字段辞职第一响应者。 所以用户可以点击字段外的任何地方来closures键盘。

UIKeyboardTypeNumberPad中的解决scheme和丢失的返回键工作很好,但只有在屏幕上没有其他非数字键盘文本字段。

我把这段代码变成了一个UIViewController,你可以简单地inheritance它来使数字键盘工作。 您将需要从上面的链接获取图标。

NumberPadViewController.h:

 #import <UIKit/UIKit.h> @interface NumberPadViewController : UIViewController { UIImage *numberPadDoneImageNormal; UIImage *numberPadDoneImageHighlighted; UIButton *numberPadDoneButton; } @property (nonatomic, retain) UIImage *numberPadDoneImageNormal; @property (nonatomic, retain) UIImage *numberPadDoneImageHighlighted; @property (nonatomic, retain) UIButton *numberPadDoneButton; - (IBAction)numberPadDoneButton:(id)sender; @end 

和NumberPadViewController.m:

 #import "NumberPadViewController.h" @implementation NumberPadViewController @synthesize numberPadDoneImageNormal; @synthesize numberPadDoneImageHighlighted; @synthesize numberPadDoneButton; - (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle { if ([super initWithNibName:nibName bundle:nibBundle] == nil) return nil; if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 3.0) { self.numberPadDoneImageNormal = [UIImage imageNamed:@"DoneUp3.png"]; self.numberPadDoneImageHighlighted = [UIImage imageNamed:@"DoneDown3.png"]; } else { self.numberPadDoneImageNormal = [UIImage imageNamed:@"DoneUp.png"]; self.numberPadDoneImageHighlighted = [UIImage imageNamed:@"DoneDown.png"]; } return self; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; // Add listener for keyboard display events if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 3.2) { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil]; } else { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; } // Add listener for all text fields starting to be edited [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textFieldDidBeginEditing:) name:UITextFieldTextDidBeginEditingNotification object:nil]; } - (void)viewWillDisappear:(BOOL)animated { if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 3.2) { [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidShowNotification object:nil]; } else { [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil]; } [[NSNotificationCenter defaultCenter] removeObserver:self name:UITextFieldTextDidBeginEditingNotification object:nil]; [super viewWillDisappear:animated]; } - (UIView *)findFirstResponderUnder:(UIView *)root { if (root.isFirstResponder) return root; for (UIView *subView in root.subviews) { UIView *firstResponder = [self findFirstResponderUnder:subView]; if (firstResponder != nil) return firstResponder; } return nil; } - (UITextField *)findFirstResponderTextField { UIResponder *firstResponder = [self findFirstResponderUnder:[self.view window]]; if (![firstResponder isKindOfClass:[UITextField class]]) return nil; return (UITextField *)firstResponder; } - (void)updateKeyboardButtonFor:(UITextField *)textField { // Remove any previous button [self.numberPadDoneButton removeFromSuperview]; self.numberPadDoneButton = nil; // Does the text field use a number pad? if (textField.keyboardType != UIKeyboardTypeNumberPad) return; // If there's no keyboard yet, don't do anything if ([[[UIApplication sharedApplication] windows] count] < 2) return; UIWindow *keyboardWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:1]; // Create new custom button self.numberPadDoneButton = [UIButton buttonWithType:UIButtonTypeCustom]; self.numberPadDoneButton.frame = CGRectMake(0, 163, 106, 53); self.numberPadDoneButton.adjustsImageWhenHighlighted = FALSE; [self.numberPadDoneButton setImage:self.numberPadDoneImageNormal forState:UIControlStateNormal]; [self.numberPadDoneButton setImage:self.numberPadDoneImageHighlighted forState:UIControlStateHighlighted]; [self.numberPadDoneButton addTarget:self action:@selector(numberPadDoneButton:) forControlEvents:UIControlEventTouchUpInside]; // Locate keyboard view and add button NSString *keyboardPrefix = [[[UIDevice currentDevice] systemVersion] floatValue] >= 3.2 ? @"<UIPeripheralHost" : @"<UIKeyboard"; for (UIView *subView in keyboardWindow.subviews) { if ([[subView description] hasPrefix:keyboardPrefix]) { [subView addSubview:self.numberPadDoneButton]; [self.numberPadDoneButton addTarget:self action:@selector(numberPadDoneButton:) forControlEvents:UIControlEventTouchUpInside]; break; } } } - (void)textFieldDidBeginEditing:(NSNotification *)note { [self updateKeyboardButtonFor:[note object]]; } - (void)keyboardWillShow:(NSNotification *)note { [self updateKeyboardButtonFor:[self findFirstResponderTextField]]; } - (void)keyboardDidShow:(NSNotification *)note { [self updateKeyboardButtonFor:[self findFirstResponderTextField]]; } - (IBAction)numberPadDoneButton:(id)sender { UITextField *textField = [self findFirstResponderTextField]; [textField resignFirstResponder]; } - (void)dealloc { [numberPadDoneImageNormal release]; [numberPadDoneImageHighlighted release]; [numberPadDoneButton release]; [super dealloc]; } @end 

请享用。

以下是对卢达的答案进行的一次彻底改革:

  • 附件视图自动resize到应用程序框架的宽度

  • 避免使用不build议使用的常量UIBarButtonItemStyleBordered

  • “完成”button被实例化为UIBarButtonSystemItemDone

目前,“完成”button位于附件视图中。 您可以通过删除相关侧面上的空间来将其定位在左侧或右侧。

我省略了“取消”button,因为默认键盘没有一个。 如果你想要一个“取消”button,我build议你将它实例化为一个UIBarButtonSystemItemCancel ,并确保你不丢弃文本字段中的原始值。 路达答案中的“取消”行为,用空白string覆盖值可能不是你想要的。

 - (void)viewDidLoad { [super viewDidLoad]; float appWidth = CGRectGetWidth([UIScreen mainScreen].applicationFrame); UIToolbar *accessoryView = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, appWidth, 0.1 * appWidth)]; UIBarButtonItem *space = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; UIBarButtonItem *done = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(selectDoneButton)]; accessoryView.items = @[space, done, space]; self.valueField.inputAccessoryView = accessoryView; } - (void)selectDoneButton { [self.valueField resignFirstResponder]; } 

有关构build附件视图的更多信息,请参阅用于数据input的自定义视图的Apple文档。 您可能也想要参考UIToolbar和UIBarButtonItem上的参考页面。

这是最近的代码。 只需在viewController中包含#import“UIViewController + NumPadReturn.h”即可。

这是.h

 #import <Foundation/Foundation.h> #import <UIKit/UIKit.h> @interface UIViewController (NumPadReturn) @end 

还有他们

 #import "UIViewController+NumPadReturn.h" @implementation UIViewController (NumPadReturn) -(void) viewDidLoad{ // add observer for the respective notifications (depending on the os version) if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 3.2) { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil]; } else { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; } } - (void)keyboardWillShow:(NSNotification *)note { // if clause is just an additional precaution, you could also dismiss it if ([[[UIDevice currentDevice] systemVersion] floatValue] < 3.2) { [self addButtonToKeyboard]; } } - (void)keyboardDidShow:(NSNotification *)note { // if clause is just an additional precaution, you could also dismiss it if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 3.2) { [self addButtonToKeyboard]; } } - (void)addButtonToKeyboard { // create custom button UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeCustom]; doneButton.frame = CGRectMake(0, 163, 106, 53); doneButton.adjustsImageWhenHighlighted = NO; if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 3.0) { [doneButton setImage:[UIImage imageNamed:@"DoneUp3.png"] forState:UIControlStateNormal]; [doneButton setImage:[UIImage imageNamed:@"DoneDown3.png"] forState:UIControlStateHighlighted]; } else { [doneButton setImage:[UIImage imageNamed:@"DoneUp.png"] forState:UIControlStateNormal]; [doneButton setImage:[UIImage imageNamed:@"DoneDown.png"] forState:UIControlStateHighlighted]; } [doneButton addTarget:self action:@selector(doneButton:) forControlEvents:UIControlEventTouchUpInside]; // locate keyboard view UIWindow* tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:1]; UIView* keyboard; for(int i=0; i<[tempWindow.subviews count]; i++) { keyboard = [tempWindow.subviews objectAtIndex:i]; // keyboard found, add the button if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 3.2) { if([[keyboard description] hasPrefix:@"<UIPeripheralHost"] == YES) [keyboard addSubview:doneButton]; } else { if([[keyboard description] hasPrefix:@"<UIKeyboard"] == YES) [keyboard addSubview:doneButton]; } } } - (void)doneButton:(id)sender { NSLog(@"doneButton"); [self.view endEditing:TRUE]; } @end 

更简单的解决scheme

 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [super touchesBegan:touches withEvent:event]; [textViewInstance1 resignFirstResponder]; [textViewInstance2 resignFirstResponder]; [textField resignFirstResponder]; } 

这个论坛post描述了如何自定义UIKeyboard来将自定义视图添加到键盘上。

我在这里描述了一个适用于iOS 4.2+的解决scheme,但在键盘出现后,解除button将会消失。 这不是可怕的,但也不是理想的。

在上面链接的问题中描述的解决scheme包括一个更优雅的错觉,closuresbutton,我淡入淡出和垂直位移button,以提供键盘和button一起解雇的外观。

最简单的方法是:

创build自定义透明button ,并将其放置在左下angular,这将具有与CGSize中的空白空间相同的UIKeyboardTypeNumberPad 。 切换(显示/隐藏)此button在textField becomeFirstResponder ,在button上分别点击。

这是我遇到的最简单的解决scheme。 我从“iOS 5开发”一书中学到了这一点。

假设数字字段被称为数字字段。

  1. ViewController ,添加以下方法:

     -(IBAction)closeKeyboard:(id)sender; 
  2. ViewController.m ,添加下面的代码:

     -(IBAction)closeKeyboard:(id)sender { [numberField resignFirstResponder]; } 
  3. 回到nib文件。

  4. 打开Utilities平移。
  5. 在“ Utilities下打开“ Identity inspector
  6. 点击View (在笔尖文件中)一次。 确保您没有点击视图中的任何项目。 为了澄清起见,您应该在Identity inspector Class下面看到UIView。
  7. 将类从UIView更改为UIControl。
  8. 打开Connection Inspector
  9. 点击并拖动Touch Down并将箭头放在File Owner图标上。 (仅供参考…文件所有者图标显示在View的左侧,显示为带黄色框的空心立方体。)
  10. select方法: closeKeyboard
  11. 运行程序。

现在当你点击View背景的任何地方时,你应该可以closures键盘。

希望这可以帮助你解决你的问题。 🙂

我修改了Bryan的解决scheme,使其更健壮一些,以便与其他types的键盘可以在相同的视图中出现。 这里描述:

在iOS numpad UIKeyboard上创build一个完成button

我试图在这里解释它,但其中大部分是代码来看待在这里不容易

如果您事先知道要input的号码的数量(例如4位数字的PIN码),您可以在按下4次按键后自动解除,如同我对这个类似问题的回答一样:

解除数字键盘

在这种情况下,不需要额外的完成button。

如果我们只是告诉我们的视图控制器的视图来结束编辑,我们也可以使“用户触摸别的地方”的解决scheme更简单:

 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [super touchesBegan:touches withEvent:event]; [self.view endEditing:YES]; //YES ignores any textfield refusal to resign } 

假设“在别处触摸会取消键盘”是视图上任何其他可编辑字段的理想行为。

如果你有多个数字字段,我build议子类化UITextField来创build一个NumericTextField,它总是显示一个完成button的数字键盘。 然后,只需在Interface Builder中将您的数字字段与此类相关联,您将不需要任何视图控制器中的任何其他代码。 以下是我在Xcode 8.0中使用的Swift 3.0类。

 class NumericTextField: UITextField { let numericKbdToolbar = UIToolbar() // MARK: Initilization required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) self.initialize() } override init(frame: CGRect) { super.init(frame: frame) self.initialize() } // Sets up the input accessory view with a Done button that closes the keyboard func initialize() { self.keyboardType = UIKeyboardType.numberPad numericKbdToolbar.barStyle = UIBarStyle.default let space = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil) let callback = #selector(NumericTextField.finishedEditing) let donebutton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.done, target: self, action: callback) numericKbdToolbar.setItems([space, donebutton], animated: false) numericKbdToolbar.sizeToFit() self.inputAccessoryView = numericKbdToolbar } // MARK: On Finished Editing Function func finishedEditing() { self.resignFirstResponder() } } 

我发现@ user1258240的答案是非常简洁的,因为这不像设置returnKeyType属性那么简单。

只是想贡献一下我自己的“可重用”方法:

 func SetDoneToolbar(field:UITextField) { let doneToolbar:UIToolbar = UIToolbar() doneToolbar.items=[ UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: self, action: nil), UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.plain, target: self, action: #selector(ViewController.dismissKeyboard)) ] doneToolbar.sizeToFit() field.inputAccessoryView = doneToolbar } override func viewDidLoad() { super.viewDidLoad() SetDoneToolbar(field: UITextField_1) SetDoneToolbar(field: UITextField_2) SetDoneToolbar(field: UITextField_3) SetDoneToolbar(field: UITextField_N) } 

对于Swift 2.2我使用这个

 func addDoneButtonOnKeyboard() { let doneToolbar: UIToolbar = UIToolbar(frame: CGRectMake(0, 0, self.view.bounds.size.width, 50)) let flexSpace = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: nil, action: nil) let done: UIBarButtonItem = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Done, target: self, action: #selector(DetailViewController.finishDecimalKeypad)) var items: [UIBarButtonItem]? = [UIBarButtonItem]() items?.append(flexSpace) items?.append(done) doneToolbar.items = items doneToolbar.sizeToFit() self.productPrice.inputAccessoryView=doneToolbar } func finishDecimalKeypad() { self.productPrice?.resignFirstResponder() } 

一个使用扩展的Swift 3解决scheme。 如果您的应用程序中有多个数字UITextField对象,这是理想的select,因为它可以灵活地为每个UITextField决定是否在“完成”或“ 取消”时执行自定义操作。

在这里输入图像说明

 // // UITextField+DoneCancelToolbar.swift // import UIKit extension UITextField { func addDoneCancelToolbar(onDone: (target: Any, action: Selector)? = nil, onCancel: (target: Any, action: Selector)? = nil) { let onCancel = onCancel ?? (target: self, action: #selector(cancelButtonTapped)) let onDone = onDone ?? (target: self, action: #selector(doneButtonTapped)) let toolbar: UIToolbar = UIToolbar() toolbar.barStyle = .default toolbar.items = [ UIBarButtonItem(title: "Cancel", style: .plain, target: onCancel.target, action: onCancel.action), UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil), UIBarButtonItem(title: "Done", style: .done, target: onDone.target, action: onDone.action) ] toolbar.sizeToFit() self.inputAccessoryView = toolbar } // Default actions: func doneButtonTapped() { self.resignFirstResponder() } func cancelButtonTapped() { self.resignFirstResponder() } } 

使用默认操作的使用示例:

 // // MyViewController.swift // @IBOutlet weak var myNumericTextField: UITextField! { didSet { myNumericTextField?.addDoneCancelToolbar() } } 

使用自定义完成操作的使用示例:

 // // MyViewController.swift // @IBOutlet weak var myNumericTextField: UITextField! { didSet { myNumericTextField?.addDoneCancelToolbar(onDone: (target: self, action: #selector(doneButtonTappedForMyNumericTextField))) } } func doneButtonTappedForMyNumericTextField() { print("Done"); myNumericTextField.resignFirstResponder() } 

SWIFT 3.0一个不同的风格,使用一些以前的答案的部分。

 func addToolbarToNumberPad() { let numberPadToolbar: UIToolbar = UIToolbar() numberPadToolbar.isTranslucent = true numberPadToolbar.items=[ UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(self.cancelAction)), UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil), UIBarButtonItem(title: "Custom", style: .done, target: self, action: #selector(self.customAction)), UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(self.doneAction)), ] numberPadToolbar.sizeToFit() textField.inputAccessoryView = numberPadToolbar } func cancelAction() { textField.resignFirstResponder() } func customAction() { textField.resignFirstResponder() } func doneAction() { textField.resignFirstResponder() } override func viewDidLoad() { super.viewDidLoad() self.addToolbarToNumberPad() } 

所有这些关于在第三行查找键盘视图和添加完成button的实现(这就是为什么button.y = 163 b / c键盘的高度是216)是脆弱的,因为iOS保持更改视图层次结构。 例如,以上代码都不适用于iOS9。

我认为通过[[UIApplication sharedApplication]窗口] lastObject]find最顶层的视图更加安全,只需要在左下angular添加buttondoneButton.frame = CGRectMake(0,SCREEN_HEIGHT-53,106 ,53); //肖像模式

Swift 2.2 /我用Dx_的答案。 不过,我想要所有键盘上的这个function。 所以在我的基类,我把代码:

 func addDoneButtonForTextFields(views: [UIView]) { for view in views { if let textField = view as? UITextField { let doneToolbar = UIToolbar(frame: CGRectMake(0, 0, self.view.bounds.size.width, 50)) let flexSpace = UIBarButtonItem(barButtonSystemItem: .FlexibleSpace, target: nil, action: nil) let done = UIBarButtonItem(title: "Done", style: .Done, target: self, action: #selector(dismissKeyboard)) var items = [UIBarButtonItem]() items.append(flexSpace) items.append(done) doneToolbar.items = items doneToolbar.sizeToFit() textField.inputAccessoryView = doneToolbar } else { addDoneButtonForTextFields(view.subviews) } } } func dismissKeyboard() { dismissKeyboardForTextFields(self.view.subviews) } func dismissKeyboardForTextFields(views: [UIView]) { for view in views { if let textField = view as? UITextField { textField.resignFirstResponder() } else { dismissKeyboardForTextFields(view.subviews) } } } 

然后,只需在viewDidLoad(或使用table view的willDisplayCell)的self.view.subviews上调用addDoneButtonForTextFields,将Donebutton添加到所有键盘上。