How to add a 'Done' button to numpad keyboard in iOS
Solution 1
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)
Solution 2
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)
}
Solution 3
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:
It also has many other cool features.
Solution 4
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)
}
Solution 5
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.
Related videos on Youtube
George McKibbin
Updated on May 12, 2021Comments
-
George McKibbin almost 3 years
So, the numpad keyboard doesn't come with a 'Done' or 'Next' button by default so I'd like to add one. In iOS 6 and below there were some tricks to add a button to the keyboard but they don't seem to be working in iOS 7.
First I subscribe to the keyboard showing notification
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
Then I try to add a button when the keyboard shows up:
- (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]; } }
But the for loop doesn't run because it doesn't find any subviews. Any suggestions? I couldn't find any solutions for iOS7 so is there a different way I'm supposed to be doing this?
Edit: Thanks for all the suggestions for toolbars guys but I'd rather not go down that route as I'm quite space poor (and it is kind of ugly).
-
Anil over 10 yearsTried this post? neoos.ch/blog/…
-
βhargavḯ over 10 years@Anil That way of customizing UIKeyboard is prohibited by apple.
-
Praveen Matanam over 10 yearsCheck with UIKeyboardDidShowNotification.
-
the1pawan over 10 years
-
Anil over 10 years@βḧäṙℊặṿῗ does Apple allow you to customize numberpads?
-
George McKibbin over 10 years@Anil That is the way I've already tried.
-
βhargavḯ over 10 years@Anil I am using approach to set inputAccessoryView to textFields.
-
Vinodh over 10 yearsCan you try github.com/simonbs/BSKeyboardControls which is the class which adds toolbar with next and previous button on top of keyboard
-
George McKibbin over 10 yearsI don't really want to add a toolbar, I want to put the button right on the keyboard.
-
Balram Tiwari over 10 years@Anil Please look at my answer below. That is a working solution for iOS7 & as well maintaining backward compatibility. Link to answer is here.
-
landonandrey over 7 yearsSee my answer here. Works on both iOS8/iOS9.
-
-
George McKibbin over 10 yearsI might have to end up doing this. I don't really like how much space it takes up.
-
Bhavin over 10 years@GeorgeMcKibbin: The space should not be the issue here as it will take that space only while you are typing. Also, according to me this approach is far better than messing up with Keyboard that usually Apple does not like.
-
George McKibbin over 10 yearsThanks, this is what I wanted :) Unfortunately If there was already a keyboard on screen and then you switch to a field that needs a numpad keyboard then keyBoardWillShow doesn't get called. But thanks, a step in the right direction haha.
-
govo about 10 yearsSYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO why not NSFoundationVersionNumber>NSFoundationVersionNumber_iOS_6_0? And I test it, NSFoundationVersionNumber_iOS_5_0 is better
-
pronebird almost 10 yearsdispatch_async is not the most reliable method to hack into keyboard here. :(
-
Balram Tiwari almost 10 years@Andy : Kindly Provide more justification for unreliability of dispatch_async or else the most reliable method to use this with this approach. You are free to edit the answer.
-
pronebird almost 10 years@BalramTiwari I wish I could, but after hacking for a while it seems to me that Apple moved keyboard initialisation after all public notifications fired. I mean, generally my suggestion here is to stay away from hacking keyboard, even though I see the benefits from UX perspective.
-
pronebird almost 10 years@BalramTiwari dispatch_async solutions are easy to break in future because they depend on Runloop.
-
Mark McCorkle over 9 yearsIt looks like to me you added a flex bar button to Bhavin's answer from 1 year ago as a new answer so I could see why someone down voted it. Maybe I missed something here as well?
-
Andrey Gordeev over 9 yearsYes, I don't use
initWithTitle:@"Done"
, I useinitWithBarButtonSystemItem:UIBarButtonSystemItemDone
instead. This will return standard Apple's Done bar button. Moreover, it'll be already localized -
Mark McCorkle over 9 yearsThis should be added as an improvement (comment) to the previously correct answer IMO or expect down votes. A new answer should involve a different approach to the original question, not an improvement to an existing question. Nonetheless, thank you for the improvement. ;-)
-
Andrey Gordeev over 9 yearsNo, I don't think so. Comments are not supposed to be used for writing code :)
-
Hemant Chittora over 9 yearsin iOS8 this done button is not hiding, After dismissal of keyboard.
-
Chris over 9 yearsWhen I do this, I only get the toolbar at the very bottom of my screen and the keyboard no longer appears. Thoughts?
-
Austin over 9 yearsgreat answer, just one tidbit, arrayWithObjects is unspokenly deprecated in favor of literals: [NSArray arrayWithObjects:doneButton, nil] => @[doneButton]
-
Fred Faust about 9 yearsThis works great but when an iPhone 6+ starts in portrait and then is rotated to horizontal the Done button no longer functions, any idea?
-
Radu Simionescu over 8 yearsthis is the correct way of doing it. Overlaying a button over the keyboard is a bad idea because the layout can change with future versions of IOS.
-
SwiftArchitect about 8 yearsThis answer, albeit clever, was bound to break.
-
Nazir about 8 yearsfrom iOS 8.0
UIBarButtonItemStyleBordered
is deprecated useUIBarButtonItemStyleDone
orUIBarButtonItemStylePlain
-
Arpit B Parekh over 7 yearsI implemented your answer very similar to what I have to do. Thanks. But button do not come as an animated object, when keyboard show.