Skip to content

Instantly share code, notes, and snippets.

@brennanMKE
Last active August 29, 2015 14:03
Show Gist options
  • Save brennanMKE/bea871ceaa430e50555c to your computer and use it in GitHub Desktop.
Save brennanMKE/bea871ceaa430e50555c to your computer and use it in GitHub Desktop.
iOS Keyboard Handling with a Base View Controller
#import <UIKit/UIKit.h>
@interface BaseViewController : UIViewController
#pragma mark - Keyboard Methods
#pragma mark -
- (void)hideKeyboardWithoutAnimation;
- (void)keyboardWillShowWithHeight:(CGFloat)height duration:(CGFloat)duration animationOptions:(UIViewAnimationOptions)animationOptions;
- (void)keyboardWillHideWithHeight:(CGFloat)height duration:(CGFloat)duration animationOptions:(UIViewAnimationOptions)animationOptions;
- (void)keyboardDidShow;
- (void)keyboardDidHide;
@end
#import "BaseViewController.h"
@interface BaseViewController ()
@end
@implementation BaseViewController {
BOOL isKeyboardVisible;
}
#pragma mark - View Lifecycle
#pragma mark -
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShowNotification:)
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHideNotification:)
name:UIKeyboardWillHideNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardDidShowNotification:)
name:UIKeyboardDidShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardDidHideNotification:)
name:UIKeyboardDidHideNotification
object:nil];
self.navigationController.navigationBar.backgroundColor = self.view.backgroundColor;
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIKeyboardWillHideNotification
object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIKeyboardDidShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIKeyboardDidHideNotification
object:nil];
}
#pragma mark - Keyboard Methods
#pragma mark -
- (void)hideKeyboardWithoutAnimation {
[self keyboardWillHideWithHeight:0.0 duration:0.0 animationOptions:kNilOptions];
}
- (void)keyboardWillShowWithHeight:(CGFloat)height duration:(CGFloat)duration animationOptions:(UIViewAnimationOptions)animationOptions {
// override if necessary
DebugLog(@"%@", NSStringFromSelector(_cmd));
UIScrollView *scrollView = [self mainScrollView];
if (scrollView) {
CGFloat bottom = self.bottomLayoutGuide.length;
UIEdgeInsets contentInset = scrollView.contentInset;
contentInset.bottom = bottom + height;
UIEdgeInsets scrollIndicatorInsets = scrollView.scrollIndicatorInsets;
scrollIndicatorInsets.bottom = contentInset.bottom;
[UIView animateWithDuration:duration delay:0.0 options:animationOptions animations:^{
scrollView.contentInset = contentInset;
scrollView.scrollIndicatorInsets = scrollIndicatorInsets;
} completion:^(BOOL finished) {
}];
}
}
- (void)keyboardWillHideWithHeight:(CGFloat)height duration:(CGFloat)duration animationOptions:(UIViewAnimationOptions)animationOptions {
// override if necessary
DebugLog(@"%@", NSStringFromSelector(_cmd));
UIScrollView *scrollView = [self mainScrollView];
if (scrollView) {
CGFloat bottom = self.bottomLayoutGuide.length;
UIEdgeInsets contentInset = scrollView.contentInset;
contentInset.bottom = bottom;
UIEdgeInsets scrollIndicatorInsets = scrollView.scrollIndicatorInsets;
scrollIndicatorInsets.bottom = contentInset.bottom;
[UIView animateWithDuration:duration delay:0.0 options:animationOptions animations:^{
scrollView.contentInset = contentInset;
scrollView.scrollIndicatorInsets = scrollIndicatorInsets;
} completion:^(BOOL finished) {
}];
}
}
- (void)keyboardDidShow {
// override if necessary
}
- (void)keyboardDidHide {
// override if necessary
}
#pragma mark - Notifications
#pragma mark -
- (void)keyboardWillShowNotification:(NSNotification *)notification {
CGFloat height = [self getKeyboardHeight:notification forBeginning:TRUE];
NSTimeInterval duration = [self getDuration:notification];
UIViewAnimationCurve animationCurve = [self getAnimationCurve:notification];
UIViewAnimationOptions animationOptions = [self animationOptionsWithCurve:animationCurve];
[self keyboardWillShowWithHeight:height duration:duration animationOptions:animationOptions];
}
- (void)keyboardWillHideNotification:(NSNotification *)notification {
CGFloat height = [self getKeyboardHeight:notification forBeginning:FALSE];
NSTimeInterval duration = [self getDuration:notification];
UIViewAnimationCurve animationCurve = [self getAnimationCurve:notification];
UIViewAnimationOptions animationOptions = [self animationOptionsWithCurve:animationCurve];
[self keyboardWillHideWithHeight:height duration:duration animationOptions:animationOptions];
}
- (void)keyboardDidShowNotification:(NSNotification *)notification {
isKeyboardVisible = TRUE;
[self keyboardDidShow];
}
- (void)keyboardDidHideNotification:(NSNotification *)notification {
isKeyboardVisible = FALSE;
[self keyboardDidHide];
}
#pragma mark - Private
#pragma mark -
- (NSTimeInterval)getDuration:(NSNotification *)notification {
NSTimeInterval duration;
NSValue *durationValue = [notification.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey];
[durationValue getValue:&duration];
return duration;
}
- (CGFloat)getKeyboardHeight:(NSNotification *)notification forBeginning:(BOOL)forBeginning {
NSDictionary *info = [notification userInfo];
CGFloat keyboardHeight;
NSValue *boundsValue = nil;
if (forBeginning) {
boundsValue = [info valueForKey:UIKeyboardFrameBeginUserInfoKey];
}
else {
boundsValue = [info valueForKey:UIKeyboardFrameEndUserInfoKey];
}
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
if (UIDeviceOrientationIsLandscape(orientation)) {
keyboardHeight = [boundsValue CGRectValue].size.width;
}
else {
keyboardHeight = [boundsValue CGRectValue].size.height;
}
return keyboardHeight;
}
- (UIViewAnimationCurve)getAnimationCurve:(NSNotification *)notification {
UIViewAnimationCurve animationCurve;
NSValue *animationCurveValue = [notification.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey];
[animationCurveValue getValue:&animationCurve];
return animationCurve;
}
- (UIViewAnimationOptions)animationOptionsWithCurve:(UIViewAnimationCurve)curve {
switch (curve) {
case UIViewAnimationCurveEaseInOut:
return UIViewAnimationOptionCurveEaseInOut;
case UIViewAnimationCurveEaseIn:
return UIViewAnimationOptionCurveEaseIn;
case UIViewAnimationCurveEaseOut:
return UIViewAnimationOptionCurveEaseOut;
case UIViewAnimationCurveLinear:
return UIViewAnimationOptionCurveLinear;
default:
// return whatever it provided because iOS 7 uses an undocumented animation value of 7 (not cool, Apple)
// http://stackoverflow.com/questions/18837166/how-to-mimic-keyboard-animation-on-ios-7-to-add-done-button-to-numeric-keyboar
return (UIViewAnimationOptions)UIViewAnimationOptionCurveLinear;
}
}
- (UIScrollView *)mainScrollView {
UIScrollView *scrollView = nil;
if (self.view.subviews.count && [self.view.subviews[0] isKindOfClass:[UIScrollView class]]) {
scrollView = (UIScrollView *)self.view.subviews[0];
}
return scrollView;
}
- (UIView *)mainContentView {
UIView *contentView = nil;
UIScrollView *scrollView = [self mainScrollView];
if (scrollView && scrollView.subviews.count) {
contentView = scrollView.subviews[0];
}
return contentView;
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment