iOS避免键盘遮挡输入方案

时间:2021-07-04 19:48:56

项目中经常会遇到这样的问题:一个tableView中有大量的textField,当点击屏幕底部的textfield时,由于键盘弹出挡住了textfield输入框里的内容,造成很差的用户体验,如下图,点击价格那一行,会出现图二这种效果(弹出的键盘完全遮盖了输入)。

图一:

iOS避免键盘遮挡输入方案

图二:

iOS避免键盘遮挡输入方案

解决思路:自定义一个textfield,声明一个公用方法  - (void)adjustTextFieldFrameWhenBeginEdtingWithView: keyBoardHeight:  并实现它,这个方法的作用是调整controller的view的y值使整个view上移,让被点击的textfield显示出来,建议在controller的view的textfield的代理方法 -(void)textFieldDidBeginEditing: 中获取自定义的textfield,并调用它的此方法(开始编辑时就调整view的y值)。

1.自定义textfield:

实现公用方法: - (void)adjustTextFieldFrameWhenBeginEdtingWithView:

 - (void)adjustTextFieldFrameWhenBeginEdtingWithView:(UIView *)view keyBoardHeight:(CGFloat)keyboadHeight
{
// 将控制器view保存起来
self.adjustView = view; // 将textfield的坐标转换到控制器view坐标系中
CGRect selfFrame = [self convertRect:self.bounds toView:view]; // 键盘的y值
CGFloat keyBoardY = ; keyBoardY = [UIScreen mainScreen].bounds.size.height - keyboadHeight ; // 控制器view 要调整的高度
CGFloat adjustY = selfFrame.origin.y + selfFrame.size.height + MARGIN - keyBoardY; if (adjustY > ) { // 调整高度大于0 [UIView animateWithDuration:0.25 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{ view.y = - adjustY;
} completion:^(BOOL finished) { }];
}else{
[UIView animateWithDuration:0.25 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
view.y = ;
} completion:^(BOOL finished) { }];
} }

第13行用到了键盘的高度keyboadHeight,所以我们还需要在控制器中得到键盘的高度。

2.在控制器中获取键盘高度

在控制器的viewDidLoad方法中,注册通知(监听键盘出现的通知)。

 //增加监听,当键盘出现或改变时收出消息
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];

当键盘弹出时,获取键盘高度,并将键盘高度传入定义好的block

//当键盘出现或改变时调用
- (void)keyboardWillShow:(NSNotification *)aNotification
{
//获取键盘的高度
NSDictionary *userInfo = [aNotification userInfo];
NSValue *aValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];
CGRect keyboardRect = [aValue CGRectValue];
CGFloat keyboadHeight = keyboardRect.size.height; // 调用保存好的block并将键盘高度传入
self.editingBlock(keyboadHeight);
}

3.在控制器中调用textfield的自适应方法 - (void)adjustTextFieldFrameWhenBeginEdtingWithView: keyBoardHeight:

在控制器的textdelegate方法 - (void)textFieldDidBeginEditing: 中,定义block,在block中调用自定义textfield的自适应方法 - (void)adjustTextFieldFrameWhenBeginEdtingWithView: keyBoardHeight: ,并传入键盘高度。

之所以用block,是因为方法  - (void)textFieldDidBeginEditing:   被调用时,还没有获取到键盘高度,所以先将代码保存为block,等获取到键盘高度后再传入键盘高度,调用textfield的自适应键盘高度的方法 - (void)adjustTextFieldFrameWhenBeginEdtingWithView: keyBoardHeight:

block中调用自定义textfield的 - (void)adjustTextFieldFrameWhenBeginEdtingWithView: keyBoardHeight: 方法,并把键盘高度作为参数传入自定义textfield。

 #pragma YDTextFieldDelegate

 - (void)textFieldDidBeginEditing:(UITextField *)textField
{
YDTextField *tf = (YDTextField *)textField; __weak typeof(self) weakSelf = self; // 定义block,等待keyboardWillShow:方法获取键盘高度后调用
self.editingBlock = ^(CGFloat keyboadHeight){ // 此处调用自定义textfield的自适应方法
[tf adjustTextFieldFrameWhenBeginEdtingWithView:weakSelf.view keyBoardHeight:keyboadHeight]; }; }

4. 输入完成后处理

在控制器viewDidLoad方法中,注册通知,监听键盘消失。

// 当键盘消失时响应
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification object:nil];

键盘消失后,将调整后的view还原。

// 当键盘消失时调用
- (void)keyboardWillHide:(NSNotification *)note
{
if ([note.name isEqualToString:UIKeyboardWillShowNotification]) { }else{
[UIView animateWithDuration:0.25 animations:^{
self.view.y = ;
} completion:^(BOOL finished) { }];
}
}

如此就完成了textfield的自适应,每次点击底部textfield,view会根据textfield的位置上移一段距离,不被键盘遮盖,效果如下:

图三:

iOS避免键盘遮挡输入方案

图四:

iOS避免键盘遮挡输入方案

附上demo代码:

控制器中代码:

 //
// ViewController.m
// TextfieldDemo
//
// Created by heyode on 16/5/20.
// Copyright © 2016年 heyode. All rights reserved.
// #import "ViewController.h"
#import "YDTextField.h"
#import "UIView+frame.h"
// 键盘和当前活动textfield的间距
#define MARGIN 15 //定义随机色
#define randomColor [UIColor colorWithRed:arc4random_uniform(256)/255.0 green:arc4random_uniform(256)/255.0 blue:arc4random_uniform(256)/255.0 alpha:1]; typedef void(^textFieldDidBeginEditingBlock)(CGFloat keyboadHeight);
#define BASECOUNT 30 @interface ViewController ()<UITableViewDelegate,UITableViewDataSource,UITextFieldDelegate>
/** tableView */
@property (nonatomic,weak) UITableView *tableView; /** 数据源 */
@property (nonatomic,strong) NSMutableArray *datas; /** block */
@property (nonatomic,copy) textFieldDidBeginEditingBlock editingBlock; @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad]; [self setUpDataSouce];
[self setUpTableView]; [self setUpNotification];
} - (void)setUpNotification
{
//增加监听,当键盘出现或改变时收出消息
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil]; // 当键盘消失时响应
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification object:nil]; } // 当键盘消失时调用
- (void)keyboardWillHide:(NSNotification *)note
{
if ([note.name isEqualToString:UIKeyboardWillShowNotification]) { }else{
[UIView animateWithDuration:0.25 animations:^{
self.view.y = ;
} completion:^(BOOL finished) { }];
}
} //当键盘出现或改变时调用
- (void)keyboardWillShow:(NSNotification *)aNotification
{
//获取键盘的高度
NSDictionary *userInfo = [aNotification userInfo];
NSValue *aValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];
CGRect keyboardRect = [aValue CGRectValue];
CGFloat keyboadHeight = keyboardRect.size.height; // 调用保存好的block并将键盘高度传入
self.editingBlock(keyboadHeight);
} - (void)setUpTableView
{
UITableView *tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
tableView.delegate = self;
tableView.dataSource = self;
[self.view addSubview:tableView]; } - (void)setUpDataSouce
{
self.datas = [NSMutableArray array]; for (int i = ; i < ; i++) {
NSString *str = [NSString stringWithFormat:@"%i",i];
[self.datas addObject:str];
} } #pragma UITableviewDatasouce
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.datas.count;
} - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{ UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle: reuseIdentifier:@"cell"];
} for (id view in cell.contentView.subviews) {
[(UIView *)view removeFromSuperview];
} cell.textLabel.text = self.datas[indexPath.row]; YDTextField *tf = [[YDTextField alloc] initWithFrame:CGRectMake(, (cell.height - cell.height - )/, cell.width , cell.height - )];
tf.tag = indexPath.row + BASECOUNT; tf.backgroundColor = randomColor;
tf.delegate = self; [cell.contentView addSubview:tf];
return cell;
} #pragma YDTextFieldDelegate - (void)textFieldDidBeginEditing:(UITextField *)textField
{
YDTextField *tf = (YDTextField *)textField; __weak typeof(self) weakSelf = self; // 定义block,等待keyboardWillShow:方法获取键盘高度后调用
self.editingBlock = ^(CGFloat keyboadHeight){ // 此处调用自定义textfield的自适应方法
[tf adjustTextFieldFrameWhenBeginEdtingWithView:weakSelf.view keyBoardHeight:keyboadHeight]; }; } @end

自定义textfield代码:

 //
// YDTextField.m
// TextfieldDemo
//
// Created by heyode on 16/5/20.
// Copyright © 2016年 heyode. All rights reserved.
// #import "YDTextField.h"
#import "UIView+frame.h" // 键盘和当前活动textfield的间距
#define MARGIN 15 @interface YDTextField()
@property (weak, nonatomic) UIView *adjustView;
/**键盘高度 */
@property (nonatomic,assign) CGFloat keyboadHeight; @end @implementation YDTextField - (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
[self initialize]; }
return self;
} - (void)awakeFromNib
{ [self initialize];
} - (void)layoutSubviews
{
[super layoutSubviews];
} - (void)initialize
{ // 点击return时,结束编辑状态
[self addTarget:self action:@selector(endEditing:) forControlEvents:UIControlEventEditingDidEndOnExit];
} - (void)adjustTextFieldFrameWhenBeginEdtingWithView:(UIView *)view keyBoardHeight:(CGFloat)keyboadHeight
{
// 将控制器view保存起来
self.adjustView = view; // 将textfield的坐标转换到控制器view坐标系中
CGRect selfFrame = [self convertRect:self.bounds toView:view]; // 键盘的y值
CGFloat keyBoardY = ; keyBoardY = [UIScreen mainScreen].bounds.size.height - keyboadHeight ; // 控制器view 要调整的高度
CGFloat adjustY = selfFrame.origin.y + selfFrame.size.height + MARGIN - keyBoardY; if (adjustY > ) { // 调整高度大于0 [UIView animateWithDuration:0.25 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{ view.y = - adjustY;
} completion:^(BOOL finished) { }];
}else{
[UIView animateWithDuration:0.25 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
view.y = ;
} completion:^(BOOL finished) { }];
} } @end