iOS -自定义键盘系列之二键盘自适应响应者

首先解释一下标题,什么是键盘自适应响应者,理解为无论响应者在什么位置,键盘弹出都会在响应者的下面,使响应者控件可见。

demo效果


键盘自动适应响应者.gif
键盘自动适应响应者.gif
提出问题######

我们在做登录页面的时候假如有多个输入框,并且当输入框在屏幕底部的时候,我们直接弹出键盘就会挡住输入框,如图所示?(需要调整键盘)

自动适应键盘实例情况.png
自动适应键盘实例情况.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中还有其他功能,您的项目需要什么功能就用这么,本文中讲功能只要以下文件就好


本文功能文件.png
本文功能文件.png

详情代码请直接下载demo查看:
自定义键盘-LZBKeyBoardView

最后赠言###

star 是对我们程序猿最大的鼓励!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,490评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,581评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,830评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,957评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,974评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,754评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,464评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,357评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,847评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,995评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,137评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,819评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,482评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,023评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,149评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,409评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,086评论 2 355

推荐阅读更多精彩内容