iPhone: Animate an object along a path iPhone: Maintain visibility of form inputs – auto-scrolling views
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:
Screen shot 2010-03-13 at 17.40.13 Screen shot 2010-03-13 at 17.40.19

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:

  1. Create a custom UIButton with clear background and dark grey text.
  2. For the highlighted state i change the background image of the button and the text color to be white
  3. I find the UIKeyboard in the application window and add the custom button at the required location
  4. 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:

xcodeProjectDecimalPointNumberPad-v4

Thanks

written by admin \\ tags: , , , ,


66 Responses to “iPhone: Number Pad with a decimal point (OS 3.0, OS 4.0) using public API”

  1. 1. bennyb Says:

    Great post. Thanks!

  2. 2. Cinto Says:

    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?

  3. 3. admin Says:

    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

  4. 4. StatCoder Says:

    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.

  5. 5. Sarah Says:

    Very nice, thank you. Unfortunately though I’ve experienced the same as StatCoder; this keypad crashes under OS 4.

  6. 6. admin Says:

    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

  7. 7. StatCoder Says:

    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.

  8. 8. Conor Higgins Says:

    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?

  9. 9. admin Says:

    Conor, just download the example code i provide and copy the source into your project. You don’t have to link any libraries.

  10. 10. admin Says:

    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

  11. 11. Martinq Says:

    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!

  12. 12. StatCoder Says:

    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.

  13. 13. CParib Says:

    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

  14. 14. admin Says:

    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

  15. 15. StatCoder Says:

    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.”

  16. 16. admin Says:

    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

  17. 17. StatCoder Says:

    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.

  18. 18. admin Says:

    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

  19. 19. Aaron Wardle Says:

    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

  20. 20. admin Says:

    Aaron,

    Let us know what happens after your next app submission.

    Thanks

  21. 21. StatCoder Says:

    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.

  22. 22. admin Says:

    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

  23. 23. admin Says:

    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).

  24. 24. Steve Says:

    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!

  25. 25. Steve Says:

    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!

  26. 26. StatCoder Says:

    The latest code update seems to resolve all of the issues I was experiencing. Thanks.

  27. 27. Aaron Wardle Says:

    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

  28. 28. admin Says:

    Hi,

    OK thanks for reporting this. I’ll give it a good clicking tomorrow and figure out what’s up.

    Thanks

  29. 29. beleg Says:

    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.

  30. 30. admin Says:

    Hi beleg,

    Yes – ignore the ‘rights reserved’ default comment. You can use any code I post on here commercially.

    Thanks

  31. 31. Brent Says:

    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?

  32. 32. Ploeter Says:

    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.

  33. 33. admin Says:

    @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.

  34. 34. Brent Says:

    @admin

    Still getting the decimal point overlay. Would you use any special methods to release the keypad at view transition?

  35. 35. admin Says:

    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

  36. 36. Brent Says:

    Ok, it responds from view transition with a:

    [numberKeyPad removeButtonFromKeyboard];
    numberKeyPad = nil;

    errors out when you call self.* but it works.

  37. 37. admin Says:

    Well you can only call self.* if you have it declared as a property on your view controller.

  38. 38. Robin Pain Says:

    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.

  39. 39. Robin Pain Says:

    …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;

  40. 40. Bon Crowder Says:

    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

  41. 41. admin Says:

    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.

  42. 42. squirehenry Says:

    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

  43. 43. lol Says:

    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!

  44. 44. MrT Says:

    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

  45. 45. Ploeter Says:

    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

  46. 46. Herison Says:

    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.

  47. 47. Vivelee Says:

    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?

  48. 48. Vivelee Says:

    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

  49. 49. Maxim Bashevoy Says:

    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

  50. 50. Maxim Bashevoy Says:

    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);

  51. 51. James Says:

    Thanks for this. Makes a huge difference to my app with this.

    James

  52. 52. hrithik Says:

    i want smthng that ’s compact

  53. 53. Bob1601 Says:

    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

  54. 54. Ivan Says:

    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.

  55. 55. Ralf Says:

    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

  56. 56. James Says:

    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?

  57. 57. croyboy Says:

    Thanks
    Works great

  58. 58. Ryan Says:

    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?

  59. 59. Janice Says:

    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?

  60. 60. Ryan Says:

    Figured it out! Fingers crossed Apple accepts it.

  61. 61. Debabrata Biswas Says:

    Very good tutorial.

  62. 62. MK Says:

    Thanks!

  63. 63. Hasan Aydın Says:

    Hello,

    Can i change button text dynamically with ‘.’ or ‘,’ or ‘;’ or etc. ?

    Thanks

  64. 64. Tarek Sakr Says:

    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.

  65. 65. admin Says:

    Hi Tarek, sure you have my permission to use this code in your product.

  66. 66. kyu Says:

    Thank you for great tutorial!!

Leave a Reply

i3Theme sponsored by Top 10 Web Hosting and Hosting in Colombia