分享一個(gè)寫好的類。解決鍵盤出現(xiàn) 遮擋住界面的問題?,F(xiàn)在讓UI自動(dòng)上移一些,能更好顯示
1. ?.H文件
#import <Foundation/Foundation.h>
#import?<UIKit/UIKit.h>
typedef enum {
? ? KeyboardActionDefault,
? ? KeyboardActionShow,
? ? KeyboardActionHide
}KeyboardAction
@protocol KeyboardUtilProtocol- (void)adaptiveViewHandleWithAdaptiveView:(UIView *)adaptiveView, ...NS_REQUIRES_NIL_TERMINATION;
- (void)adaptiveViewHandleWithController:(UIViewController *)viewController adaptiveView:(UIView *)adaptiveView, ...NS_REQUIRES_NIL_TERMINATION;
@end
#pragma mark - KeyboardInfo(model)
@interface KeyboardInfo : NSObject
@property (assign, nonatomic) CGFloat animationDuration;
@property (assign, nonatomic) CGRect frameBegin;
@property (assign, nonatomic) CGRect frameEnd;
@property (assign, nonatomic) CGFloat heightIncrement;
@property (assign, nonatomic) KeyboardAction action;
@property (assign, nonatomic) BOOL isSameAction;
- (void)fillKeyboardInfoWithDuration:(CGFloat)duration frameBegin:(CGRect)frameBegin frameEnd:(CGRect)frameEnd heightIncrement:(CGFloat)heightIncrement action:(KeyboardAction)action isSameAction:(BOOL)isSameAction;
@end
#pragma mark - ZYKeyboardUtil
@interface ZYKeyboardUtil : NSObject
typedef void (^animateWhenKeyboardAppearBlock)(int appearPostIndex, CGRect keyboardRect, CGFloat keyboardHeight, CGFloat keyboardHeightIncrement);
typedef void (^animateWhenKeyboardDisappearBlock)(CGFloat keyboardHeight);
typedef void (^printKeyboardInfoBlock)(ZYKeyboardUtil *keyboardUtil, KeyboardInfo *keyboardInfo);
typedef void (^animateWhenKeyboardAppearAutomaticAnimBlock)(ZYKeyboardUtil *keyboardUtil);
- (void)setAnimateWhenKeyboardAppearBlock:(animateWhenKeyboardAppearBlock)animateWhenKeyboardAppearBlock;
- (void)setAnimateWhenKeyboardAppearAutomaticAnimBlock:(animateWhenKeyboardAppearAutomaticAnimBlock)animateWhenKeyboardAppearAutomaticAnimBlock;
- (void)setAnimateWhenKeyboardDisappearBlock:(animateWhenKeyboardDisappearBlock)animateWhenKeyboardDisappearBlock;
- (void)setPrintKeyboardInfoBlock:(printKeyboardInfoBlock)printKeyboardInfoBlock;
@end
#pragma mark - UIView+Utils
@interface UIView (Utils)
- (void)findControllerWithResultController:(UIViewController **)resultController;
@end
2. ?.M文件
#import "ZYKeyboardUtil.h"
#define MARGIN_KEYBOARD_DEFAULT 10
#define TEXTVIEW_NO_ANIM_BEGIN if ([_adaptiveView isKindOfClass:[UITextView class]]) {\
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? [CATransaction begin];\
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];\
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }
#define TEXTVIEW_NO_ANIM_END if ([_adaptiveView isKindOfClass:[UITextView class]]) {\
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? [CATransaction commit];\
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }
@interface ZYKeyboardUtil()
@property (assign, nonatomic) BOOL keyboardObserveEnabled;
@property (assign, nonatomic) int appearPostIndex;
@property (strong, nonatomic) KeyboardInfo *keyboardInfo;
@property (assign, nonatomic) BOOL haveRegisterObserver;
@property (weak, nonatomic) UIViewController *adaptiveController;
@property (weak, nonatomic) UIView *adaptiveView;
@property (strong, nonatomic) NSValue *prepareRectValue;
@property (copy, nonatomic) animateWhenKeyboardAppearBlock animateWhenKeyboardAppearBlock;
@property (copy, nonatomic) animateWhenKeyboardAppearAutomaticAnimBlock animateWhenKeyboardAppearAutomaticAnimBlock;
@property (copy, nonatomic) animateWhenKeyboardDisappearBlock animateWhenKeyboardDisappearBlock;
@property (copy, nonatomic) printKeyboardInfoBlock printKeyboardInfoBlock;
@end
@implementation ZYKeyboardUtil
- (void)dealloc {
? ? [[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark - lazy注冊觀察者
- (void)registerObserver {
? ? if (_haveRegisterObserver == YES) {
? ? ? ? return;
? ? }
? ? self.haveRegisterObserver = YES;
? ? [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
? ? [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
? ? [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidHide:) name:UIKeyboardDidHideNotification object:nil];
? ? [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil];
}
- (void)adaptiveViewHandleWithController:(UIViewController *)viewController adaptiveView:(UIView *)adaptiveView, ...NS_REQUIRES_NIL_TERMINATION {
? ? NSMutableArray *adaptiveViewList = [NSMutableArray array];
? ? [adaptiveViewList addObject:adaptiveView];
? ? va_list var_list;
? ? va_start(var_list, adaptiveView);
? ? UIView *view;
? ? while ((view = va_arg(var_list, UIView *))) {
? ? ? ? [adaptiveViewList addObject:view];
? ? }
? ? va_end(var_list);
? ? self.adaptiveController = viewController;
? ? for (UIView *adaptiveViews in adaptiveViewList) {
? ? ? ? UIView *firstResponder = nil;
? ? ? ? [self recursionTraverseFindFirstResponderIn:adaptiveViews responder:&firstResponder];
? ? ? ? if (nil != firstResponder) {
? ? ? ? ? ? self.adaptiveView = firstResponder;
? ? ? ? ? ? [self fitKeyboardAutomatically:firstResponder controllerView:viewController.view keyboardRect:_keyboardInfo.frameEnd];
? ? ? ? ? ? break;
? ? ? ? }
? ? }
}
- (void)adaptiveViewHandleWithAdaptiveView:(UIView *)adaptiveView, ...NS_REQUIRES_NIL_TERMINATION {
? ? NSMutableArray *adaptiveViewList = [NSMutableArray array];
? ? [adaptiveViewList addObject:adaptiveView];
? ? va_list var_list;
? ? va_start(var_list, adaptiveView);
? ? UIView *view;
? ? while ((view = va_arg(var_list, UIView *))) {
? ? ? ? [adaptiveViewList addObject:view];
? ? }
? ? va_end(var_list);
? ? UIViewController *adaptiveController;
? ? [adaptiveView findControllerWithResultController:&adaptiveController];
? ? if (adaptiveController) {
? ? ? ? self.adaptiveController = adaptiveController;
? ? } else {
? ? ? ? LOG(@"\nERROR: Can not find adaptiveView`s Controller");
? ? ? ? return;
? ? }
? ? for (UIView *adaptiveViews in adaptiveViewList) {
? ? ? ? UIView *firstResponder = nil;
? ? ? ? [self recursionTraverseFindFirstResponderIn:adaptiveViews responder:&firstResponder];
? ? ? ? if (nil != firstResponder) {
? ? ? ? ? ? self.adaptiveView = firstResponder;
? ? ? ? ? ? [self fitKeyboardAutomatically:firstResponder controllerView:adaptiveController.view keyboardRect:_keyboardInfo.frameEnd];
? ? ? ? ? ? break;
? ? ? ? }
? ? }
}
- (void)recursionTraverseFindFirstResponderIn:(UIView *)view responder:(UIView **)responder {
? ? if ([view isFirstResponder]) {
? ? ? ? *responder = view;
? ? } else {
? ? ? ? for (UIView *subView in view.subviews) {
? ? ? ? ? ? if ([subView isFirstResponder]) {
? ? ? ? ? ? ? ? *responder = subView;
? ? ? ? ? ? ? ? return;
? ? ? ? ? ? }
? ? ? ? ? ? [self recursionTraverseFindFirstResponderIn:subView responder:responder];
? ? ? ? }
? ? }
? ? return;
}
- (void)fitKeyboardAutomatically:(UIView *)adaptiveView controllerView:(UIView *)controllerView keyboardRect:(CGRect)keyboardRect {
? ? UIWindow *window = [[UIApplication sharedApplication] keyWindow];
? ? CGRect convertRect = [adaptiveView.superview convertRect:adaptiveView.frame toView:window];
? ? if (CGRectGetMinY(keyboardRect) - MARGIN_KEYBOARD_DEFAULT < CGRectGetMaxY(convertRect)) {
? ? ? ? //記住originFrame
? ? ? ? self.prepareRectValue = [NSValue valueWithCGRect:controllerView.frame];
? ? ? ? CGFloat signedDiff = CGRectGetMinY(keyboardRect) - CGRectGetMaxY(convertRect) - MARGIN_KEYBOARD_DEFAULT;
? ? ? ? //updateOriginY
? ? ? ? CGFloat newOriginY = CGRectGetMinY(controllerView.frame) + signedDiff;
? ? ? ? controllerView.frame = CGRectMake(controllerView.frame.origin.x, newOriginY, controllerView.frame.size.width, controllerView.frame.size.height);
? ? }
}
- (void)restoreKeyboardAutomatically {
? ? [self textViewHandle];
? ? if (_prepareRectValue) {
? ? ? ? self.adaptiveController.view.frame = [_prepareRectValue CGRectValue];
? ? ? ? _prepareRectValue = nil;
? ? }
}
- (void)textViewHandle {
? ? //還原時(shí) textView可能會(huì)出現(xiàn)offset錯(cuò)亂現(xiàn)象
? ? if ([_adaptiveView isKindOfClass:[UITextView class]]) {
? ? ? ? [(UITextView *)_adaptiveView setContentOffset:CGPointMake(0, 0)];
? ? }
}
#pragma mark - 重寫KeyboardInfo set方法,調(diào)用animationBlock
- (void)setKeyboardInfo:(KeyboardInfo *)keyboardInfo {
? ? //home鍵使應(yīng)用進(jìn)入后臺(tái)也會(huì)有某些通知
? ? if([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
? ? ? ? return;
? ? }
? ? _keyboardInfo = keyboardInfo;
? ? if(!keyboardInfo.isSameAction || (keyboardInfo.heightIncrement != 0)) {
? ? ? ? [UIView animateWithDuration:keyboardInfo.animationDuration animations:^{
? ? ? ? ? ? switch (keyboardInfo.action) {
? ? ? ? ? ? ? ? case KeyboardActionShow:
? ? ? ? ? ? ? ? ? ? if(self.animateWhenKeyboardAppearBlock != nil) {
? ? ? ? ? ? ? ? ? ? ? ? self.animateWhenKeyboardAppearBlock(++self.appearPostIndex, keyboardInfo.frameEnd, keyboardInfo.frameEnd.size.height, keyboardInfo.heightIncrement);
? ? ? ? ? ? ? ? ? ? } else if (self.animateWhenKeyboardAppearAutomaticAnimBlock != nil) {
? ? ? ? ? ? ? ? ? ? ? ? self.animateWhenKeyboardAppearAutomaticAnimBlock(self);
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? case KeyboardActionHide:
? ? ? ? ? ? ? ? ? ? if(self.animateWhenKeyboardDisappearBlock != nil) {
? ? ? ? ? ? ? ? ? ? ? ? self.animateWhenKeyboardDisappearBlock(keyboardInfo.frameEnd.size.height);
? ? ? ? ? ? ? ? ? ? ? ? self.appearPostIndex = 0;
? ? ? ? ? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? ? ? ? ? //auto restore
? ? ? ? ? ? ? ? ? ? ? ? [self restoreKeyboardAutomatically];
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? default:
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? ? ? [CATransaction commit];
? ? ? ? }completion:^(BOOL finished) {
? ? ? ? ? ? if(self.printKeyboardInfoBlock != nil && self.keyboardInfo != nil) {
? ? ? ? ? ? ? ? self.printKeyboardInfoBlock(self, keyboardInfo);
? ? ? ? ? ? }
? ? ? ? }];
? ? }
}
- (void)triggerAction {
? ? dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
? ? ? ? self.keyboardInfo = _keyboardInfo;
? ? });
}
#pragma mark - 重寫B(tài)lock set方法,懶加載方式注冊觀察者
/**
* @brief handle the covering event youself when keyboard Appear, Animation automatically.
*
* use animateWhenKeyboardAppearBlock, animateWhenKeyboardAppearAutomaticAnimBlock will be invalid.
*/
- (void)setAnimateWhenKeyboardAppearBlock:(animateWhenKeyboardAppearBlock)animateWhenKeyboardAppearBlock {
? ? _animateWhenKeyboardAppearBlock = animateWhenKeyboardAppearBlock;
? ? [self registerObserver];
}
/**
* @brief handle the covering automatically, you must invoke the method adaptiveViewHandleWithController:adaptiveView: by the param keyboardUtil.
*
* use animateWhenKeyboardAppearAutomaticAnimBlock, animateWhenKeyboardAppearBlock must be nil.
*/
- (void)setAnimateWhenKeyboardAppearAutomaticAnimBlock:(animateWhenKeyboardAppearAutomaticAnimBlock)animateWhenKeyboardAppearAutomaticAnimBlock {
? ? _animateWhenKeyboardAppearAutomaticAnimBlock = animateWhenKeyboardAppearAutomaticAnimBlock;
? ? [self registerObserver];
}
/**
* @brief restore the UI youself when keyboard disappear.
*
* if not configure this Block, automatically itself.
*/
- (void)setAnimateWhenKeyboardDisappearBlock:(animateWhenKeyboardDisappearBlock)animateWhenKeyboardDisappearBlock {
? ? _animateWhenKeyboardDisappearBlock = animateWhenKeyboardDisappearBlock;
? ? [self registerObserver];
}
- (void)setPrintKeyboardInfoBlock:(printKeyboardInfoBlock)printKeyboardInfoBlock {
? ? _printKeyboardInfoBlock = printKeyboardInfoBlock;
? ? [self registerObserver];
}
- (void)setPrepareRectValue:(NSValue *)prepareRectValue {
? ? //為nil時(shí)才設(shè)置
? ? if (!_prepareRectValue) {
? ? ? ? _prepareRectValue = prepareRectValue;
? ? }
}
#pragma mark 響應(yīng)selector
- (void)keyboardWillShow:(NSNotification *)notification {
? ? [self handleKeyboard:notification keyboardAction:KeyboardActionShow];
}
- (void)keyboardWillChangeFrame:(NSNotification *)notification {
? ? if(self.keyboardInfo.action == KeyboardActionShow){
? ? ? ? //[self handleKeyboard:notification keyboardAction:KeyboardActionShow];
? ? }
}
- (void)keyboardWillHide:(NSNotification *)notification {
? ? [self handleKeyboard:notification keyboardAction:KeyboardActionHide];
}
- (void)keyboardDidHide:(NSNotification *)notification {
? ? //置空
? ? self.keyboardInfo = nil;
}
#pragma mark 處理鍵盤事件
- (void)handleKeyboard:(NSNotification *)notification keyboardAction:(KeyboardAction)keyboardAction {
? ? //進(jìn)入后臺(tái)觸發(fā)某些通知,不響應(yīng)
? ? if([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
? ? ? ? return;
? ? }
? ? //解析通知
? ? NSDictionary *infoDict = [notification userInfo];
? ? CGRect frameBegin = [[infoDict objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
? ? CGRect frameEnd = [[infoDict objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
? ? CGFloat previousHeight;
? ? if(self.keyboardInfo.frameEnd.size.height > 0) {
? ? ? ? previousHeight = self.keyboardInfo.frameEnd.size.height;
? ? }else {
? ? ? ? previousHeight = 0;
? ? }
? ? CGFloat heightIncrement = frameEnd.size.height - previousHeight;
? ? BOOL isSameAction;
? ? if(self.keyboardInfo.action == keyboardAction) {
? ? ? ? isSameAction = YES;
? ? }else {
? ? ? ? isSameAction = NO;
? ? }
? ? KeyboardInfo *info = [[KeyboardInfo alloc] init];
? ? [info fillKeyboardInfoWithDuration:DURATION_ANIMATION frameBegin:frameBegin frameEnd:frameEnd heightIncrement:heightIncrement action:keyboardAction isSameAction:isSameAction];
? ? self.keyboardInfo = info;
}
- (void)fillKeyboardInfoWithKeyboardInfo:(KeyboardInfo *)keyboardInfo duration:(CGFloat)duration frameBegin:(CGRect)frameBegin frameEnd:(CGRect)frameEnd heightIncrement:(CGFloat)heightIncrement action:(KeyboardAction)action isSameAction:(BOOL)isSameAction {
? ? keyboardInfo.animationDuration = duration;
? ? keyboardInfo.frameBegin = frameBegin;
? ? keyboardInfo.frameEnd = frameEnd;
? ? keyboardInfo.heightIncrement = heightIncrement;
? ? keyboardInfo.action = action;
? ? keyboardInfo.isSameAction = isSameAction;
}
@end
#pragma mark - KeyboardInfo(model)
@interface KeyboardInfo()
- (void)fillKeyboardInfoWithDuration:(CGFloat)duration frameBegin:(CGRect)frameBegin frameEnd:(CGRect)frameEnd heightIncrement:(CGFloat)heightIncrement action:(KeyboardAction)action isSameAction:(BOOL)isSameAction;
@end
@implementation KeyboardInfo
- (void)fillKeyboardInfoWithDuration:(CGFloat)duration frameBegin:(CGRect)frameBegin frameEnd:(CGRect)frameEnd heightIncrement:(CGFloat)heightIncrement action:(KeyboardAction)action isSameAction:(BOOL)isSameAction {
? ? self.animationDuration = duration;
? ? self.frameBegin = frameBegin;
? ? self.frameEnd = frameEnd;
? ? self.heightIncrement = heightIncrement;
? ? self.action = action;
? ? self.isSameAction = isSameAction;
}
@end
#pragma mark - UIView+Utils
@implementation UIView (Utils)
- (void)findControllerWithResultController:(UIViewController **)resultController {
? ? UIResponder *responder = [self nextResponder];
? ? if (nil == responder) {
? ? ? ? return;
? ? }
? ? if ([responder isKindOfClass:[UIViewController class]]) {
? ? ? ? *resultController = (UIViewController *)responder;
? ? } else if ([responder isKindOfClass:[UIView class]]) {
? ? ? ? [(UIView *)responder findControllerWithResultController:resultController];
? ? }
}
@end
3. 如何使用
#pragma mark - ========== 鍵盤遮擋問題 ==========
#pragma mark 鍵盤彈出
- (void)configKeyBoardRespond
{
? ? self.keyboardUtil = [[ZYKeyboardUtil alloc] init];
? ? __weak JHmessageLoginVC *weakSelf = self;
? ? //增加需要避免遮擋的控件
? ? [_keyboardUtil setAnimateWhenKeyboardAppearAutomaticAnimBlock:^(ZYKeyboardUtil *keyboardUtil) {
? ? ? ? [keyboardUtil adaptiveViewHandleWithController:weakSelf adaptiveView:weakSelf.bgView,nil];
? ? }];
}