iOS 鍵盤遮擋問題 (自動(dòng)上移UI)

分享一個(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];

? ? }];

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容