Skip to content

Instantly share code, notes, and snippets.

@Galeas
Last active March 20, 2018 11:32
Show Gist options
  • Save Galeas/79ee4d87abdb7876c16fdc77d58e4a7e to your computer and use it in GitHub Desktop.
Save Galeas/79ee4d87abdb7876c16fdc77d58e4a7e to your computer and use it in GitHub Desktop.
iOS AutoLayout Keyboard Adjuster
@import UIKit;
typedef void (^KeyboardAdjustingBlock)();
@interface KeyboardAdjuster : NSObject
@property (nonatomic, assign) BOOL activated;
@property (nonatomic, nullable, weak) IBOutlet UIView *targetView;
@property (nonatomic, nullable, weak) IBOutlet NSLayoutConstraint *targetConstraint;
+ (nonnull instancetype)createWithView:(nonnull UIView *)view constraint:(nonnull NSLayoutConstraint *)constraint;
- (nonnull instancetype)initWithShow:(nullable KeyboardAdjustingBlock)show hide:(nullable KeyboardAdjustingBlock)hide NS_DESIGNATED_INITIALIZER;
@end
#import "KeyboardAdjuster.h"
#define SAFE_RUN(block, ...) block ? block(__VA_ARGS__) : nil
@interface KeyboardAdjuster ()
@property (nonatomic, assign) CGFloat advance;
@property (nonatomic, assign) BOOL keyboardOnScreen;
@end
@implementation KeyboardAdjuster
#pragma mark - Initialization
+ (instancetype)createWithView:(UIView *)view constraint:(NSLayoutConstraint *)constraint
{
KeyboardAdjuster *obj = [KeyboardAdjuster new];
obj.targetView = view;
obj.targetConstraint = constraint;
return obj;
}
- (instancetype)init
{
return [self initWithShow:nil hide:nil];
}
- (instancetype)initWithShow:(KeyboardAdjustingBlock)show hide:(KeyboardAdjustingBlock)hide
{
if( self = [super init] ) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardStateChange:) name:UIKeyboardWillShowNotification object:show];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardStateChange:) name:UIKeyboardWillHideNotification object:hide];
}
return self;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}
#pragma mark - Notification handler
- (void)keyboardStateChange:(NSNotification *)evt
{
if( !self.activated ) {
return;
}
KeyboardAdjustingBlock block = evt.object;
SAFE_RUN(block);
NSDictionary *userInfo = evt.userInfo;
CGRect keyboardFrame = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGRect viewFrame = [self.targetView convertRect:self.targetView.bounds toView:self.targetView.window];
if( [evt.name isEqualToString:UIKeyboardWillShowNotification] && !self.keyboardOnScreen ) {
self.keyboardOnScreen = YES;
CGRect intersection = CGRectIntersection(viewFrame, keyboardFrame);
self.advance = intersection.size.height;
self.targetConstraint.constant += self.advance;
} else if( [evt.name isEqualToString:UIKeyboardWillHideNotification] ) {
self.keyboardOnScreen = NO;
self.targetConstraint.constant -= self.advance;
self.advance = 0.0;
}
NSTimeInterval duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
UIViewAnimationCurve curve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue];
UIViewAnimationOptions options = UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionLayoutSubviews | curve;
[UIView animateWithDuration:duration delay:0 options:options animations:^{
[self.targetView.superview setNeedsLayout];
[self.targetView.superview layoutIfNeeded];
} completion:nil];
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment