项目中经常会遇到这样的问题:一个tableView中有大量的textField,当点击屏幕底部的textfield时,由于键盘弹出挡住了textfield输入框里的内容,造成很差的用户体验,如下图,点击价格那一行,会出现图二这种效果(弹出的键盘完全遮盖了输入)。
图一:
图二:
解决思路:自定义一个textfield,声明一个公用方法 - (void)adjustTextFieldFrameWhenBeginEdtingWithView: keyBoardHeight: 并实现它,这个方法的作用是调整controller的view的y值使整个view上移,让被点击的textfield显示出来,建议在controller的view的textfield的代理方法 -(void)textFieldDidBeginEditing:
1.自定义textfield:
实现公用方法: - (void)adjustTextFieldFrameWhenBeginEdtingWithView:
1 - (void)adjustTextFieldFrameWhenBeginEdtingWithView:(UIView *)view keyBoardHeight:(CGFloat)keyboadHeight
2 {
3 // 将控制器view保存起来
4 self.adjustView = view;
5
6 // 将textfield的坐标转换到控制器view坐标系中
7 CGRect selfFrame = [self convertRect:self.bounds toView:view];
8
9 // 键盘的y值
10 CGFloat keyBoardY = 0;
11
12
13 keyBoardY = [UIScreen mainScreen].bounds.size.height - keyboadHeight ;
14
15
16
17 // 控制器view 要调整的高度
18 CGFloat adjustY = selfFrame.origin.y + selfFrame.size.height + MARGIN - keyBoardY;
19
20
21
22 if (adjustY > 0) { // 调整高度大于0
23
24 [UIView animateWithDuration:0.25 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
25
26 view.y = - adjustY;
27 } completion:^(BOOL finished) {
28
29 }];
30 }else{
31 [UIView animateWithDuration:0.25 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
32 view.y = 0;
33 } completion:^(BOOL finished) {
34
35 }];
36 }
37
38
39 }
第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:
- (void)adjustTextFieldFrameWhenBeginEdtingWithView: keyBoardHeight:
1 #pragma YDTextFieldDelegate
2
3 - (void)textFieldDidBeginEditing:(UITextField *)textField
4 {
5 YDTextField *tf = (YDTextField *)textField;
6
7 __weak typeof(self) weakSelf = self;
8
9 // 定义block,等待keyboardWillShow:方法获取键盘高度后调用
10 self.editingBlock = ^(CGFloat keyboadHeight){
11
12 // 此处调用自定义textfield的自适应方法
13 [tf adjustTextFieldFrameWhenBeginEdtingWithView:weakSelf.view keyBoardHeight:keyboadHeight];
14
15 };
16
17 }
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代码:
控制器中代码:
1 //
2 // ViewController.m
3 // TextfieldDemo
4 //
5 // Created by heyode on 16/5/20.
6 // Copyright © 2016年 heyode. All rights reserved.
7 //
8
9 #import "ViewController.h"
10 #import "YDTextField.h"
11 #import "UIView+frame.h"
12 // 键盘和当前活动textfield的间距
13 #define MARGIN 15
14
15 //定义随机色
16 #define randomColor [UIColor colorWithRed:arc4random_uniform(256)/255.0 green:arc4random_uniform(256)/255.0 blue:arc4random_uniform(256)/255.0 alpha:1];
17
18 typedef void(^textFieldDidBeginEditingBlock)(CGFloat keyboadHeight);
19 #define BASECOUNT 30
20
21 @interface ViewController ()<UITableViewDelegate,UITableViewDataSource,UITextFieldDelegate>
22 /** tableView */
23 @property (nonatomic,weak) UITableView *tableView;
24
25 /** 数据源 */
26 @property (nonatomic,strong) NSMutableArray *datas;
27
28 /** block */
29 @property (nonatomic,copy) textFieldDidBeginEditingBlock editingBlock;
30
31
32 @end
33
34 @implementation ViewController
35
36 - (void)viewDidLoad {
37 [super viewDidLoad];
38
39 [self setUpDataSouce];
40 [self setUpTableView];
41
42 [self setUpNotification];
43 }
44
45 - (void)setUpNotification
46 {
47 //增加监听,当键盘出现或改变时收出消息
48 [[NSNotificationCenter defaultCenter] addObserver:self
49 selector:@selector(keyboardWillShow:)
50 name:UIKeyboardWillShowNotification
51 object:nil];
52
53 // 当键盘消失时响应
54 [[NSNotificationCenter defaultCenter] addObserver:self
55 selector:@selector(keyboardWillHide:)
56 name:UIKeyboardWillHideNotification object:nil];
57
58 }
59
60
61 // 当键盘消失时调用
62 - (void)keyboardWillHide:(NSNotification *)note
63 {
64 if ([note.name isEqualToString:UIKeyboardWillShowNotification]) {
65
66 }else{
67 [UIView animateWithDuration:0.25 animations:^{
68 self.view.y = 0;
69 } completion:^(BOOL finished) {
70
71 }];
72 }
73 }
74
75 //当键盘出现或改变时调用
76 - (void)keyboardWillShow:(NSNotification *)aNotification
77 {
78 //获取键盘的高度
79 NSDictionary *userInfo = [aNotification userInfo];
80 NSValue *aValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];
81 CGRect keyboardRect = [aValue CGRectValue];
82 CGFloat keyboadHeight = keyboardRect.size.height;
83
84 // 调用保存好的block并将键盘高度传入
85 self.editingBlock(keyboadHeight);
86 }
87
88 - (void)setUpTableView
89 {
90 UITableView *tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
91 tableView.delegate = self;
92 tableView.dataSource = self;
93 [self.view addSubview:tableView];
94
95 }
96
97
98 - (void)setUpDataSouce
99 {
100 self.datas = [NSMutableArray array];
101
102 for (int i = 0; i < 20; i++) {
103 NSString *str = [NSString stringWithFormat:@"%i",i];
104 [self.datas addObject:str];
105 }
106
107 }
108
109 #pragma UITableviewDatasouce
110 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
111 {
112 return self.datas.count;
113 }
114
115 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
116 {
117
118
119 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
120 if (cell == nil) {
121 cell = [[UITableViewCell alloc] initWithStyle:0 reuseIdentifier:@"cell"];
122 }
123
124
125 for (id view in cell.contentView.subviews) {
126 [(UIView *)view removeFromSuperview];
127 }
128
129
130 cell.textLabel.text = self.datas[indexPath.row];
131
132 YDTextField *tf = [[YDTextField alloc] initWithFrame:CGRectMake(50, (cell.height - cell.height - 2)/2, cell.width , cell.height - 2)];
133 tf.tag = indexPath.row + BASECOUNT;
134
135 tf.backgroundColor = randomColor;
136 tf.delegate = self;
137
138 [cell.contentView addSubview:tf];
139 return cell;
140 }
141
142 #pragma YDTextFieldDelegate
143
144 - (void)textFieldDidBeginEditing:(UITextField *)textField
145 {
146 YDTextField *tf = (YDTextField *)textField;
147
148 __weak typeof(self) weakSelf = self;
149
150 // 定义block,等待keyboardWillShow:方法获取键盘高度后调用
151 self.editingBlock = ^(CGFloat keyboadHeight){
152
153 // 此处调用自定义textfield的自适应方法
154 [tf adjustTextFieldFrameWhenBeginEdtingWithView:weakSelf.view keyBoardHeight:keyboadHeight];
155
156 };
157
158 }
159
160
161 @end
自定义textfield代码:
1 //
2 // YDTextField.m
3 // TextfieldDemo
4 //
5 // Created by heyode on 16/5/20.
6 // Copyright © 2016年 heyode. All rights reserved.
7 //
8
9 #import "YDTextField.h"
10 #import "UIView+frame.h"
11
12 // 键盘和当前活动textfield的间距
13 #define MARGIN 15
14
15 @interface YDTextField()
16 @property (weak, nonatomic) UIView *adjustView;
17 /**键盘高度 */
18 @property (nonatomic,assign) CGFloat keyboadHeight;
19
20 @end
21
22 @implementation YDTextField
23
24
25 - (instancetype)initWithFrame:(CGRect)frame
26 {
27 if (self = [super initWithFrame:frame]) {
28 [self initialize];
29
30 }
31 return self;
32 }
33
34 - (void)awakeFromNib
35 {
36
37 [self initialize];
38 }
39
40 - (void)layoutSubviews
41 {
42 [super layoutSubviews];
43 }
44
45 - (void)initialize
46 {
47
48 // 点击return时,结束编辑状态
49 [self addTarget:self action:@selector(endEditing:) forControlEvents:UIControlEventEditingDidEndOnExit];
50 }
51
52
53
54
55
56 - (void)adjustTextFieldFrameWhenBeginEdtingWithView:(UIView *)view keyBoardHeight:(CGFloat)keyboadHeight
57 {
58 // 将控制器view保存起来
59 self.adjustView = view;
60
61 // 将textfield的坐标转换到控制器view坐标系中
62 CGRect selfFrame = [self convertRect:self.bounds toView:view];
63
64 // 键盘的y值
65 CGFloat keyBoardY = 0;
66
67
68 keyBoardY = [UIScreen mainScreen].bounds.size.height - keyboadHeight ;
69
70
71
72 // 控制器view 要调整的高度
73 CGFloat adjustY = selfFrame.origin.y + selfFrame.size.height + MARGIN - keyBoardY;
74
75
76
77 if (adjustY > 0) { // 调整高度大于0
78
79 [UIView animateWithDuration:0.25 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
80
81 view.y = - adjustY;
82 } completion:^(BOOL finished) {
83
84 }];
85 }else{
86 [UIView animateWithDuration:0.25 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
87 view.y = 0;
88 } completion:^(BOOL finished) {
89
90 }];
91 }
92
93
94 }
95
96
97
98
99
100 @end