iOS避免键盘遮挡输入方案

项目中经常会遇到这样的问题:一个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: 

 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: 

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

 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
原文地址:https://www.cnblogs.com/heyode/p/5511435.html