The iOS keyboard slides from the bottom of the screen and is positioned on the top of application's content. Apple wrote a guide for handling such events and moving the content from behind the keyboard. The basic workflow for this is to listen to the keyboard notifications, get the size of the keyboard, adjust the bottom content inset of scroll view by the keyboard height and scroll the target text field into view.
// Call this method somewhere in your view controller setup code.
- (void)registerForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
}
// Called when the UIKeyboardDidShowNotification is sent.
- (void)keyboardWasShown:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
// If active text field is hidden by keyboard, scroll it so it's visible
// Your application might not need or want this behavior.
CGRect aRect = self.view.frame;
aRect.size.height -= kbSize.height;
if (!CGRectContainsPoint(aRect, activeField.frame.origin) ) {
CGPoint scrollPoint = CGPointMake(0.0, activeField.frame.origin.y-kbSize.height);
[scrollView setContentOffset:scrollPoint animated:YES];
}
}
// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
}
There is one important point that Apple misses here in the guide though. This doesn't work very well when the app is operating in the landscape mode. I struggled with this for quite some time before actually figuring out that the keyboard height is always returned for the portrait mode irrespective of the orientation that the app is currently operating in. Here's a quick hack to fix this.
if (UIInterfaceOrientationIsLandscape([UIDevice currentDevice].orientation)) {
kbSize = CGSizeMake(kbSize.height, kbSize.width);
}