UIKeyboardTypeNumberPad and the missing "return" key
If you have ever written an iPhone app that requires numeric input, then you surely know about the UIKeyboardTypeNumberPad. And if you have ever used that flavor of the iPhone's keyboard, then you surely know that it lacks one very important feature: The UIKeyboardTypeNumberPad does not have a "return" key.
UPDATE 17 June 2010
With the arrival of new iOS versions (like 3.2 for iPad and 4.0 for iPhone/iPod touch), some internals regarding our solution have seized working due to changes in the SDK on Apple's side (as some of our readers pointed out in the comments). Now we have updated our solution to also work with iOS versions > 3.1.3 (meaning specifically 3.2 and 4.0GM "golden master"). Please feel free to download the complete XCode project at the bottom of the article.
To keep it short, the behaviour of the keyboard has changed in versions > 3.1.3 in such a manner that it's no longer possible to add the button before the keyboard slides up. This means that the done button has to be added after the keyboard is put in place. This has been pointed out andexplained in more detail by one of our readers.
In that way, the new solution is not perfect. On the other hand, most users will not be aware of it anyway. We're looking into the matter in more detail when we find some spare time and maybe come up with a more sophisticated solution.
In fact every other keyboard type (except for the pretty similar UIKeyboardTypePhonePad) does offer the possibility to be dismissed by setting the returnKeyType property of the corresponding UITextInputTraits implementor. So how does one achieve the same effect with the number pad? We have found a workround!
When looking at the number pad, you'll notice that there is an unused space on its bottom left. That's where we are going to plug in our custom "return" key.
![](http://www.neoos.ch/images/stories/shotnodone.png)
To make it short: take a screenshot, cut out the whole backspace key, flip it horizotally, clear its backspace symbol in Photoshop and overlay it with the text that we want on our “return” key. We’ve chosen to label it “DONE”. Now we have the image for our custom button’s UIControlStateNormal. Repeat the whole procedure (with a touched backspace key when taking the screenshot) to get a second image for our button’s UIControlStateHighlighted. Here’s the result:
![](http://www.neoos.ch/images/stories/doneup.png)
![](http://www.neoos.ch/images/stories/donedown.png)
Now back to coding. First we need to know when the number pad is going to be slided up on the screen so we can plug in our custom button before that happens. Luckily there’s a notification for exactly that purpose, and registering for it is as easy as:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];
Don't forget to remove the observer from the notification center in the appropriate place once you're done with the whole thing:
[[NSNotificationCenter defaultCenter] removeObserver:self];
Now we’re getting to the heart of it. All we have to do in the keyboardWillShow method is to locate the keyboard view and add our button to it. The keyboard view is part of a second UIWindow of our application as others have already figured out (see this thread). So we take a reference to that window (it will be the second window in most cases, so objectAtIndex:1 in the code below is fine), traverse its view hierarchy until we find the keyboard and add the button to its lower left:
- (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:@"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 view found; add the custom button to it
if([[keyboard description] hasPrefix:@"UIKeyboard"] == YES)
[keyboard addSubview:doneButton];
}
}
Voilà, that’s it! The empty space for our button starts at coordinate (0, 163) and has the dimensions (106, 53). The doneButton method has to be written now of course, but that’s not hard any more. Just make sure that you call resignFirstResponder on the text field that is being edited to have the keyboard slide down.
![](http://www.neoos.ch/images/stories/shotwithdone.png)
We’re “DONE”.
We have just discovered that the graphical design of the keyboard has slightly changed in the current iPhone OS 3.0 beta version. This means that the position and the image of our custom button will have to be adapted to that new style.
The whole thing can be downloaded as an Xcode project from us.
UPDATE: download 3.0 compatible Xcode project.
UPDATE 2010: download the newest version (runs on all "known" versions 2.0 - 4.0)
AppManiac· 208 weeks ago
Bernd· 208 weeks ago
I found it to work better though with a textfield delegate instead of notification. This was because I had several textfields, both numbers and conventional text.
Great Post!
Bernd
sdd· 208 weeks ago
kayhan· 207 weeks ago
John Biesnecker· 207 weeks ago
Barak· 206 weeks ago
Benjamin Ragheb· 204 weeks ago
for (UIView *keyboard in tempWindow.subviews) {
if ([[[keyboard class] name] hasPrefix:@"UIKeyboard"]) {
[keyboard addSubview:doneButton];
break;
}
}
Usually modifying a collection while fast-enumerating it will cause an exception to be thrown, but we can get away with it in this case because we immediately break out of the loop after the modification.
Cormac· 204 weeks ago
Doug· 199 weeks ago
Harris· 198 weeks ago
http://harrisrappaport.com/misc/ReturnUp.png
http://harrisrappaport.com/misc/ReturnDown.png
Mark3p· 197 weeks ago
This has been accomplished by altering the following two lines
[doneButton setImage:[UIImage imageNamed:@"DoneUp.png"] forState:UIControlStateNormal];
[doneButton setImage:[UIImage imageNamed:@"DoneDown.png"] forState:UIControlStateHighlighted];
by
if ([[[UIDevice currentDevice] systemVersion] hasPrefix:@"3"]) {
[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];
}
DuMe· 196 weeks ago
Thanks
Charlie· 195 weeks ago
peter· 194 weeks ago
Chris· 194 weeks ago
numerics1p· 193 weeks ago
theDark· 188 weeks ago
this was a huge help! thank you very much!
Vince· 187 weeks ago
L Ramsey· 183 weeks ago
Here's a snippet that adds the button using the textFieldDidBeginEditing method of the UITextFieldDelegate protocol.
- (void) textFieldDidBeginEditing:(UITextField *)textField {
if (textField == passwordValue) {
// 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];
}
}
}
}
Richard Brown· 182 weeks ago
Thanks for the post.
João Cargas· 181 weeks ago
work perfectly, but i would like it work in landscape mode too when i rotate, but i can't, how i can do it?
thanks
João Cargas· 181 weeks ago
"doneButton.frame = CGRectMake(0, 123, 158,39);"
I create other images, but they don't appear in device, but resign is ok and simulator all is ok
Yuri· 181 weeks ago
mat· 178 weeks ago
i want to attach this feature to my nib file..but if i override viewLoad method (like in the folder project) my xib file doesn't appear,
there is just a textFiled created in the viewLoad.
Sorry for my bad english!!
zefcan· 178 weeks ago