Moving content located under the iOS keyboard

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);
}
Published 12 Nov 2012

I build mobile and web applications. Full Stack, Rails, React, Typescript, Kotlin, Swift
Pulkit Goyal on Twitter