|
Mar
13
|
Of the various keyboards you can choose when developing iPhone apps, the number pad doesn’t come with a decimal point. There is a blank button in the bottom left corner that doesn’t do anything, so I’m going to show you how to put a decimal point button there to look like this:

There are a few other tutorial around that show you how to do this, but i believe mine is better….because the code is simpler to use, its more flexible, and the UI colors and button states are perfectly matched to the rest of the keyboard (unlike some of the other tutorials) The code you use to implement this will look like this:
@interface DecimalPointNumberPadViewController : UIViewController <UITextFieldDelegate> {
NumberKeypadDecimalPoint *numberKeyPad;
}
@end
@implementation DecimalPointNumberPadViewController
- (void) textFieldDidBeginEditing:(UITextField *)textField {
numberKeyPad = [[NumberKeypadDecimalPoint keypadForTextField:textField] retain];
}
- (void)textFieldDidEndEditing:(UITextField *)textField {
[numberKeyPad release];
}
@end
- it works on any number of UITextFields that are displayed on your view controller.
- It will only add one decimal point per text field.
To achieve this, here are the basic steps of what i do:
- Create a custom UIButton with clear background and dark grey text.
- For the highlighted state i change the background image of the button and the text color to be white
- I find the UIKeyboard in the application window and add the custom button at the required location
- I add a delegate to the button to listen for click events and pass the event to a handler which adds a decimal point to the current UITextField
Update 5th June 2010: OS4 compatible and using only public API
As using private API’s is against the SDK agreement, I’ve updated the code to remove references to any private API. It is also now compatible with OS 4.0.
Update 20th July 2010: This code was part of the app I’m working on and was accepted by apple.
A copy of my XCode project is here:
Thanks
DecimalPointNumberPad-v4
March 20th, 2010 at 10:51 pm
Great post. Thanks!
April 27th, 2010 at 10:14 pm
I’m having some difficulty using your custom key pad. When I change from a textfield which uses your custom keypad, to one which uses the default keypad, the decimal image still shows up in the lower left corner when I click there even though the numberkeypad has been releases in the textFieldDidEndEditing method.
Any suggestions?
May 1st, 2010 at 2:13 pm
Hi Cinto,
Yes – its seems this was a bug. I’ve updated the XCode project so that it now removes the decimal button from the keyboard when it is released. I’ve tested and it appears to be working ok now.
Thanks
May 9th, 2010 at 7:34 pm
Do you know whether this works with:
1) iPad – When using compatibility mode (ie running it using the iPhone UI)?
2) iPhone OS4?
I believe some of the other methods were broken when used with the iPad and then worked with some published modifications. However, I believe iPhone OS4 may have broken it again. Thanks.
May 19th, 2010 at 8:44 am
Very nice, thank you. Unfortunately though I’ve experienced the same as StatCoder; this keypad crashes under OS 4.
May 19th, 2010 at 11:20 am
Hi StatCode/Sarah,
Thanks for pointing this out. I haven’t tested for iPad or iPhone OS4.
My project is about to be tested on OS4 – so I will be fixing this for the OS4 official release.
Thanks
May 23rd, 2010 at 6:25 am
Any luck with OS4? The issue is the ability to obtain the keyboard view in order to add the button:
for(int i = 0; i < [keyboardWindow.subviews count]; i++) {
keyboard = [keyboardWindow.subviews objectAtIndex:i];
// keyboard view found; add the custom button to it
if([[keyboard description] hasPrefix:@"<UIKeyboard"] == YES)
[keyboard addSubview:button];
}
I even tried to add the button view to the main window but it still appears behind the keyboard.
May 26th, 2010 at 1:24 pm
Hey,
I’m VERY new to iPhone dev and have been looking for a solution to this problem for the last couple of days until I found your page. Could you maybe give me a little bit of help with respect to how I actually implement this in my own app? Do I have to link certain things etc?
May 26th, 2010 at 2:18 pm
Conor, just download the example code i provide and copy the source into your project. You don’t have to link any libraries.
May 26th, 2010 at 2:20 pm
StatCoder,
I still haven’t looked into it – however i won’t forget as it’s a requirement of the client in my current project, so it will be done – and i will post the solution here.
Thanks
May 26th, 2010 at 4:23 pm
This really looks great! But me as others can’t get it to work in 4.0, please post here if anyone find a solution. Thanks!
May 29th, 2010 at 12:56 am
I’m starting to believe that there is no way to access the keyboard anymore. You can add a view to the top edge of a keyboard with inputAccessoryView and you can specify your own custom keyboard view with inputView, however, iterating through the windows, the commonly used method to access the keyboard, was broken in the last two betas. I imagine that some developers are creating their own custom keyboards, however, that seems to be a lot of trouble to add a single custom key.
May 30th, 2010 at 10:03 pm
Hello,
I have the same problem of Conor Higgins: I am unable to use your code in my project. These are my steps:
1) I added files “DecimalPointButton.h” and “DecimalPointButton.m” to my project.
2) I added the protocol definition to the view controller with the UITextField.
3) I added the “textFieldDidBeginEditing” and “textFieldDidEndEditing” methods to the view controller, like into the article.
With these 3 changes nothing happens. What is my error???
Thank you for your help, and thank you for sharing your wonderful code
June 4th, 2010 at 3:38 pm
Hi All,
I just spent the last hour fixing this in OS4. I have a fix and will post the code on here this weekend.
Thanks
June 5th, 2010 at 2:56 pm
Someone posted an email that they received from Apple last night regarding the customization of keyboards:
“The organization and layout of the view hierarchy for the keyboard are undocumented and private. There are no public APIs in the iPhone OS SDK provided for keyboard customizations on the iPhone, and modifying or extending the view hierarchy of the keyboard is modifying or extending a private API.”
June 5th, 2010 at 9:30 pm
Hi,
I’ve posted the updated code. I’ve also removed any reference to private API’s.
I now add the button to the topmost window on the phone, whatever it may be. So no reference to any private API’s there. I animate it in so that it doesn’t look too out of place.
To work on OS 4.0 i also had to add a timer to the textFieldDidBeginEditing method – this is to allow the keyboard time to become the topmost window, after which the custom button can sit on top again.
Thanks
Dave
June 6th, 2010 at 4:28 am
Looks great, Dave. I guess the timer was the key. It was a cinch to implement and seems to be testing out fine so far. Good work. It’s really appreciated.
June 6th, 2010 at 7:02 pm
CParib,
Have you looked into the source project i provided? Its a small project, and if you look at the view controller in there – it shows you what you need to add to the “textFieldDidBeginEditing” and “textFieldDidEndEditing” methods.
Thanks
Dave
June 7th, 2010 at 5:54 am
Thanks for the info and example here, I got an email from apple on Friday telling me I could not use private API’s to add a decimal point to the keyboard, and I was starting to think I would have to make my very own keyboard.
This example works perfectly for me.
Thanks Aaron
June 9th, 2010 at 12:16 pm
Aaron,
Let us know what happens after your next app submission.
Thanks
June 10th, 2010 at 6:36 am
I have noticed a couple of issues when using this method with multiple textviews. Sometimes the decimal button reanimates itself onto the keypad when switching directly from one textview to another. If you push an alert view such as after doing a range check, the decimal button will not be there after the alert is dismissed. I’m guessing that the button gets animated onto the alert and then disappears with the alert. Thanks.
June 10th, 2010 at 9:59 am
Hey,
Yeah, somebody raised this issue to me this morning. I’ll be working on this later, so i’ll probably post an update later on today.
Thanks
June 10th, 2010 at 6:42 pm
I’ve updated the code to remove the bug with the decimal point re-animating itself.
I’ve also tried pushing a UIAlertView on the screen too, and it still seems to work – but i’m not entirely sure what exactly you meant with your bug. Are you doing a range check on the text field with: shouldChangeCharactersInRange ?
My changes are all in the view controller. I now only release the decimal point if the keyboard is dismissed (instead of on each textfield change).
June 13th, 2010 at 4:02 pm
I’m trying to modify this sample to implement a Done button rather than a decimal point.
To do this I need to implement the keypadWithDelegate rather than the keypadForTextField, so I can use the decimalPointPressed method to do the same job as backgroundTap in your sample.
I tried modifying keypadWithDelegate to return a pointer like keypadForTextField does, but I’m missing something. When I release the numkeypad the Done button stays on screen.
Can you show me a small sample? Thanks!
June 13th, 2010 at 5:20 pm
I figured it out. I modified keypadWithTextField to do double duty:
+ (NumberKeypadDecimalPoint *) keypadForTextField:(UITextField *)textField id:_delegate {
NumberKeypadDecimalPoint *keypad = [[NumberKeypadDecimalPoint alloc] init];
keypad.decimalPointButton = [DecimalPointButton decimalPointButton];
keypad.currentTextField = textField; //Save reference to current textfield being edited
[keypad.decimalPointButton addTarget:_delegate action:@selector(decimalPointPressed) forControlEvents:UIControlEventTouchUpInside];
[keypad addButtonToKeyboard:keypad.decimalPointButton];
return [keypad autorelease];
}
Then, in the delegate decimalPointPressed, I duplicated the backgroundTap code. I changed the button code to add DoneUp and DoneDown images instead of the decimal point, and voila!
June 15th, 2010 at 12:19 am
The latest code update seems to resolve all of the issues I was experiencing. Thanks.
June 15th, 2010 at 7:18 pm
Hi,
I have just tried your latest code and think I have found a glitch, if you randomly click each text box / background a lot of times eventually the . will not appear or over lays on the standard keyboard.
I am testing this with OS4.
Thanks Aaron
June 15th, 2010 at 9:32 pm
Hi,
OK thanks for reporting this. I’ll give it a good clicking tomorrow and figure out what’s up.
Thanks
June 23rd, 2010 at 3:33 pm
This is great. I added a done button on the top for my project and now I am ready to show my boss, Just one question, is it ok if I use your code/graphics in my commercial project, I noticed that your code says all rights reserved across the top. Thanks.
June 23rd, 2010 at 9:28 pm
Hi beleg,
Yes – ignore the ‘rights reserved’ default comment. You can use any code I post on here commercially.
Thanks
June 24th, 2010 at 12:59 pm
First off, thanks for the great post. Secondly, I’ve noticed that when you go from a UITable view to a new view and call out the keyboard, the decimal point doesnt appear until you click another text field and reload the delegate. Then when you leave the view and go back to the table view the decimal point stays active until the view switch animation i finished. Any recommendations?
June 26th, 2010 at 10:32 am
Hi thank you for all your work and for publishing it…
I think I have found a little error… when I run your sample project and I go in one of the two textfields with a number-keypad but I don’t press anything and then I go into the normal-keypad textfield… I can’t press the “.?123″ key as the decimal point keeps showing up… So I get a decimal point in the normal-keypad textfield, when I don’t want it…
Could take a look at this and see if you have the same issue?
Thanks.
June 27th, 2010 at 7:28 pm
@Aaron Wardle
I’ve fixed this issue you reported. Thanks.
@Ploeter
I’ve also fixed this issue.
Both are in the new project I’ve uploaded (version 4).
I’ve only tested on the simulator on OS 3.1.3 and OS 4.
June 28th, 2010 at 3:19 pm
@admin
Still getting the decimal point overlay. Would you use any special methods to release the keypad at view transition?
June 28th, 2010 at 4:02 pm
Hi Brent,
If you saved a reference to your numberKeyPad in textFieldDidBeginEditing you should be able to remove it from the screen using:
[self.numberKeyPad removeButtonFromKeyboard];
self.numberKeyPad = nil;
Try that and let me know how you get on.
Thanks
June 28th, 2010 at 7:02 pm
Ok, it responds from view transition with a:
[numberKeyPad removeButtonFromKeyboard];
numberKeyPad = nil;
errors out when you call self.* but it works.
June 28th, 2010 at 7:32 pm
Well you can only call self.* if you have it declared as a property on your view controller.
July 1st, 2010 at 3:19 pm
It this a good way to make the decimal point key stay “in place” after orientation?…
In NumberKeypayDecimalPoint.m’s init() add this line:
…
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationDidChange:) name:UIDeviceOrientationDidChangeNotification object:nil];
…
and this method:
- (void)orientationDidChange:(NSNotification *)notificaton {
if([[UIDevice currentDevice] orientation] == UIDeviceOrientationPortrait)
self.frame = CGRectMake(0, 427, 105, 53);
else
self.frame = CGRectMake(0, 281, 158, 39);
}
or is there a “proper” way to do it?
Thanks very much for this excellent article. I am a newbie and would not have had any idea where to start.
July 1st, 2010 at 3:50 pm
…but when the keyboard window is rotated to Horizontal and then its “parent” is returned to, and then the parent is de-rotated to Vertical and the keyboard re-entered – the button is still in Horizontal position (on top of the ‘1′ key)…
…so I altered the above code to this:
- (void)orientationDidChange:(NSNotification *)notificaton {
[self initButton];
}
-(void)initButton{
if([[UIDevice currentDevice] orientation] == UIDeviceOrientationPortrait)
self.frame = CGRectMake(0, 427, 105, 53);
else
self.frame = CGRectMake(0, 281, 158, 39);
}
and added this line:
keypad.decimalPointButton.initButton;
to the keypadForTextField(…) method, just after the if(…) i.e.
if( !(keypad) ) {
…
}
keypad.decimalPointButton.initButton;
keypad.currentTextField = textField;
…
July 6th, 2010 at 9:40 pm
I’m trying to incorporate this into a tab view. I add the tab view manually (starting with view controller then adding the tab view to the main.xib). I got your code to work with my single view controller before adding the tab bar view. When I add the other view and the tab bar, it won’t function. I tried using your original code, added a second view (with exactly the code and nib of the first one with “view 2″ put in so I could tell the difference) and put in the tab bar into main.xib. I think I connected everything correctly but it won’t work. On yours (with the added 2nd view and tab bar) the app works but without the tab bar. On mine, it doesn’t do anything (literally, it shows a black screen – builds just fine, no errors and no exceptions, but black screen on the simulator).
Any ideas? Have you used it in a tab bar controller app before?
bon
July 6th, 2010 at 10:17 pm
Sounds like you have other unrelated issues. You might be better posting this question on some forums such as the apple dev forums. Sounds like you haven’t reconnected your view to your controller at a guess. And yes, I use this code within a tab bar controller.
July 7th, 2010 at 3:00 pm
Just HAD to say, a massive thank you!
Your code is fantastic, and will greatly improve my app
by allowing me to use the number pad as opposed to the
normal keyboard.
seriously, this is great, and you are a swell person for taking
the time to help n00bs like myself.
have a good one
July 9th, 2010 at 11:41 am
Hey I’ve got some questions about your code.
So I downloaded the project, but I’m trying to get it into one of my projects. What exactly do I have to move over? Which files do I HAVE to move over, and which ones am I NOT supposed to move over?
The code that you displayed on this page (for “how to implement” the look) is confusing me. What file am I supposed to put it in?
Sorry, I’m completely new to all of this.
Thanks!
July 9th, 2010 at 10:22 pm
What if I want to have one text field where I want to show the decimal on the keyboard and another text field that I want to use the normal numeric keypad?
Thanks
July 11th, 2010 at 8:14 pm
Just to let you know that I submitted my app using your decimal point…
It took them almost two full weeks to review it but it was finally accepted yesterday…
Thanks
July 17th, 2010 at 12:29 pm
I’ll tell you that the old code with the method (void) keyboardWillShow:(NSNotification *)note is working with OS4. But you need a bit update.
You don’t need to detect the keyboard prefix because in a TextEdit, because natively, you have a keyboard with it.
I’ll post my code when i am in my mac.
July 21st, 2010 at 10:34 am
Strange thing. Your new code works very good… until i save it.
When i debug your code- there is a dot and turning off keyboard.
When i just save project (eg in IB but without doing any changes- just saving) dot and turning off keyboard is lost :/ After debugging there is nothing more than just normal number pad (without dot) and it doesn’t turn off.
Why is it working like this?
July 21st, 2010 at 10:39 am
A little update: it does work when i save project in xcode, but if i enter Interface Builder (even without saving) it doesnt work any more o.O
July 21st, 2010 at 4:59 pm
Thanks for the great solution! The only feature I’m missing is that the button doesn’t make the clicking sound as other buttons do.
Keep up the good work!
Max
July 21st, 2010 at 5:04 pm
To make clicking sound (the volume is wrong though…):
#import
NSString *path = [[NSBundle bundleWithIdentifier:@"com.apple.UIKit"] pathForResource:@”Tock” ofType:@”aiff”];
SystemSoundID soundID = 0×100;
AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath:path], &soundID);
AudioServicesPlaySystemSound(soundID);
July 25th, 2010 at 6:46 am
Thanks for this. Makes a huge difference to my app with this.
James
July 29th, 2010 at 6:06 am
i want smthng that ’s compact
July 29th, 2010 at 9:04 am
Hi,
I’ve been working with this code and it seems to be working as in I’m not getting any errors but the decimal button just isn’t showing up. What am I missing? Has anyone else experienced something like this? I thought it might have something to do with the fact that I have 2 view controllers, but it still shouldnt really be causing that.
If anyone can help it would be great. I’m pretty confused at this stage.
Bob
July 30th, 2010 at 6:59 pm
I’m sure you are aware that you can receive notifications for when the keyboard appears. Why not use the UIKeyboardDidShowNotification instead of the timer to trigger the adding of the button? I guess it might be harder to animate it in in that case. The fact that the implementation uses a timer makes me uncomfortable though, but otherwise, great work.
August 2nd, 2010 at 7:44 pm
Hi Bob1601,
the code should also work with a flip view. You should be adding your delegate in Interface Builder. Just right click on the “files owner” and connect your input fields.
Ralf
August 4th, 2010 at 11:08 pm
Hi, i put your example in my code, but when the keypad dissapear, the button still in the view and is in nfornt of my tab bar, for hese reason my first tab button of my tab bar cant be use and when i clicked i activate the button. eny solution please?
August 5th, 2010 at 4:16 pm
Thanks
Works great
August 6th, 2010 at 2:41 am
Wow..just what I’ve been looking for! You’re awesome.
Although I’m having troubles getting it to work with my project. I’m using it in a TabBarController based app. I’ve included the NumberKeypadDecimalPoint.h and .m files and copy pasted the rest of the code, but no go. Is there a trick to using this with a TabBar app?
August 6th, 2010 at 5:29 pm
Good work on this, however, I have 3 views using a UITabBarController and this works only on the last view. The other two views don’t show the decimal point at all. Has anyone gotten this error?
August 6th, 2010 at 8:15 pm
Figured it out! Fingers crossed Apple accepts it.
August 7th, 2010 at 1:13 pm
Very good tutorial.
August 8th, 2010 at 12:35 pm
Thanks!
August 10th, 2010 at 11:57 am
Hello,
Can i change button text dynamically with ‘.’ or ‘,’ or ‘;’ or etc. ?
Thanks
August 12th, 2010 at 4:08 pm
Thanks a lot David for the code. I am sending you here to take your permission to add your code to our Sensible TableView product. We’d be really happy to give you a gift version in exchange. Please have a look at Sensible TableView at: http://www.sensiblecocoa.com . Thanks a lot.
August 29th, 2010 at 10:46 am
Hi Tarek, sure you have my permission to use this code in your product.
August 30th, 2010 at 6:01 am
Thank you for great tutorial!!