ios中TextField防止被键盘遮挡


1、

已上图举例,弹出键盘不会遮挡TextField输入,(下面横线是通过UIView画的线实现的,不用在意这些细节)

2、

获取键盘高度:可以自行百度下,下面有完整代码

3、

设置TextField的代理,实现代理协议,遵守代理方法

4、

计算偏移量。

首先假设TextField被键盘完全覆盖,进行计算应该偏移量,执行代码,发现效果可行后,关闭键盘时返回,一定不要用偏移量去返回,用偏移量会产生非常严重的问题,怎么解决看详细的代码。

其次假设TextField没被键盘覆盖,经测试发现上面假设不变即可以实现目标,其他状态下也可以实现目标。

5、

详细代码:

// 登录注册界面

==================================


#import <UIKit/UIKit.h>


@interface Register1ViewController : UIViewController


@end

=================================

// 登录注册界面


#import "Register1ViewController.h"

#import "ReadMeViewController.h"




@interface Register1ViewController ()  <UITextFieldDelegate>


@property (weak, nonatomic) IBOutlet UITextField *numberFid;   // 手机号码


@property (weak, nonatomic) IBOutlet UITextField *securityCodeFid;   // 验证码


@property (weak, nonatomic) IBOutlet UIButton *getsecurityCodeBtn;  // 获取验证码


@property (weak, nonatomic) IBOutlet UIImageView *changeImg;  // 协议选中


@property (weak, nonatomic) IBOutlet UILabel *readLab; // 点击进入协议详情


@property (weak, nonatomic) IBOutlet UIButton *registerBtn;   // 立即登录


@property (assign, nonatomic) BOOL isRead;   // 是否同意协议

@property (nonatomic, strong) NSTimer *timer; //验证码倒计时


@end


static NSInteger a = 0;

int offset; //偏移量

int key_height; //键盘高度


@implementation Register1ViewController


- (void)viewDidLoad {

    [super viewDidLoad];

    //设置按钮背景色

//    self.navigationController.navigationBar.hidden = YES;

    

    self.numberFid.delegate = self;    // 1.代理

    self.securityCodeFid.delegate = self;    // 1.代理

    

    _getsecurityCodeBtn.backgroundColor = RGBACOLORTitle;

    _registerBtn.backgroundColor = RGBACOLORTitle;

    self.title = @"登录";

    self.isRead = YES;

    self.registerBtn.layer.masksToBounds = YES;

    self.registerBtn.layer.cornerRadius = 3;

    self.getsecurityCodeBtn.layer.masksToBounds = YES;

    self.getsecurityCodeBtn.layer.cornerRadius = 3;

    self.tabBarController.tabBar.hidden = YES;

    UITapGestureRecognizer *changeTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(changeClick:)];

    [self.changeImg addGestureRecognizer:changeTap];

    CALayer * layer = [self.changeImg layer];

    layer.borderColor = [[UIColor lightGrayColor] CGColor];

    layer.borderWidth = 0.5f;

    UITapGestureRecognizer *readTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(readClick:)];

    [self.readLab addGestureRecognizer:readTap];

    

    //增加监听,当键盘出现或改变时收出消息

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification

                                                      object:nil];

 

    //增加监听,当键退出时收出消息

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

                                                      object:nil];

}


- (void)viewWillAppear:(BOOL)animated{

    a = 0;

    self.timer = nil;

}


// 实现代理中的方法

// 实现代理中的方法

- (BOOL)textFieldShouldReturn:(UITextField *)textField {

    [textField resignFirstResponder];

    return YES;

}



- (void)keyboardWillShow:(NSNotification *)aNotification{

   NSDictionary *userInfo = [aNotification userInfo];

   NSValue *aValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];

   CGRect keyboardRect = [aValue CGRectValue];

   key_height = keyboardRect.size.height;

 }


//当键退出时调用

 - (void)keyboardWillHide:(NSNotification *)aNotification{

     

 }


/***下面是全屏的一个view, view上有子控件 textField的使用方法***/

- (void)textFieldDidBeginEditing:(UITextField *)textField{

    //情形1、当前键盘覆盖了TextField (经调试发现即使没有覆盖本方法也同样适用)

    // 最后一个控件的y点位置,最后一个控件的高度,有navigation的话要加64,没有可不加

    int lastViewHeight = self.registerBtn.frame.origin.y + 30 + 64; //  获取最后一个控件离底端位置,即所占屏幕高度

    int textFieldHeight = textField.frame.origin.y + textField.frame.size.height; // 需要移动的Textfield的底端高度

    int superHight =  lastViewHeight -  ScreenHeight;//超出屏幕部分的距离

    int destinationPosition = lastViewHeight - superHight - key_height; // 目标位置高度:最后一个控件减去超出的,减去键盘高度

    offset = textFieldHeight - destinationPosition + 20;//目标控件顶端位置减去目标位置高度,期望键盘和Textfield有20的距离

    NSTimeInterval animationDuration = 0.30f; // 下面都是动画

    [UIView beginAnimations:@"ResizeForKeyboard" context:nil];

    [UIView setAnimationDuration:animationDuration];

    if(offset > 0) // 

    self.view.frame = CGRectMake(0.0f, -offset, ScreenWidth, ScreenHeight);//经测试ScreenHeight参数貌似不是非常重要,可以用lastViewHeithgt代替

    [UIView commitAnimations];

}


- (void)textFieldDidEndEditing:(UITextField *)textField{

//   30是Textfield的高度

    if(offset > 0){

        NSTimeInterval animationDuration = 0.30f;

        [UIView beginAnimations:@"ResizeForKeyboard" context:nil];

        [UIView setAnimationDuration:animationDuration];

        // 64 是navigation的高度,如果没有,就写为0

        self.view.frame = CGRectMake(0.0f, 64, ScreenWidth, ScreenHeight);//经测试ScreenHeight参数貌似不是非常重要,可以用lastViewHeithgt代替

        [UIView commitAnimations];

    }

}


// 点击事件

// 获取验证码

- (IBAction)getsecurityCodeAction:(UIButton *)sender {

    if (!self.numberFid.text || [self.numberFid.text isEqualToString:@""]) {

        //        [MBProgressHUD show:@"请补全号码或输入正确号码" icon:nil view:self.view time:3];

        [MBProgressHUD showAlertView:@"" andMessage:@"请补全号码或输入正确号码"];

        return;

    }

    self.timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timerClick) userInfo:nil repeats:YES];

    [self getsecurityCode];

    [[NSRunLoop currentRunLoop]addTimer:_timer forMode:NSDefaultRunLoopMode];

    [_timer fire];

}

// 立即登录

- (IBAction)registerAction:(UIButton *)sender {

    if (self.isRead) {

        

        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {

            

        }];

    }else{

        [MBProgressHUD showAlertView:@"" andMessage:@"请阅读并同意《用户协议》"];

    }

}


- (void)Register{

    

}


- (void)getsecurityCode{

    

}


//协议是否选中

- (void)changeClick:(UITapGestureRecognizer *)sender{

    if (_isRead) {

        self.changeImg.image = nil;

        self.isRead = NO;

    }else{

        self.changeImg.image = [UIImage imageNamed:@"loginandregist_protocol"];

        self.isRead = YES;

    }

}


//点击进入协议详情

- (void)readClick:(UITapGestureRecognizer *)sender{

    ReadMeViewController *vc = [ReadMeViewController new];

    [self.navigationController pushViewController:vc animated:YES];

}


- (void)timerClick{

    NSInteger b = 60 - a;

    if (b > 0) {

        self.getsecurityCodeBtn.titleLabel.text = [NSString stringWithFormat:@"重新发送%ld",b];

        [self.getsecurityCodeBtn setTitle:[NSString stringWithFormat:@"重新发送%ld",b] forState:(UIControlStateNormal)];

        self.getsecurityCodeBtn.userInteractionEnabled = NO;

        a++;

    }

    if (b == 0) {

        [self.getsecurityCodeBtn setTitle:@"获取验证码" forState:(UIControlStateNormal)];

        self.getsecurityCodeBtn.userInteractionEnabled = YES;

        a = 0;

        [_timer invalidate];

    }

}


// 将键盘收缩

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

    [self.view endEditing:YES];

}


@end

=================================


ps:应该没有什么代码遗漏,自己写了三天才完成的,主要计算那里太坑了,

还有就是:

self.view.frame = CGRectMake(0.0f, 64, ScreenWidth, ScreenHeight); 

这个写64或者是0,主要是看有没有navigation。有一点小瑕疵,就是在和键盘位置差不多的时候,会重叠一点,计算应该没问题,不知道为啥会这样。