天天看点

简单完美的解决键盘遮挡输入框的问题

开发时页面中会有很多输入框,不可避免的会有键盘弹出时挡住输入框的情况(还有iPhone尺寸,键盘的高度不一致等原因)。
    一般做法是监听键盘弹出和隐藏的通知,弹出时让view上移一部分(键盘的高度),隐藏时view下移一部分。
           
还有做法就是在textField的代理方法中上移view和下移view,在- (void)textFieldDidBeginEditing:(UITextField *)textField中上移view,在- (void)textFieldDidEndEditing:(UITextField *)textField中下移view。
    但是,这两种做法都不能完美解决我们标题的问题。
    我的做法是将上面两种方法结合,通过通知获得键盘的高度,通过textField的代理方法我们能知道是哪一个textField,然后将这个textField的frame转化到控制器的view的frame,这样我们就可以比较适否被遮挡,遮挡的话进行上移等等。
           
解决方法:创建一个控制器,作为其他控制器的基类,这样其他控制器中的输入框只要设置了delegate是self就不用写多余代码。
           
#import "YTUIViewController.h"
#import "Define.h"

@interface YTUIViewController ()
{
    CGFloat viewBottom;     //textField的底部
    CGFloat keyboardDuration;   //键盘隐藏需要的时间 = 键盘弹出的时间
}

@end




@implementation YTUIViewController


//移除监听
- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}



- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];


    [self setupForKeyBoard];
}



#pragma mark -键盘相关
//键盘的准备
- (void)setupForKeyBoard
{
    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];

    //点击手势点击非输入框区域隐藏键盘
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(keyBoardHideAction)];

    NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];



    //键盘显示后添加手势
    [nc addObserverForName:UIKeyboardWillShowNotification object:nil queue:mainQueue usingBlock:^(NSNotification * _Nonnull note) {
        [self.view addGestureRecognizer:tap];
        [self keyboardWillShow:note];
    }];

    //键盘消失后移除手势
    [nc addObserverForName:UIKeyboardWillHideNotification object:nil queue:mainQueue usingBlock:^(NSNotification * _Nonnull note) {
        [self.view removeGestureRecognizer:tap];

        //键盘动画时间
        double duration = [[note.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];

        [UIView animateWithDuration:duration animations:^{
            self.view.frame = CGRectMake(,   , SCREEN_WIDTH, SCREEN_HEIGHT);
        }];
    }];
}


//键盘消失后view下移
- (void)keyBoardHideAction
{
    NSLog(@"begin hide");
    [self.view endEditing:YES];

}


//通过note获取键盘高度,键盘动画时间
- (void)keyboardWillShow:(NSNotification *)note
{
    NSLog(@"后调用");

    //键盘高度
    CGFloat keyboardH = [[note.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;

    //键盘动画时间
    keyboardDuration = [[note.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];

    if (viewBottom + keyboardH < SCREEN_HEIGHT) {
        return;
    }
    else
    {
        [UIView animateWithDuration:keyboardDuration animations:^{
            self.view.frame = CGRectMake(, - ( keyboardH - (SCREEN_HEIGHT - viewBottom)), SCREEN_WIDTH, SCREEN_HEIGHT);
        }];
    }
}





#pragma mark -UITextFieldDelegate
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    NSLog(@"最先调用");

    //将textField的rect转换到self.view上
    CGRect rect = [textField.superview convertRect:textField.frame toView:self.view];

    //textField的底部
    viewBottom = rect.origin.y + rect.size.height;


}


- (void)textFieldDidEndEditing:(UITextField *)textField
{
    NSLog(@"最后调用");
    [UIView animateWithDuration:keyboardDuration animations:^{
        self.view.frame = CGRectMake(, , SCREEN_WIDTH, SCREEN_HEIGHT);
    }];

}

           
注意:.h文件如下,遵循协议申明在.h文件,这样子类不用再申明遵循该协议
           
#import <UIKit/UIKit.h>

@interface YTUIViewController : UIViewController<UITextFieldDelegate>

@end
           
附上demo地址:[KeyboardDemo](https://git.oschina.net/yant/KeyboardDemo)
    如有不对,请指正。