I have a UIViewController that contains a UITableView with custom cells, inside the cell are UILabels, a couple of uneditable UITextView and one editable UITextView. Now, when I tap on one of the UITextView that is near the bottom or the bottom part of the table, the UITextView is covered by the keyboard. I've tried http://cocoawithlove.com/2008/10/sliding-uitextfields-around-to-avoid.html which works great for textfield/textview but not working on the table with custom cell. Any help or suggestions how to go about this?
5 Answers
When your table view contains data entry fields like a UITextField or a UITextView and the table view is long enough to cover the screen, you will have a problem accessing data entry fields that are hidden by the keyboard. 
To overcome this problem two solutions are:
- The easiest and recommended way is to use a - UITableViewControllerinstead of- UIViewController, which automatic make sure keypad won't hide the editable field (If possible use this approach to avoid U.I. adjustment inconvenience)
- If you use a - UIViewControllerand a- UITableViewas its subview. You can scroll your UI’s frame by observing the- UIKeyboardWillShowNotificationand- UIKeyboardWillHideNotification- - (void)registerForKeyboardNotifications { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; //Posted immediately prior to the display of the keyboard [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; //Posted immediately prior to the dismissal of the keyboard. } - (void)keyboardWillShow:(NSNotification *)aNotification { CGRect keyboardBounds = [[[aNotification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue]; [UIView beginAnimations:nil context:nil]; [UIView setAnimationBeginsFromCurrentState:YES]; self.tableView.contentInset = UIEdgeInsetsMake(0, 0, keyboardBounds.size.height, 0); //when keyboard is up, that time just bring your text filed above the keyboard self.tableView.scrollIndicatorInsets = UIEdgeInsetsMake(0, 0, keyboardBounds.size.height, 0); [self.tableView scrollToRowAtIndexPath:[self findIndexPathToScroll] atScrollPosition:UITableViewScrollPositionTop animated:YES]; //findIndexPathToScroll implementation not shown [UIView commitAnimations]; } - (void)keyboardWillHide:(NSNotification *)aNotification { [UIView beginAnimations:nil context:nil]; [UIView setAnimationBeginsFromCurrentState:YES]; self.tableView.contentInset = UIEdgeInsetsZero; //Once keyboard is hidden then bring back your table into your original position. self.tableView.scrollIndicatorInsets = UIEdgeInsetsZero; [UIView commitAnimations]; }- registerForKeyboardNotifications- call this method when you load the UITableView, ie: viewDidLoad
- findIndexPathToScroll- (Implementation not shown) Its your business logic to prepare IndexPath where table view should scroll
- removeObserver'UIKeyboardWillShowNotification' and 'UIKeyboardWillHideNotification' both in- deallocand- viewDidUnload
 
 
    
    - 1,434
- 5
- 22
- 41
 
    
    - 2,011
- 1
- 14
- 11
I fixed the issue. Please see my solution below:
1. First declare a global varibale called "activeFileld"
@property(nonatomic,strong)id activeFiled;
2. Create a method called "registerForKeyboardNotifications"
- (void)registerForKeyboardNotifications 
{
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(keyboardWillShow:)
                                                     name:UIKeyboardWillShowNotification object:nil]; //Posted immediately prior to the display of the keyboard
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(keyboardWillHide:)
                                                     name:UIKeyboardWillHideNotification object:nil]; //Posted immediately prior to the dismissal of the keyboard.
}
3. Called the above method in viewWillAppear:
-(void)viewWillAppear:(BOOL)animated{
  [super viewWillAppear:animated];
  //Register kryboard Notification
   [self registerForKeyboardNotifications];
}
4. Call the Delegate method for UitextFieldd Or UitextView
- (void)textFieldDidBeginEditing:(UITextField *)sender {
        self.activeField = sender;
}
- (void)textFieldDidEndEditing:(UITextField *)sender{
        self.activeField = nil;
}
- (void)textViewDidBeginEditing:(UITextView *)textView
{
    // save the text view that is being edited
    _notes = textView.text;
}
- (void)textViewDidEndEditing:(UITextView *)textView
{
    // release the selected text view as we don't need it anymore
    _activeField = nil;
}
5.
- (void)keyboardWillShow:(NSNotification *)notification
{
    if([_activeField isKindOfClass:[UITextField class]]) {
        NSDictionary* info = [notification userInfo];
        NSLog(@"Dictionary %@",info);
        CGRect kbRect = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
        kbRect = [self.view convertRect:kbRect fromView:nil];
        UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbRect.size.height, 0.0);
        self.tableView.contentInset = contentInsets;
        self.tableView.scrollIndicatorInsets = contentInsets;
        CGRect aRect = self.view.frame;
        aRect.size.height -= kbRect.size.height;
        UITextField *textField = (UITextField*)_activeField;
        if (!CGRectContainsPoint(aRect, textField.frame.origin) ) {
            [self.tableView scrollRectToVisible:textField.frame animated:YES];
        }
    }else if([_activeField isKindOfClass:[UITextView class]]) {
        NSDictionary* info = [notification userInfo];
        NSLog(@"Dictionary %@",info);
        CGRect kbRect = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
        kbRect = [self.view convertRect:kbRect fromView:nil];
        UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbRect.size.height, 0.0);
        self.tableView.contentInset = contentInsets;
        self.tableView.scrollIndicatorInsets = contentInsets;
        CGRect aRect = self.view.frame;
        aRect.size.height += kbRect.size.height;
        UITextView *activeTextView = (UITextView*)_activeField;
        if (!CGRectContainsPoint(aRect, textField.superview.superview.frame.origin) ) {
            [self.tableView scrollRectToVisible:activeTextView.superview.superview.frame animated:YES];
       }
   }
}
// Called when the UIKeyboardWillHideNotification is received
- (void)keyboardWillHide:(NSNotification *)aNotification
{
    UIEdgeInsets contentInsets = UIEdgeInsetsZero;
    self.tableView.contentInset = contentInsets;
    self.tableView.scrollIndicatorInsets = contentInsets;
}
 
    
    - 131
- 4
- 8
Two solutions:
Preferred: use a UITableViewController instead of a UIViewController as that one will automatically make sure that your keypad won't hide the editable field.
Hacky: How to make a UITextField move up when keyboard is present?
- 
                    well, I cannot use UITableViewController since I got a lot of stuff inside this view and not just UITableView. I'll try the other one. i'll get back here later. – Diffy Nov 21 '11 at 09:38
A simple solution. Implement the heightForFooter method, and let it return a value of (say) 100, and when you select the a cell in UITableView, they will simply slide up by that height, and the keyboard will not cover the view. 
 
    
    - 12,145
- 12
- 79
- 132
I've always used a two fold solution for this.
- Resize table so it now fits in the smaller area.
- Scroll to the cell we want visible. (we needed to re-size the table for this or you'd still wind up being unable to get to the last couple of cells in the table.)
To do this, I register keyboard show/hide events and act accordingly when they get called.
- (void)keyboardWillShow:(NSNotification *)note {
    [self updateForKeyboardShowHide:note appearing:YES];
}
- (void)keyboardWillHide:(NSNotification *)note {
    [self updateForKeyboardShowHide:note appearing:NO];
}
- (void)updateForKeyboardShowHide:(NSNotification *)note appearing:(BOOL)isAppearing {
    // ignore notifications if our view isn't attached to the window
    if (self.view.window == nil)
        return;
    CGFloat directionalModifier = isAppearing?-1:1;
    CGRect keyboardBounds = [[note.userInfo valueForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
    CGFloat animationDuration = [[note.userInfo valueForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue];
    // figure out table re-size based on keyboard
    CGFloat keyboardHeight;
    UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
    if (UIInterfaceOrientationIsPortrait(orientation))
        keyboardHeight = keyboardBounds.size.height;
    else 
        keyboardHeight = keyboardBounds.size.width;
    [UIView animateWithDuration:animationDuration animations:^{
        // resize table
        CGRect newFrame = table.frame;
        newFrame.size.height += [self calculateKeyboardOffsetWithHeight:keyboardHeight] * directionalModifier;
        table.frame = newFrame;        
    }  completion:^(BOOL finished){
        // scroll to selected cell
        if (isAppearing) {
            NSIndexPath *indexPath = [NSIndexPath indexPathForRow:textFieldInEdit.tag inSection:0];
            [table scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
        }
    }];
}
- (CGFloat)calulateKeyboardOffsetWithHeight:(CGFloat)keyboardHeight {
    // This depends on the size and position of your table.
    //   If your table happen to go all the way to the bottom of
    // the screen, you'll needs to adjust it's size by the whole keyboard height.
    // You might as well ditch this method and inline the value.
    return keyboardHeight;
    //   My table did not go to the bottom of the screen and the position was
    // change dynamically so and there was long boring calculation I needed to
    // do to figure out how much my table needed to shrink/grow.
}
 
    
    - 23,075
- 12
- 60
- 84
- 
                    You forgot to include your method "calculateKeyboardOffsetWithHeight:", without which this won't work – Adam Aug 19 '12 at 08:51
- 
                    @Adam I didn't think the method was needed, but in I can see how it could cause confusion and so I added it in and explained it. I hope that helps. – DBD Aug 20 '12 at 13:11
 
     
     
    