如何在 iOS 中为 numpad 键盘添加“完成”按钮

因此,numpad 键盘默认没有“完成”或“下一步”按钮,所以我想添加一个。在 iOS6及以下版本中,有一些在键盘上添加按钮的技巧,但是在 iOS7中似乎不起作用。

首先我订阅了显示通知的键盘

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];

然后,当键盘出现时,我尝试添加一个按钮:

- (void)keyboardWillShow:(NSNotification *)note
{
// create custom button
UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeSystem];
doneButton.frame = CGRectMake(0, 50, 106, 53);
doneButton.adjustsImageWhenHighlighted = NO;
[doneButton setTitle:@"Done" forState:UIControlStateNormal];
[doneButton addTarget:self action:@selector(dismissKeyboard) 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 view found; add the custom button to it
if([[keyboard description] hasPrefix:@"UIKeyboard"] == YES)
[keyboard addSubview:doneButton];
}
}

但是 for 循环不会运行,因为它找不到任何子视图。有什么建议吗?我找不到任何 iOS7的解决方案,所以我应该用不同的方式来做这件事吗?

编辑: 感谢所有对工具栏家伙的建议,但我宁愿不走这条路,因为我相当空间贫乏(这是一种丑陋)。

74180 次浏览

You can add a button to the keyboard's input accessory view

myTextField.inputAccessoryView =_inputView;

input accessory view is a view that comes over the keyboard always and dismiss with the [textfield resignFirstResponder]

put done over the input view and perform resign first responder of the textfields.

The much safer approach is to use a UIToolBar with Done Button as inputAccessoryView.


Sample Code :

UIToolbar *keyboardDoneButtonView = [[UIToolbar alloc] init];
[keyboardDoneButtonView sizeToFit];
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithTitle:@"Done"
style:UIBarButtonItemStyleBordered target:self
action:@selector(doneClicked:)];
[keyboardDoneButtonView setItems:[NSArray arrayWithObjects:doneButton, nil]];
txtField.inputAccessoryView = keyboardDoneButtonView;

Your -doneClicked method should look like this :

- (IBAction)doneClicked:(id)sender
{
NSLog(@"Done Clicked.");
[self.view endEditing:YES];
}

Sample Code Swift:

let keyboardDoneButtonView = UIToolbar.init()
keyboardDoneButtonView.sizeToFit()
let doneButton = UIBarButtonItem.init(barButtonSystemItem: UIBarButtonSystemItem.Done,
target: self,
action: Selector("doneClicked:")))


keyboardDoneButtonView.items = [doneButton]
textFieldInput.inputAccessoryView = keyboardDoneButtonView

Your -doneClicked method should look like this :

func doneClicked(sender: AnyObject) {
self.view.endEditing(true)
}

This is a simple way of projecting a done button in iOS7 num-keypad. In the below delegate method of UITextField, add a notification for keyboard show.

-(void)textFieldDidBeginEditing:(UITextField *)textField {
    

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];
}

Now implement the method keyboardWillShow as below. Here we need to take extra care for iOS7.

- (void)keyboardWillShow:(NSNotification *)note {
// create custom button
UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeCustom];
doneButton.frame = CGRectMake(0, 163, 106, 53);
doneButton.adjustsImageWhenHighlighted = NO;
[doneButton setImage:[UIImage imageNamed:@"doneButtonNormal.png"] forState:UIControlStateNormal];
[doneButton setImage:[UIImage imageNamed:@"doneButtonPressed.png"] forState:UIControlStateHighlighted];
[doneButton addTarget:self action:@selector(doneButton:) forControlEvents:UIControlEventTouchUpInside];
    

if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) {
dispatch_async(dispatch_get_main_queue(), ^{
UIView *keyboardView = [[[[[UIApplication sharedApplication] windows] lastObject] subviews] firstObject];
[doneButton setFrame:CGRectMake(0, keyboardView.frame.size.height - 53, 106, 53)];
[keyboardView addSubview:doneButton];
[keyboardView bringSubviewToFront:doneButton];
            

[UIView animateWithDuration:[[note.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue]-.02
delay:.0
options:[[note.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]
animations:^{
self.view.frame = CGRectOffset(self.view.frame, 0, 0);
} completion:nil];
});
} else {
// locate keyboard view
dispatch_async(dispatch_get_main_queue(), ^{
UIWindow* tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:1];
UIView* keyboard;
for(int i=0; i<[tempWindow.subviews count]; i++) {
keyboard = [tempWindow.subviews objectAtIndex:i];
// keyboard view found; add the custom button to it
if([[keyboard description] hasPrefix:@"UIKeyboard"] == YES)
[keyboard addSubview:doneButton];
}
});
}
}

Now add this macro to suitable header to detect the SYSTEM_VERSION

#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)

Just use

yourTextField.inputAccessoryView

hope you help

Even easier way:

Swift 3.0 and above:

func addDoneButton() {
let keyboardToolbar = UIToolbar()
keyboardToolbar.sizeToFit()
let flexBarButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace,
target: nil, action: nil)
let doneBarButton = UIBarButtonItem(barButtonSystemItem: .done,
target: view, action: #selector(UIView.endEditing(_:)))
keyboardToolbar.items = [flexBarButton, doneBarButton]
textField.inputAccessoryView = keyboardToolbar
}

Swift 2.3 and below:

func addDoneButton() {
let keyboardToolbar = UIToolbar()
keyboardToolbar.sizeToFit()
let flexBarButton = UIBarButtonItem(barButtonSystemItem: .FlexibleSpace,
target: nil, action: nil)
let doneBarButton = UIBarButtonItem(barButtonSystemItem: .Done,
target: view, action: #selector(UIView.endEditing(_:)))
keyboardToolbar.items = [flexBarButton, doneBarButton]
textField.inputAccessoryView = keyboardToolbar
}

Objective C:

- (void)addDoneButton {
UIToolbar* keyboardToolbar = [[UIToolbar alloc] init];
[keyboardToolbar sizeToFit];
UIBarButtonItem *flexBarButton = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
target:nil action:nil];
UIBarButtonItem *doneBarButton = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemDone
target:self.view action:@selector(endEditing:)];
keyboardToolbar.items = @[flexBarButton, doneBarButton];
self.textField.inputAccessoryView = keyboardToolbar;
}

EDIT:

I've created a useful library called DCKit, which already have the toolbar out of the box:

Done toolbar above keyboard in iOS (with using DCKit library)

It also has many other cool features.

You do need to detect whether you are on a phone or iPad since the iPad implements a return key on the "number" pad

  1. register the controller to the notification
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// Keyboard events
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];


[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
}
  1. don't forget to remove the controller from the notification centre
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.view endEditing:YES];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
  1. implement keyboard notification handlers
- (void)keyboardWillShow:(NSNotification *)notification {


// create custom button
UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeCustom];
doneButton.frame = CGRectMake(0, 107, 106, 53);
[doneButton setTitle:@"Done" forState:UIControlStateNormal];
[doneButton addTarget:self  action:@selector(doneButton:)forControlEvents:UIControlEventTouchUpInside];
 

// save the reference to the button in order to use it in keyboardWillHide method
self.donekeyBoardBtn = doneButton;


// to my mind no need to search for subviews
UIWindow *windowContainigKeyboard = [[[UIApplication sharedApplication] windows]  lastObject];
[windowContainigKeyboard addSubview:self.donekeyBoardBtn];
self.donekeyBoardBtn.frame = CGRectMake(0., CGRectGetHeight(w.frame) -  CGRectGetHeight(self.donekeyBoardBtn.frame), CGRectGetWidth(self.donekeyBoardBtn.frame), CGRectGetHeight(self.donekeyBoardBtn.frame));
}


- (void)keyboardWillHide:(NSNotification *)notification {


[self.donekeyBoardBtn removeFromSuperview];
}
  1. implement done button action
- (void)doneButton:(id)sender {
// add needed implementation
[self.view endEditing:YES];
}


Just building on answers above with the Swift version since I had to translate it:

@IBOutlet weak var numberTextField: UITextField!


override func viewDidLoad() {
addDoneButtonTo(numberTextField)
}


// MARK: Done for numberTextField


private func addDoneButtonTo(textField: UITextField) {
let flexBarButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: nil, action: nil)
let doneBarButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Done, target: self, action: "didTapDone:")
let keyboardToolbar = UIToolbar()
keyboardToolbar.sizeToFit()
keyboardToolbar.items = [flexBarButton, doneBarButton]
textField.inputAccessoryView = keyboardToolbar
}


func didTapDone(sender: AnyObject?) {
numberTextField.endEditing(true)
}

Keyboard view could be found hasPrefix:@"UIKeyboard", the button can not be added as a subview. Here's my solution: enter link description here