部分页面需要显示一个工具栏,当键盘出现时,这个工具栏显示在键盘上方。由于使用了IQKeyboardManager,导致有的页面iOS12.5.6系统的手机出现首次键盘高度比实际低44像素,而iOS14.7.1系统的手机出现首次键盘高度比实际低44像素并且有时出现最后收到键盘隐藏通知但是实际显示了键盘。
收到通知直接设置工具栏的frame,也过于突兀,最好采用做动画的方式显示工具栏,动画完成时再修正键盘高度,这样能部分解决上面的那两个问题。
那键盘的动画时间是0.25秒,可以在键盘通知里获取到这个参数。那键盘的实际高度从哪里获取呢?经过观察View UI Herarchy发现有键盘的页面都有UIInputSetContainerView,键盘的总高度就是UIInputSetHostView的总高度。只是iOS13及跟高的系统,键盘是在第二个窗口的UIInputWindowController中,而比iOS13低的版本在第是哪个窗口的UITextEffectsWindow中。具体的实现如下:
增加键盘显示通知:
//监听键盘的变化[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyBoardChange:) name:UIKeyboardWillShowNotification object:nil];
键盘通知处理:
- (void)keyBoardChange:(NSNotification *)notification {//获取键盘的高度NSDictionary *userInfo = [notification userInfo];NSValue *aValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];CGRect keyboardRect = [aValue CGRectValue];CGFloat height = keyboardRect.size.height;//获取动画时间ICGFloat animationDuration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];NSLog(@"animationDuration:%f,height:%f",animationDuration,height);if(self.keyBoardChangeBlock){self.keyBoardChangeBlock(height, animationDuration);}
}
键盘显示动画与修正:
- (LCCommentToolView *)comTool {if (_comTool == nil) {_comTool = [[LCCommentToolView alloc] initWithFrame:CGRectMake(0, 0, KScreenW, BaseSize(100))] ;[_comTool setCorner:UIRectCornerTopLeft|UIRectCornerTopRight cornerSize:BaseSize(15) forRect:CGRectMake(0, 0, KScreenW, BaseSize(100))];DYWeakSelf;[_comTool setKeyBoardChangeBlock:^(CGFloat height, CGFloat animationDuration) {if (DYGlobleData.isLogin) {if(animationDuration <= 0){//防范式编程,理论不会出现weakSelf.bgV.hidden = NO;}else{weakSelf.bgV.hidden = (height<=0);[UIView animateWithDuration:animationDuration animations:^{if((height<=0)){[weakSelf.comTool mas_updateConstraints:^(MASConstraintMaker *make) {make.height.mas_equalTo(BaseSize(100));make.width.mas_equalTo(KScreenW);make.bottom.mas_equalTo(BaseSize(100) -(49+(BR_BOTTOM_MARGIN?24:0)));}];[weakSelf.comTool updateCommentTVWithShift:(BaseSize(100) -(49+(BR_BOTTOM_MARGIN?24:0))+(BR_BOTTOM_MARGIN?24:0))];}else{[weakSelf.comTool mas_updateConstraints:^(MASConstraintMaker *make) {make.height.mas_equalTo(BaseSize(100));make.width.mas_equalTo(KScreenW);make.bottom.mas_equalTo(-height);}];[weakSelf.comTool updateCommentTVWithShift:0];}[weakSelf layoutIfNeeded];} completion:^(BOOL finished) {CGFloat keyboardHeight = [weakSelf displayKeyboardDockView];if(keyboardHeight > 0){[weakSelf.comTool mas_updateConstraints:^(MASConstraintMaker *make) {make.height.mas_equalTo(BaseSize(100));make.width.mas_equalTo(KScreenW);make.bottom.mas_equalTo(-keyboardHeight);}];[weakSelf.comTool updateCommentTVWithShift:0];}else{[weakSelf.comTool mas_updateConstraints:^(MASConstraintMaker *make) {make.height.mas_equalTo(BaseSize(100));make.width.mas_equalTo(KScreenW);make.bottom.mas_equalTo(BaseSize(100) -(49+(BR_BOTTOM_MARGIN?24:0)));}];[weakSelf.comTool updateCommentTVWithShift:(BaseSize(100) -(49+(BR_BOTTOM_MARGIN?24:0))+(BR_BOTTOM_MARGIN?24:0))];}[weakSelf layoutIfNeeded];}];}} else {weakSelf.bgV.hidden = YES;[weakSelf.comTool mas_updateConstraints:^(MASConstraintMaker *make) {make.height.mas_equalTo(BaseSize(100));make.width.mas_equalTo(KScreenW);make.bottom.mas_equalTo(BaseSize(100) -(49+(BR_BOTTOM_MARGIN?24:0)));}];[weakSelf.comTool updateCommentTVWithShift:(BaseSize(100) -(49+(BR_BOTTOM_MARGIN?24:0))+(BR_BOTTOM_MARGIN?24:0))];};}];}return _comTool;
}
识别键盘是否在显示和获取键盘高度,键盘高为0.0是键盘隐藏:
- (CGFloat)displayKeyboardDockView{UIWindow *keyboardWindow = [[[UIApplication sharedApplication] windows] objectAtSafeIndex:1];UIView *keyboardContainerView;UIView *keyboardHostView;if (@available(iOS 13.0, *)){for(int i = 0; i < [keyboardWindow.subviews count]; i++) {keyboardContainerView = [keyboardWindow.subviews objectAtIndex:i];UIViewController *nextResponder = (UIViewController*)[keyboardContainerView nextResponder];if(([nextResponder isKindOfClass:NSClassFromString(@"UIWindow")])){NSLog(@"[nextResponder.subviews count]:%d, nextResponder.subviews:%@", [keyboardWindow.subviews count], keyboardWindow.subviews);}//寻找keyboardWindow层的UIInputWindowControllerelse if ([nextResponder isKindOfClass:NSClassFromString(@"UIInputWindowController")]) {for(int y = 0; y < [nextResponder.view.subviews count]; y++) {//寻找UIInputWindowController层的UIInputSetContainerViewif([[keyboardContainerView description] hasPrefix:@"<UIInputSetContainerView"] == YES){for(int t = 0; t < [keyboardContainerView.subviews count]; t++) {keyboardHostView = [keyboardContainerView.subviews objectAtIndex:t];//寻找UIInputSetContainerView层的UIInputSetHostViewif([[keyboardHostView description] hasPrefix:@"<UIInputSetHostView"] == YES){NSLog(@"keyboardHostView description:%@,keyboardHostView.isHidden:%d,[keyboardHostView.subviews count],[keyboardHostView.subviews count],keyboardHostView.frame.size.height:%f,keyboardHostView.frame.origin.y:%f, (keyboardHostView.frame.origin.y == [[UIScreen mainScreen] bounds].size.height):%d", [keyboardHostView description],keyboardHostView.isHidden,[keyboardHostView.subviews count], keyboardHostView.frame.size.height,keyboardHostView.frame.origin.y, (keyboardHostView.frame.origin.y == [[UIScreen mainScreen] bounds].size.height));if (lroundl(keyboardHostView.frame.origin.y) != lroundl(([[UIScreen mainScreen] bounds].size.height))){return keyboardHostView.frame.size.height;}else{return 0.0;}}}}}}}return 0.0;}else{keyboardWindow = [[[UIApplication sharedApplication] windows] objectAtSafeIndex:2];if(keyboardWindow && [keyboardWindow isKindOfClass:NSClassFromString(@"UITextEffectsWindow")] && !isCommonUnitEmptyArray(keyboardWindow.subviews)){keyboardContainerView = [keyboardWindow.subviews objectAtSafeIndex:0];if(keyboardContainerView && ([[keyboardContainerView description] hasPrefix:@"<UIInputSetContainerView"] == YES)){for(int t = 0; t < [keyboardContainerView.subviews count]; t++) {keyboardHostView = [keyboardContainerView.subviews objectAtIndex:t];//寻找UIInputSetContainerView层的UIInputSetHostViewif([[keyboardHostView description] hasPrefix:@"<UIInputSetHostView"] == YES){NSLog(@"keyboardHostView description:%@,keyboardHostView.isHidden:%d,[keyboardHostView.subviews count],[keyboardHostView.subviews count],keyboardHostView.frame.size.height:%f,keyboardHostView.frame.origin.y:%f, (keyboardHostView.frame.origin.y == [[UIScreen mainScreen] bounds].size.height):%d", [keyboardHostView description],keyboardHostView.isHidden,[keyboardHostView.subviews count], keyboardHostView.frame.size.height,keyboardHostView.frame.origin.y, (keyboardHostView.frame.origin.y == [[UIScreen mainScreen] bounds].size.height));if (lroundl(keyboardHostView.frame.origin.y) != lroundl(([[UIScreen mainScreen] bounds].size.height))){return keyboardHostView.frame.size.height;}else{return 0.0;}}}}}return 0.0;}}