浅谈键盘遮挡输入框的处理<类别方法>

处理键盘遮挡输入框的方法很多,不管怎么说,网上有个第三方还是很不错的.但是工程中第三方库还是越少越好.
这里通过给UITextField添加类别方法来实现
这里涉及到 键盘和输入框
比较简单的做法是监听键盘发出的通知.毕竟键盘的frame的改变可能会遮档到输入框.
很多做法是监听键盘出现和键盘隐藏的通知.
但是切换输入法可能也会使键盘frame发生改变.
所以我比较建议的是监听键盘frame发生的改变.

  1. 给分类添加需要的方法
    -(void)setAutojust:(BOOL)autojust;
    使用时直接设置就好了.
    在实现文件中,定义一个keywindow的初始frame
#define OrignalRect [UIApplication sharedApplication].keyWindow.bounds
实现添加的方法
-(void)setAutojust:(BOOL)autojust{
    if (autojust) {
         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChange:) name:UIKeyboardWillChangeFrameNotification object:nil];
    }else{
        [[NSNotificationCenter defaultCenter]removeObserver:self];
    }
}

实现监听的方法

-(void)keyboardWillChange:(NSNotification *)notice{
    if (!self.isFirstResponder) {
        return;
    }
    if (notice.name == UIKeyboardWillChangeFrameNotification ) {
        //1.获取改变的结束位置:
        NSValue *endRectValue =  [notice.userInfo valueForKey:UIKeyboardFrameEndUserInfoKey];
        CGRect endRect = endRectValue.CGRectValue;
        //2.获取动画执行时间
        NSNumber *duration = [notice.userInfo valueForKey:UIKeyboardAnimationDurationUserInfoKey];
        CGFloat durationTime = duration.floatValue;
        //3.判断结束时 有没有挡道输入框
        //转换到同一坐标系
        CGRect reletive =  [self convertRect:self.bounds toView:[UIApplication sharedApplication].keyWindow];
        CGFloat textMaxY =  CGRectGetMaxY(reletive);
        CGFloat keybordMinY = CGRectGetMinY(endRect);
        //键盘弹起如果挡到了 改变window的frame
        if (textMaxY >= keybordMinY) {
            [UIView animateWithDuration:durationTime delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
                CGRect windowRect = OrignalRect;
                CGFloat space = 5;
                windowRect.origin.y = keybordMinY -textMaxY - space;
                [UIApplication sharedApplication].keyWindow.frame = windowRect;
            } completion:nil];
            return;
        }
        //4.如果键盘收回时 window 没恢复 进行恢复
        if (!CGRectEqualToRect([UIApplication sharedApplication].keyWindow.frame, OrignalRect)) {
            [UIView animateWithDuration:durationTime delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
                [UIApplication sharedApplication].keyWindow.frame = OrignalRect;
            } completion:nil];
        }
    }
}

当有多个输入框的时候,直接切换到比较高的输入框,再切换到其他地方,收起接盘,可能会出现windowframe没回去的情况,因此这个时候,还需要监听一下收起键盘的方法.因为虽然已经监听了键盘改变的方法,但那个方法中判断了是不是第一响应,而被挡到的可能早就不是第一响应了,因此那里面的方法不一定会走.

所以要单独监听 这里只用还原window的frame就可以

因此在设置监听的方法中增加下列代码

   [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];

实现方法

-(void)keyboardWillHide:(NSNotification *)notice{
    if (!CGRectEqualToRect([UIApplication sharedApplication].keyWindow.frame, OrignalRect)) {
        [UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
            [UIApplication sharedApplication].keyWindow.frame = OrignalRect;
        } completion:nil];
    }
}

注意移除监听者

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter]removeObserver:self];
}

这样就可以了,如果想要更加完美的表现,要么使用第三方库,要么需要在ViewCtr或者父视图做未处理,因为分类方法只能获得自己的相关属性和状态,如果一堆输入框,处理起来比较麻烦.
目前这个分类方法,已经基本适应多个输入框自适应键盘frame的变更了.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容