You don't get that behavior for free, you need to scroll the content up/down yourself. A UITableView
inherits from a UIScrollView
, so scrolling is not the actual problem. To scroll, you can set its contentSize
and contentOffset
(even animated if you like).
The first thing is, you want to listen to these notifications:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
These will tell you whether the keyboard will show or hide. In each of these methods, change the contentOffset
and contentSize
of your UITableView
accordingly:
- (void)keyboardWillShow:(NSNotification *)notification
{
// keyboard info
NSDictionary *userInfo = [notification userInfo];
CGRect keyboardRect = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
UIViewAnimationOptions animationCurve = [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue];
NSTimeInterval animationDuration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
// offsets
UIView *cell = myTextField.superView; // assuming your text field is a direct child of the UITableViewCell
CGFloat textFieldBottomY = self.view.frame.origin.y + myTableView.frame.origin.y - myTableView.contentOffset.y + cell.frame.origin.y + myTextField.origin.y + myTextField.frame.size.height;
CGFloat keyboardTopY = keyboardRect.origin.y;
// new content size: add size to be able to scroll
originalContentOffset = myTableView.contentOffset; // store the original content offset to set back when keyboard hides
originalContentSize = myTableView.contentSize; // store the original content size to set back when keyboard hides
CGSize newContentSize = myTableView.contentSize;
newContentSize.height += keyboardRect.size.height;
myTableView.contentSize = newContentSize;
// scroll to just beneath your text field
[UIView animateWithDuration:animationDuration delay:0 options:animationCurve animations:^{
myTableView.contentOffset = CGPointMake(0, textFieldBottomY - keyboardTopY);
} completion:NULL];
}
To reset everything:
- (void)keyboardWillHide:(NSNotification *)notification
{
// keyboard info
NSDictionary *userInfo = [notification userInfo];
UIViewAnimationOptions animationCurve = [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue];
NSTimeInterval animationDuration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
// move content
[UIView animateWithDuration:animationDuration delay:0 options:animationCurve animations:^{
myTableView.contentOffset = originalContentOffset;
} completion:^(BOOL finished) {
if (finished) {
// reset content size
myTableView.contentSize = originalContentSize;
}
}];
}
To detect which text field is selected/active:
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
myTextField = textField;
}
I didn't test out the code on a UITableView
, but I used it very recently on a UIScrollView
. Again - since a UITableView
inherits from a UIScrollVIew
, this should not be a problem. If the table view does not scroll correctly to just beneath the text field, the value of textFieldBottomY
is incorrect.