自定义键盘系列之二键盘自适应响应者
2017-05-04 本文已影响171人
摸着石头过河_崖边树
首先解释一下标题,什么是键盘自适应响应者,理解为无论响应者在什么位置,键盘弹出都会在响应者的下面,使响应者控件可见。
demo效果
![](https://img.haomeiwen.com/i1886288/13cf451288875c07.gif)
提出问题######
我们在做登录页面的时候假如有多个输入框,并且当输入框在屏幕底部的时候,我们直接弹出键盘就会挡住输入框,如图所示?(需要调整键盘)
![](https://img.haomeiwen.com/i1886288/c1b7bf5f5bef66fd.png)
分析问题######
当我们点击输入框时候,被点击的输入框成为FirstResponder,我们可以采用监听键盘通知方式,滚动输入框所在的父控件,从而实现键盘在FirstResponder的下面。
解决问题方案######
方案一:遇到这种要滚动的问题,我们可以把FirstResponder的控件增加到UIScroollView中,这样可以实现滚动。
优点:最容易想到的方案,简单易写;
缺点:为了实现键盘自适应响应者功能,增加额外的UIScroollView滚动控件。
方案二:我们可以监听键盘的时候,直接滚动当前响应者控件的父View,设置View的frame.origin.y就可以
优点:没有增加控件就可以实现功能
所以我最终采用方案二
具体实现####
我想这样的需求主要用在登录的时候,所以就打算写一个UIViewController分类,就可以实现(已经封装成工具类,项目可以直接使用),这样可以一行代码拥有这个功能
#import "UIViewController+LZBKeyBoardObserver.h" 分类名称
使用方法:一行代码控制器有这个功能
[self lzb_addKeyBoardObserverAutoAdjustHeight];
1、在分类中增加键盘的监听
- (void)lzb_addKeyBoardObserverAutoAdjustHeight
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
有监听,必须有移除
- (void)lzb_removeKeyBoardObserver
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
//键盘手势
[[NSNotificationCenter defaultCenter] removeObserver:_keyboardWillShowObser name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:_keyboardWillHideObser name:UIKeyboardWillHideNotification object:nil];
}
2、键盘显示的时候调用通知方法,代码中有实现的步骤
- (void)keyboardWillShow:(NSNotification *)notification
{
//获取键盘的参数
CGFloat keyboardHeight = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;
CGFloat keyboardAnimaitonDuration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue];
NSInteger option = [notification.userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue];
//移除之前的动画
[self.view.layer removeAllAnimations];
UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow;
//找出第一响应者
UIView *firstResponseView = [self findFirstResponderWithView:self.view];
CGRect rect = [keyWindow convertRect:firstResponseView.frame fromView:firstResponseView.superview];
//计算第一响应者与键盘弹出的差值,滚动距离
CGFloat firstResponseViewMaxY= CGRectGetMaxY(rect);
CGFloat keyBoardY = keyWindow.bounds.size.height - keyboardHeight;
CGFloat keyBoardResponseViewMargin = firstResponseViewMaxY - keyBoardY;
//如果响应者的最大Y值 > 键盘的Y值才滚动
_lzb_keyBoard_DefaultMargin = 0;
if(firstResponseViewMaxY > keyBoardY)
{
//设置lzb_settingKeyBoard_DefaultMargin固定距离(就是滚动后的间距)
_lzb_keyBoard_DefaultMargin = lzb_settingKeyBoard_DefaultMargin;
_lzb_keyBoard_DefaultMargin +=keyBoardResponseViewMargin;
//滚动动画
__weak UIViewController *weakSelf = self;
[UIView animateKeyframesWithDuration:keyboardAnimaitonDuration
delay:0
options:option
animations:^{
CGRect frame = weakSelf.view.frame;
frame.origin.y -= _lzb_keyBoard_DefaultMargin;
weakSelf.view.frame = frame;
} completion:nil];
}
}
其中有个递归查找响应者的方法,比较简单,就不细说
- (UIView *)findFirstResponderWithView:(UIView *)view
{
if(self.isFirstResponder)
return self.view;
for (UIView *subView in view.subviews)
{
if(subView.isFirstResponder)
return subView;
else
continue;
}
return view;
}
3、键盘隐藏调用通知方法
- (void)keyboardWillHide:(NSNotification *)notification
{
//获取键盘的参数
CGFloat keyboardAnimaitonDuration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue];
NSInteger option = [notification.userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue];
__weak UIViewController *weakSelf = self;
//滚动动画
[UIView animateWithDuration:keyboardAnimaitonDuration
delay:0
options:option
animations:^{
CGRect frame = weakSelf.view.frame;
frame.origin.y += _lzb_keyBoard_DefaultMargin;
weakSelf.view.frame = frame;
}
completion:nil];
//注意:一定要清0,因为不知道下一次响应者是位置
_lzb_keyBoard_DefaultMargin = 0;
}
4.额外小功能,点击任意地方取消键盘响应
- (void)lzb_addKeyBoardTapAnyAutoDismissKeyBoard
{
UITapGestureRecognizer *lzbTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAnywhereToDismissKeyboard:)];
NSOperationQueue *mainQuene =[NSOperationQueue mainQueue];
__weak UIViewController *weakSelf = self;
_keyboardWillShowObser=[[NSNotificationCenter defaultCenter]
addObserverForName:UIKeyboardWillShowNotification
object:nil
queue:mainQuene
usingBlock:^(NSNotification * _Nonnull note) {
[weakSelf.view addGestureRecognizer:lzbTap];
}];
_keyboardWillHideObser = [[NSNotificationCenter defaultCenter]
addObserverForName:UIKeyboardWillHideNotification
object:nil
queue:mainQuene
usingBlock:^(NSNotification *note){
[weakSelf.view removeGestureRecognizer:lzbTap];
}];
}
#pragma mark - handel
- (void)tapAnywhereToDismissKeyboard:(UIGestureRecognizer *)gestureRecognizer {
[self.view endEditing:YES];
}
demo中还有其他功能,您的项目需要什么功能就用这么,本文中讲功能只要以下文件就好
![](https://img.haomeiwen.com/i1886288/dbb079c399a31c78.png)
详情代码请直接下载demo查看:
自定义键盘-LZBKeyBoardView
最后赠言###
star 是对我们程序猿最大的鼓励!