Search code examples
iosiphonecocoa-touchuitextfielduikit

How to add a 'Done' button to numpad keyboard in iOS


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


Solution

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