您的位置:首页 > 移动开发 > IOS开发

iOS避免键盘遮挡输入方案

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

图一:



图二:



解决思路:自定义一个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 = 0;

keyBoardY = [UIScreen mainScreen].bounds.size.height - keyboadHeight ;

// 控制器view 要调整的高度
CGFloat adjustY = selfFrame.origin.y + selfFrame.size.height + MARGIN - keyBoardY;

if (adjustY > 0) { // 调整高度大于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 = 0;
} 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 = 0;
} completion:^(BOOL finished) {

}];
}
}


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

图三:



图四:



附上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 = 0; } 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 = 0; i < 20; 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:0 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(50, (cell.height - cell.height - 2)/2, cell.width , cell.height - 2)];
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 = 0;

keyBoardY = [UIScreen mainScreen].bounds.size.height - keyboadHeight ;

// 控制器view 要调整的高度
CGFloat adjustY = selfFrame.origin.y + selfFrame.size.height + MARGIN - keyBoardY;

if (adjustY > 0) { // 调整高度大于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 = 0;
} completion:^(BOOL finished) {

}];
}

}

@end
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: