One of Apple's big shortcomings in the iPhone SDK is input methods. Apple gives developers very little support in terms of custom input methods, which is why it's so frustrating that the 10-button numeric keyboard that is provided in the SDK is missing something as crucial as a "DONE" button.
Thanks to the work of a development team called Neoos, many app developers found a workaround to this issue by adding a custom button on top of the default numeric keyboard. But in iOS 4, this method stops working. I did some digging and found out everything I could about the issue and want to share it with any developers who might be looking for the same solution I am.
If you're reading this I'm assuming you understand how Neoos' solution to the problem worked. In iPhone OS 3, when a UIKeyboardWillShowNotification was sent, their custom method iterated through all the subviews on the screen to find the keyboard, and then added a custom button on top of it.The problem is this: in iOS 4 (at least, in the Gold Master Seed available to developers as of a few days ago), the keyboard view is not instantiated by the time the UIKeyboardWillShowNotification is sent, so it's impossible to add the custom button to it.
The best solution I've discovered is easy to implement but doesn't provide the same end result that we had in OS 3. By switching from the UIKeyboardWillShowNotification to the UIKeyboardDidShowNotification, the custom method which searches for the keyboard and adds the button isn't called until the keyboard is already on screen. This means that it is guaranteed to find the keyboard view and add the done button. The disadvantage will only be noticed by particularly observant users: as the keyboard slides into place, the bottom left button is still blank, and once the keyboard is in place, the "DONE" button simply appears.
For now, this seems to be the best solution available to us as developers. If anyone manages to find a better solution, I'd love to hear it, and I hope that the information here was helpful in finding that solution.
Thanks for that!
ReplyDeletei can't do that.. can you explain better?
ReplyDeleteactually i'm doing this
in view did load
[[NSNotificationCenter defaultCenter] addObserver: self
selector: @selector(keyboardDidShowOrHide:)
name: UIKeyboardDidShowNotification object:nil];
then the method
- (void) keyboardDidShowOrHide : (id) sender {
UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeCustom];
doneButton.frame = CGRectMake(0, 363, 106, 53);
doneButton.adjustsImageWhenHighlighted = NO;
[doneButton setBackgroundImage:[UIImage imageNamed:@"doneup.png"] forState:UIControlStateNormal];
[doneButton setBackgroundImage:[UIImage imageNamed:@"donedown.png"] forState:UIControlStateHighlighted];
[doneButton addTarget:self action:@selector(doneButton) forControlEvents:UIControlEventTouchUpInside];
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];
}
}
thank you
You can actually add the button before the keyboard shows, if you schedule it on the next run loop pass (performSelector with delay 0). Example code: http://gist.github.com/454844
ReplyDeleteif([[keyboard description] hasPrefix:@"<UIKeyboard"] == YES
ReplyDeleteno longer works in os4 Anyone found out what the new name is?
UIKeyboardDidShowNotification did not work with " hasPrefix:@"<UIKeyboard"" use UITextEffectsWindow
ReplyDeleteor u can use @"<UIPeripheralHostView"
ReplyDeleteThanks a ton saved me a lot of efforts
ReplyDeletebut the Done button disappears when I change my device
ReplyDeleteorientation, and I still need it
@"<UIPeripheralHostView" works okay but, the button is also added to the alphabet keyboard. How to avoid this and only add the Done button to the NumericKeyPad?
ReplyDeleteEsben,
ReplyDeletedo you have a fix for this "zombie" doneButton???
A fade effect could visually enhance the user experience rather than the Done button suddenly appearing :)
ReplyDeleteI can't find anything of that code.Done button is not shown.I test it on ios 4.2.I test it with debugger control is going to subview part at the end of the code but does not show anything.
ReplyDeleteAny kind of help.
thanks
Works for me on 4.3 both device and simulator. I add the observer in the editingDidBegin and remove in editingDidEnd for the field; this way the button is shown only when certain field is beind edited.
ReplyDeleteI won't accept my username and password so I can't upload logs, any ideas
ReplyDeleteThanks for your help! Mine finally worked. Posting the code here in case it helps anyone else:
ReplyDelete- (void)keyboardDidShow:(NSNotification *)note {
// create custom button
UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeCustom];
doneButton.frame = CGRectMake(0, 163, 106, 53);
doneButton.adjustsImageWhenHighlighted = NO;
[doneButton setBackgroundImage:[UIImage imageNamed:@"doneup.png"] forState:UIControlStateNormal];
[doneButton setBackgroundImage:[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:@"<UIPeripheralHostView"] == YES)
{
[keyboard addSubview:doneButton];
return;
}
}
}
Hey Connor, I have found that it is still possible to use KeyboardWillShow in iOS 4 and plus. Have a look at this snippet: https://gist.github.com/454844. Here goes some comments of the author, Henrik N: "There were two issues:
ReplyDeleteUIKeyboardWillShowNotification is sent before the keyboard view exists, but it you schedule your code to run on the next run loop pass, they do exist. So you don't have to bother with DidShow which is visually less pleasing.
On iOS 4 the UIKeyboard view was elsewhere in the view hierarchy."
Hope this could help!
Thanks for the trick. Works great.
ReplyDeletehttps://medium.com/@chan0123/missing-done-button-in-ios-d74810a409b1 May be this this link will help full for u
ReplyDelete