• 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
  • 相关阅读:
    eclipse历史版本下载地址
    注解@SuppressWarnings
    VB创建文件夹
    VB学习生成JavaBean
    C++下的强制转换类型
    Django扩展
    数据查询操作
    深入剖析C++多态、VPTR指针、虚函数表
    快速排序一步一步优化
    cookie与session
  • 原文地址:https://www.cnblogs.com/heyode/p/5511435.html
Copyright © 2020-2023  润新知