一. 键盘通知实现
调用键盘事件一般是为了在键盘弹出或者隐藏的时候同时调整输入框的位置以防止被键盘遮挡:
三. 实现多个输入框防键盘遮挡
1.注册键盘通知事件:
- (void)viewDidLoad {
[superviewDidLoad];
// 注册键盘通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:)name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:)name:UIKeyboardWillHideNotification object:nil];
}
其中keyboardWillShow和keyboardWillHide是自定义函数,用于在键盘显示和隐藏时触发。
2.事件实现:
- (void)keyboardWillShow:(NSNotification*)notificationShow {
//键盘的动画时间
doubleduration = [[notificationShow.userInfoobjectForKey:UIKeyboardAnimationDurationUserInfoKey]doubleValue];
//键盘将要弹出的时候要做的事...
}
- (void)keyboardWillHide:(NSNotification*)notificationHide {
//键盘的动画时间
doubleduration = [[notificationHide.userInfoobjectForKey:UIKeyboardAnimationDurationUserInfoKey]doubleValue];
//键盘将要隐藏的时候要做的事...
}
二. 实现单个输入框防遮挡
//
// InputAjustViewController.m
// JXHDemo
//
// Created by Xinhou Jiang on 6/8/16.
// Copyright © 2016 Jiangxh. All rights reserved.
//
#define inputW 200 // 输入框宽高
#define inputH 40
#define minDistance 10 // 键盘与输入框调整的最小间距
#define navH 64 // 如果当前页面有导航栏的话要加入导航栏高度的考虑
#import "InputAjustViewController.h"
@interface InputAjustViewController()
/**
* 输入框
*/
@property (nonatomic, strong)UITextField *inputFeild;
/**
* 输入框防遮挡调整的offset
*/
@property (nonatomic)CGFloat offset;
@end
@implementation InputAjustViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 设置输入框
[self setInputFeild];
// 注册键盘通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
/**
* 设置输入框
*/
- (void)setInputFeild {
//1.输入框
_inputFeild = [[UITextField alloc] initWithFrame:CGRectMake(ApplicationW/2 - inputW/2, ApplicationH/2, inputW, inputH)];
//边框
//_inputFeild.layer.borderWidth = 1;
//_inputFeild.layer.borderColor = [UIColor orangeColor].CGColor;
//边框类型
_inputFeild.borderStyle = UITextBorderStyleRoundedRect;
//背景色
_inputFeild.backgroundColor = [UIColor whiteColor];
//placeholder
_inputFeild.placeholder = @"Please input...";
//文字颜色
_inputFeild.textColor = [UIColor blueColor];
//文字对齐格式
//_inputFeild.textAlignment = UITextAlignmentLeft;
//文字大小和字体
_inputFeild.font = [UIFont fontWithName:@"Times New Roman" size:20];
//文字自适应
_inputFeild.adjustsFontSizeToFitWidth = YES;
//文字清除按钮
_inputFeild.clearsOnBeginEditing =YES;
[self.view addSubview:_inputFeild];
}
/**
* 键盘即将弹出
*/
- (void)keyboardWillShow:(NSNotification*)notificationShow {
// 获取键盘信息数据
NSDictionary *keyboardInfo = [notificationShow userInfo];
// 获取键盘高度
CGFloat keyboardH = [[keyboardInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;
// 计算遮挡的offset
_offset = _inputFeild.frame.origin.y + _inputFeild.frame.size.height + keyboardH + minDistance + navH - ApplicationH;
if(_offset > 0) {
// 将当前view往上移动offset距离
CGRect frame = self.view.frame;
self.view.frame = CGRectMake(0, frame.origin.y-_offset, frame.size.width, frame.size.height);
}
}
/**
* 键盘即将隐藏
*/
- (void)keyboardWillHide:(NSNotification*)notificationHide {
// 将当前view移回
if(_offset > 0) {
CGRect frame = self.view.frame;
self.view.frame = CGRectMake(0, frame.origin.y+_offset, frame.size.width, frame.size.height);
}
}
/**
* 调用当前view的触摸事件撤销键盘
*/
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
//[self.view endEditing:YES];//取消第一响应者
[_inputFeild resignFirstResponder];//直接取消输入框的第一响应
}
@end
三. 实现多个输入框防键盘遮挡
当界面有多个输入框时,键盘弹出时要知道是哪一个输入框要开始编辑,并进行调整,实现方法是改装上面的代码,
加入输入框UITextFeildDelegate的代理,其代理事件在键盘通知事件之前执行,所以可以利用代理得到将要编辑的输入框,然后执行和上面相同的调整操作,调整代码如下:
//
// InputAjustViewController.m
// JXHDemo
//
// Created by Xinhou Jiang on 6/8/16.
// Copyright © 2016 Jiangxh. All rights reserved.
//
#define inputW 200 // 输入框宽高
#define inputH 40
#define minDistance 10 // 键盘与输入框调整的最小间距
#define navH 64 // 如果当前页面有导航栏的话要加入导航栏高度的考虑
#import "InputAjustViewController.h"
@interface InputAjustViewController()<UITextFieldDelegate>
/**
* 正在编辑的输入框
*/
@property (nonatomic, strong)UITextField *inputFeild;
/**
* 输入框防遮挡调整的offset
*/
@property (nonatomic)CGFloat offset;
@end
@implementation InputAjustViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 设置输入框
[self setInputFeild];
// 注册键盘通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
/**
* 设置输入框
*/
- (void)setInputFeild {
// 2个输入框
UITextField *input = [[UITextField alloc] initWithFrame:CGRectMake(ApplicationW/2 - inputW/2, ApplicationH/2, inputW, inputH)];
//设置当前控制器代理
input.delegate = self;
//边框类型
input.borderStyle = UITextBorderStyleRoundedRect;
//背景色
input.backgroundColor = [UIColor whiteColor];
//placeholder
input.placeholder = @"Please input...";
[self.view addSubview:input];
UITextField *input2 = [[UITextField alloc] initWithFrame:CGRectMake(ApplicationW/2 - inputW/2, ApplicationH/3*2, inputW, inputH)];
//设置当前控制器代理
input2.delegate = self;
//边框类型
input2.borderStyle = UITextBorderStyleRoundedRect;
//背景色
input2.backgroundColor = [UIColor whiteColor];
//placeholder
input2.placeholder = @"Please input...";
[self.view addSubview:input2];
}
/**
* 键盘即将弹出
*/
- (void)keyboardWillShow:(NSNotification*)notificationShow {
// 获取键盘信息数据
NSDictionary *keyboardInfo = [notificationShow userInfo];
// 获取键盘高度
CGFloat keyboardH = [[keyboardInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;
// 计算遮挡的offset
_offset = _inputFeild.frame.origin.y + _inputFeild.frame.size.height + keyboardH + minDistance + navH - ApplicationH;
if(_offset > 0) {
// 将当前view往上移动offset距离
CGRect frame = self.view.frame;
self.view.frame = CGRectMake(0, frame.origin.y-_offset, frame.size.width, frame.size.height);
}
}
/**
* 键盘即将隐藏
*/
- (void)keyboardWillHide:(NSNotification*)notificationHide {
// 将当前view移回
if(_offset > 0) {
CGRect frame = self.view.frame;
self.view.frame = CGRectMake(0, frame.origin.y+_offset, frame.size.width, frame.size.height);
}
}
/**
* 调用当前view的触摸事件撤销键盘
*/
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
//[self.view endEditing:YES];//取消第一响应者
[_inputFeild resignFirstResponder];//直接取消输入框的第一响应
}
/**
* 输入框开始编辑代理事件
*/
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
// 将要编辑的输入框设置为当前目标调整输入框
_inputFeild = textField;
return YES;
}
@end
四. bug清除优化后的最终版本
上面的实现方式在多个输入框之间直接切换输入时会出现view不能恢复到初始位置等问题,解决方式和动画平滑优化一下几点:
1.进入视图时记录当前view的初始frame用于回复view的初始位置;
2.视图的移动调整以其初始为参考,而不是移动后的view的frame的位置;
3.通过键盘事件获取键盘动画的时间,加入uiview的动画实现view跟随键盘同步动画平滑移动;
优化后的最终版本代码如下:
//
// InputAjustViewController.m
// JXHDemo
//
// Created by Xinhou Jiang on 6/8/16.
// Copyright © 2016 Jiangxh. All rights reserved.
//
#define inputW 200 // 输入框宽高
#define inputH 40
#define minDistance 5 // 键盘与输入框调整的最小间距
#import "InputAjustViewController.h"
@interface InputAjustViewController()<UITextFieldDelegate>
/**
* 正在编辑的输入框
*/
@property (nonatomic, strong)UITextField *inputFeild;
/**
* 输入框防遮挡调整的offset
*/
@property (nonatomic)CGFloat offset;
/*
* 视图原frame,用于恢复视图位置
*/
@property (nonatomic) CGRect originalFrame;
@end
@implementation InputAjustViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 保存view初始位置尺寸
_originalFrame = self.view.frame;
// 设置输入框
[self setInputFeild];
// 注册键盘通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
/**
* 设置输入框
*/
- (void)setInputFeild {
// 2个输入框
UITextField *input = [[UITextField alloc] initWithFrame:CGRectMake(ApplicationW/2 - inputW/2, ApplicationH/2, inputW, inputH)];
//设置当前控制器代理
input.delegate = self;
//边框类型
input.borderStyle = UITextBorderStyleRoundedRect;
//背景色
input.backgroundColor = [UIColor whiteColor];
//placeholder
input.placeholder = @"Please input...";
[self.view addSubview:input];
UITextField *input2 = [[UITextField alloc] initWithFrame:CGRectMake(ApplicationW/2 - inputW/2, ApplicationH/3*2, inputW, inputH)];
//设置当前控制器代理
input2.delegate = self;
//边框类型
input2.borderStyle = UITextBorderStyleRoundedRect;
//背景色
input2.backgroundColor = [UIColor whiteColor];
//placeholder
input2.placeholder = @"Please input...";
[self.view addSubview:input2];
}
/**
* 键盘即将弹出
*/
- (void)keyboardWillShow:(NSNotification*)notificationShow {
// 获取键盘信息数据
NSDictionary *keyboardInfo = [notificationShow userInfo];
// 获取键盘高度
CGFloat keyboardH = [[keyboardInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;
// 获取键盘动画时间
double duration = [[notificationShow.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
// 计算遮挡的offset
_offset = _inputFeild.frame.origin.y + _inputFeild.frame.size.height + keyboardH + minDistance - ApplicationH;
if(_offset > 0) {
// 将当前view往上移动offset距离
CGRect frame = _originalFrame;
[UIView animateWithDuration:duration animations:^{
self.view.frame = CGRectMake(0, frame.origin.y-_offset, frame.size.width, frame.size.height);
} completion:^(BOOL finished) {
}];
}
}
/**
* 键盘即将隐藏
*/
- (void)keyboardWillHide:(NSNotification*)notificationHide {
// 获取键盘动画时间
double duration = [[notificationHide.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
// 将当前view移回
if(_offset > 0) {
[UIView animateWithDuration:duration animations:^{
self.view.frame = _originalFrame;
} completion:^(BOOL finished) {
}];
}
}
/**
* 调用当前view的触摸事件撤销键盘
*/
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
//[self.view endEditing:YES];//取消第一响应者
[_inputFeild resignFirstResponder];//直接取消输入框的第一响应
}
/**
* 输入框开始编辑代理事件
*/
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
// 将要编辑的输入框设置为当前目标调整输入框
_inputFeild = textField;
return YES;
}
@end
GitHub Demo:https://github.com/jiangxh1992/JXHDemo/tree/master/JXHDemo/UIKit/输入框防键盘遮挡