本文介绍,如何解决 UITextField被软键盘遮挡的问题
在iOS开发中,需要经常使用到 UITextField 控件来接收用户输入到数据,使用时也会经常发生 UITextField 被弹出的软键盘遮挡,根据目前的情况,解决方案有以下:
- 第三方库:IQKeyboardManager
- 监听软键盘的弹出和消失
IQKeyboardManager
这种方式,非常高效,可以进行无需调用代码既可以自动适配 软键盘弹出和消失 时, UITextField 自动上移和恢复;具体用法不在此文介绍,想要了解用法的,可以自行到github上查看:https://github.com/hackiftekhar/IQKeyboardManager
监听软键盘的弹出和消失
这种方式就需要自己添加代码去控制了,此文主要介绍这种手动适配方案
原理
- 监听软键盘的弹出,把整个界面往上移动
- 监听软键盘的消失,把整个界面恢复
实现步骤
- 把UITextField添加到ViewController,并且实现UITextFieldDelegate
@interface UIViewController () <UITextFieldDelegate>
// 当前获取焦点的UITextField
@property (strong, nonatomic) UITextField *currentResponderTextField;
@end
@implementation BIGBaseViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 界面存在多个 UITextField
UITextField *textField1 = [[UITextField alloc] init];
// ... TextField的各种属性设置
textField1.delegate = self; // 这一个属性一定需要设置
[self.view addSubview:textField1];
UITextField *textField2 = [[UITextField alloc] init];
// ... TextField的各种属性设置
textField2.delegate = self; // 这一个属性一定需要设置
[self.view addSubview:textField2];
// ...
}
#pragma mark -- UITextFieldDelegate
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
//当将要开始编辑的时候,获取当前的textField的赋值给属性变量currentResponderTextField
self.currentResponderTextField = textField;
return YES;
}
@end
- 注册通知
- (void)dealloc
{
// 注册了通知,在ViewController消失到时候,要移除通知的监听
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIKeyboardWillHideNotification
∂object:nil];
}
- (void)viewDidLoad {
[super viewDidLoad];
// 添加 .... 各种View
// 在ViewController加载到时候注册通知监听
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:) // 软键盘出现的时候,回调到方法
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHide:) // 软键盘消失的时候,回调到方法
name:UIKeyboardWillHideNotification
object:nil];
}
- 软键盘出现时回调:keyboardWillShow
- (void)keyboardWillShow:(NSNotification *)notification {
if (!(self.currentResponderTextField && [self.currentResponderTextField isKindOfClass:[UITextField class]])) {
// 如果没有响应者不进行操作
return;
}
//获取currentResponderTextField相对于self.view的frame信息
CGRect rect = [self.currentResponderTextField.superview convertRect:self.currentResponderTextField.frame toView:self.view];
//获取弹出键盘的frame的value值
NSDictionary *userInfo = [notification userInfo];
NSValue *aValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];
CGRect keyboardRect = [aValue CGRectValue];
//获取键盘相对于self.view的frame信息 ,传window和传nil是一样的
keyboardRect = [self.view convertRect:keyboardRect fromView:self.view.window];
//弹出软键盘左上角点Y轴的值
CGFloat keyboardTop = keyboardRect.origin.y;
//获取键盘弹出动画时间值
NSNumber * animationDurationValue = [userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey];
NSTimeInterval animationDuration = [animationDurationValue doubleValue];
if (keyboardTop < CGRectGetMaxY(rect)) {
// true 键盘盖住了输入框
// 计算整体界面需要往上移动的偏移量,CGRectGetMaxY(rect)表示,输入框Y轴最大值
CGFloat gap = keyboardTop - CGRectGetMaxY(rect);
// 存在多个TextField的情况下,可能整体界面可能以及往上移多次,导致self.view的Y轴值不再为0,而是负数
gap = gap + self.view.frame.origin.y;
__weak typeof(self)weakSelf = self;
[UIView animateWithDuration:animationDuration animations:^{
weakSelf.view.frame = CGRectMake(weakSelf.view.frame.origin.x, gap, weakSelf.view.frame.size.width, weakSelf.view.frame.size.height);
}];
}
}
- 软键盘消失时回调:keyboardWillHide
- (void)keyboardWillHide:(NSNotification *)notification {
if (!(self.currentResponderTextField && [self.currentResponderTextField isKindOfClass:[UITextField class]])) {
// 如果没有响应者不进行操作
return;
}
//获取键盘隐藏动画时间值
NSDictionary *userInfo = [notification userInfo];
NSNumber * animationDurationValue = [userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey];
NSTimeInterval animationDuration = [animationDurationValue doubleValue];
if (self.view.frame.origin.y < 0) {
//true 证明已经往上移动,软键盘消失时,整个界面要恢复原样
__weak typeof(self)weakSelf = self;
[UIView animateWithDuration:animationDuration animations:^{
weakSelf.view.frame = CGRectMake(weakSelf.view.frame.origin.x, 0, weakSelf.view.frame.size.width, weakSelf.view.frame.size.height);
}];
}
}