Search code examples
iosios4

Scroll UITextField above Keyboard in a UITableViewCell on a regular UIViewController


I have tried most of the examples here on StackOverflow. I also used Apple's. The problem I seem to have with them is that they don't account for the UITextField being in a UITableView. I've done this many times, but not in this way. I have a custom UITableViewCell with a UITextField in it.

On my UITableView (which is NOT a UITableViewController), I need to be able to avoid hiding the UITextField under the UITableView.

I have this as of now:

-(void)viewDidLoad
{
....
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillShow:)
                                                 name:UIKeyboardWillShowNotification
                                               object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillHide:)
                                                 name:UIKeyboardWillHideNotification
                                               object:nil];

....
}

- (void)scrollToRectOfTextField {
    UITableViewCell *cell = (UITableViewCell*)[self.activeTextField superview];
    CGRect r = CGRectMake(self.activeTextField.frame.origin.x,
                          cell.frame.origin.y+self.activeTextField.frame.origin.y,
                          self.activeTextField.frame.size.width,
                          self.activeTextField.frame.size.height);
    [self.tableView scrollRectToVisible:r animated:YES];
}

- (void)keyboardDidShow:(NSNotification *)notification
{
    if (UI_USER_INTERFACE_IDIOM()== UIUserInterfaceIdiomPhone) {
        NSDictionary *userInfo = [notification userInfo];
        CGSize size = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
        NSLog(@"TableView: %@", NSStringFromCGRect(self.tableView.frame));
        CGRect newTableViewFrame = CGRectMake(self.tableView.frame.origin.x,
                                              self.tableView.frame.origin.y,
                                              self.tableView.frame.size.width, self.tableView.frame.size.height - size.height);
        self.tableView.frame = newTableViewFrame;
        NSLog(@"New TableView: %@", NSStringFromCGRect(self.tableView.frame));


        self.tableView.contentSize = CGSizeMake(self.tableView.contentSize.width, self.tableView.contentSize.height-size.height);
    }
}


- (void)keyboardWillHide:(NSNotification *)notification
{
    NSDictionary *userInfo = [notification userInfo];
    CGSize size = [[userInfo objectForKey: UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
    self.tableView.frame = CGRectMake(self.tableView.frame.origin.x,
                                      self.tableView.frame.origin.y,
                                      self.tableView.frame.size.width,
                                      self.tableView.frame.size.height + size.height);

    NSLog(@"%@", NSStringFromCGRect(self.tableView.frame));
}


-(void)textFieldDidBeginEditing
{
     [self scrollToRectOfTextField];
}

This seems to push a bunch of white space up past my keyboard. Please also note that I have an inputAccessoryView on my UITextField as well.

Oh, and I cannot use any third party classes. I love TPKeyboardAvoidingScrollView, but I cannot use anything third party.


Solution

  • I spent all day trying to figure this out. I posted it here, then found a blog link and an incredibly simple solution. It looks like this:

    -(BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
        CGPoint pointInTable = [textField.superview convertPoint:textField.frame.origin toView:self.tableView];
        CGPoint contentOffset = self.tableView.contentOffset;
    
        contentOffset.y = (pointInTable.y - textField.inputAccessoryView.frame.size.height);
    
        NSLog(@"contentOffset is: %@", NSStringFromCGPoint(contentOffset));
    
        [self.tableView setContentOffset:contentOffset animated:YES];
    
        return YES;
    }
    
    
    -(BOOL)textFieldShouldEndEditing:(UITextField *)textField
    {
        [textField resignFirstResponder];
    
        if ([textField.superview.superview isKindOfClass:[UITableViewCell class]])
        {
            UITableViewCell *cell = (UITableViewCell*)textField.superview.superview;
            NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
    
            [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:TRUE];
        }
    
        return YES;
    }
    

    Check this for iOS 8