Skip to content

Instantly share code, notes, and snippets.

@cameroncooke cameroncooke/keyboard.m

Last active Oct 16, 2015
Embed
What would you like to do?
The (not so) ultimate UIScrollView keyboard appearance and disappearance implementation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
- (void)keyboardWillShowNotification:(NSNotification *)notification
{
UIView *view = self.view;
CGRect keyboardFrame = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
keyboardFrame = [view convertRect:keyboardFrame fromView:self.view.window];
// according to Apple docs you can't rely on the origin of the keyboard frame as it will be animating
// so we can just work it out manually
keyboardFrame.origin.x = 0;
keyboardFrame.origin.y = CGRectGetHeight([UIScreen mainScreen].bounds) - CGRectGetHeight(keyboardFrame);
// don't adjust the offsets if the keyboard is now obscuring the view
if (!CGRectIntersectsRect(keyboardFrame, view.frame)) {
return;
}
CGFloat duration = [[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
NSInteger animationCurve = [[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue];
CGRect intersection = CGRectIntersection(keyboardFrame, view.frame);
UIEdgeInsets insets = self.scrollView.contentInset;
insets.bottom = intersection.size.height;
[UIView animateWithDuration:duration delay:0.0f options:animationCurve animations:^{
self.scrollView.contentInset = insets;
self.scrollView.scrollIndicatorInsets = insets;
} completion:nil];
}
- (void)keyboardWillHideNotification:(NSNotification *)notification
{
CGFloat duration = [[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
NSInteger animationCurve = [[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue];
UIEdgeInsets insets = self.scrollView.contentInset;
insets.bottom = 0;
[UIView animateWithDuration:duration delay:0.0f options:animationCurve animations:^{
self.scrollView.contentInset = insets;
self.scrollView.scrollIndicatorInsets = self.scrollView.contentInset;
} completion:nil];
}
@cameroncooke

This comment has been minimized.

Copy link
Owner Author

cameroncooke commented Sep 17, 2015

This code will adjust the scrollview offsets to account for keyboard overlap. It calculates the intersection and adjusts accordingly. This means this will work if the UIViewController is presented fullscreen or in a Popover on iPad and will only adjust the scroll insets if necessary.

Just add the two methods to your view controller, make sure you have a property for your UIScrollView called scrollView and add the following code to the top of your view controller:

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShowNotification:) name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHideNotification:) name:UIKeyboardWillHideNotification object:nil];
}

Works on iOS 8 and later

@cameroncooke

This comment has been minimized.

Copy link
Owner Author

cameroncooke commented Oct 16, 2015

Don't use this, it doesn't work, use http://stackoverflow.com/a/19660499/248848 instead

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.