রবিবার, ১৮ মার্চ, ২০১২

Add Done Button at numberpad in iPhone

Every keyboard type except number pad offer return key. By using which user can hide keyboard. 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.

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



To achieve this we can create two images and like done button in number pad and set this images to a button for state UIControlStateNormal  and UIControlStateHighlighted for iOS 3 and iOS 4. Then add this button to keyboard when keyboard shows.

   

Now back to coding. First we need to know when the number pad is going to be slides up on the screen so we can put our custom button before that happens. Luckily there’s a notification for exactly that purpose, and registering for it is as easy as:
 
 //Add observers for the respective notifications (depending on the os version)
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 3.2) {
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(keyboardDidShow:)
                                                     name:UIKeyboardDidShowNotification
                                                   object:nil];
 
    }
    else
    {
        [[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. iOS 4 sticks the UIKeyboard inside a UIPeripheralHostView. In iOS 3 keyboard view is part of a second UIWindow of our application as others have already figured out. 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. So, we need to check device version first then add done button to keyboard.
 
- (void)keyboardWillShow: (NSNotification *)notification {
    if(!addDone){
        return;
    }else{
        if ([[[UIDevice currentDevice] systemVersion] floatValue] < 3.2) {
            [self performSelector:@selector(addHideKeyboardButtonToKeyboard) 
                           withObject:nil afterDelay:0];
        }
    }       
} 
 
 
- (void)keyboardDidShow:(NSNotification *)notification {
    if(!addDone){
       return;
    }else{
       if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 3.2) {
           [self performSelector:@selector(addHideKeyboardButtonToKeyboard) withObject:nil afterDelay:0];
       }
    }  
}
 

- (void)addHideKeyboardButtonToKeyboard {
    UIWindow *keyboardWindow = nil;
    for (UIWindow *testWindow in [[UIApplication sharedApplication] windows]) {
       if (![[testWindow class] isEqual:[UIWindow class]]) {
           keyboardWindow = testWindow;
           break;
       }
    }
    if (!keyboardWindow) return;
   
    // Locate UIKeyboard.
    UIView *foundKeyboard = nil;
    for (UIView *possibleKeyboard in [keyboardWindow subviews]) {
      
       // iOS 4 sticks the UIKeyboard inside a UIPeripheralHostView.
       if ([[possibleKeyboard description] hasPrefix:@"<UIPeripheralHostView"]) {
           possibleKeyboard = [[possibleKeyboard subviews] objectAtIndex:0];
       }                                                                               
      
       if ([[possibleKeyboard description] hasPrefix:@"<UIKeyboard"]) {
           foundKeyboard = possibleKeyboard;
           break;
       }
    }
   
    if (foundKeyboard) {
       [self addButtonToKeyboard];
    }
}



 
-(void)addButtonToKeyboard {
    // create custom button
    doneButton = [[UIButton buttonWithType:UIButtonTypeCustom] retain];
    doneButton.frame = CGRectMake(0, 163, 106, 53);
    doneButton.adjustsImageWhenHighlighted = NO;
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 3.0) {
       [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];
    }
    [doneButton addTarget:self action:@selector(removeNumberKeyboardWhenDonePressed:) forControlEvents:UIControlEventTouchUpInside];
    // locate keyboard view
    UIView *keyboard;
    UIWindow* tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:1];
    for(int i=0; i<[tempWindow.subviews count]; i++) {
       keyboard = [tempWindow.subviews objectAtIndex:i];
       // keyboard found, add the button
       if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 3.2) {
           if([[keyboard description] hasPrefix:@"<UIPeripheralHost"] == YES)
               [keyboard addSubview:doneButton];
       } else {
           if([[keyboard description] hasPrefix:@"<UIKeyboard"] == YES)
               [keyboard addSubview:doneButton];
       }
    }
    buttonAdded = YES;
} 
 
-(void)addButtonToKeyboard {
    // create custom button
    doneButton = [[UIButton buttonWithType:UIButtonTypeCustom] retain];
    doneButton.frame = CGRectMake(0, 163, 106, 53);
    doneButton.adjustsImageWhenHighlighted = NO;
    if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 3.0) {
       [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];
    }
    [doneButton addTarget:self action:@selector(removeNumberKeyboardWhenDonePressed:) forControlEvents:UIControlEventTouchUpInside];
    // locate keyboard view
    UIView *keyboard;
    UIWindow* tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:1];
    for(int i=0; i<[tempWindow.subviews count]; i++) {
       keyboard = [tempWindow.subviews objectAtIndex:i];
       // keyboard found, add the button
       if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 3.2) {
           if([[keyboard description] hasPrefix:@"<UIPeripheralHost"] == YES)
               [keyboard addSubview:doneButton];
       } else {
           if([[keyboard description] hasPrefix:@"<UIKeyboard"] == YES)
               [keyboard addSubview:doneButton];
       }
    }
    buttonAdded = YES;
}
 

That’s it! The empty space for our button starts at coordinate
 (0, 163) and has the dimensions (106, 53). 



We are done. This project can be downloaded from here.

২টি মন্তব্য:

  1. Is it possible to add some flowchart of your work? it is not a good way for the reader to read all of your code to understand your work. I hope you will consider this. :)
    Good effort. Keep going.. :)

    উত্তরমুছুন