zoukankan      html  css  js  c++  java
  • iOS 处理键盘遮挡TextField、TextView问题

      之前处理键盘遮挡问题都是在每一个控制器进行单独处理,这样做真的是非常的费事,今天在做项目的时候就想到自己封装一个,记录一下这个“跌宕起伏”的过程。

      思路是这样的:计算文本编辑控件Frame与键盘Frame,如果遮挡则移动控制器View。

      创建控制器类:WKAvoidKeyboardViewController

      

     1 #import <UIKit/UIKit.h>
     2 
     3 @interface WKAvoidKeyboardViewController : UIViewController
     4 
     5 @property (nonatomic, strong) UITextField *editTextField;
     6 @property (nonatomic, strong) UITextView *editTextView;
     7 
     8 - (void)hideKeyboard:(NSNotification *)noti;
     9 - (void)showKeyboard:(NSNotification *)noti;
    10 
    11 
    12 @end
    13 
    14 
    15 #import "WKAvoidKeyboardViewController.h"
    16 
    17 #define GetOSVersion [[UIDevice currentDevice].systemVersion floatValue]
    18 
    19 #define GetTransformDistance(Distance) (GetOSVersion < 7.1 ? Distance / 2 : Distance)
    20 
    21 @interface WKAvoidKeyboardViewController ()<UITextFieldDelegate, UITextViewDelegate>
    22 
    23 @end
    24 
    25 @implementation WKAvoidKeyboardViewController
    26 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    27 {
    28     [self.view endEditing:YES];
    29 }
    30 @end

      步骤1:通过通知获取当前编辑的文本控件

    //注册通知
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(showKeyboard:) name:UIKeyboardWillShowNotification object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(hideKeyboard:) name:UIKeyboardWillHideNotification object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textFieldBeginEditing:) name:UITextFieldTextDidBeginEditingNotification object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textFieldBeginEditing:) name:UITextViewTextDidBeginEditingNotification object:nil];
    - (void)textFieldBeginEditing:(NSNotification *)noti
    {
        self.editTextField = noti.object;
        self.editTextView = nil; 
    }
    - (void)textViewBeginEditing:(NSNotification *)noti
    {
        self.editTextView = noti.object;
        self.editTextField = nil;
    }

      步骤2:通知获取键盘高度

      步骤3:计算是否需要移动

      

    #pragma mark - 键盘躲避
    
    - (void)showKeyboard:(NSNotification *)noti
    {
        self.view.transform = CGAffineTransformIdentity;
        UIView *editView = _editTextView ? _editTextView : _editTextField;
        
        CGRect tfRect = [editView.superview convertRect:editView.frame toView:self.view];
        NSValue *value = noti.userInfo[@"UIKeyboardFrameEndUserInfoKey"];
        NSLog(@"%@", value);
        CGRect keyBoardF = [value CGRectValue];
        
        CGFloat animationTime = [noti.userInfo[@"UIKeyboardAnimationDurationUserInfoKey"] floatValue];
        CGFloat _editMaxY = CGRectGetMaxY(tfRect);
        CGFloat _keyBoardMinY = CGRectGetMinY(keyBoardF);
        NSLog(@"%f %f", _editMaxY, _keyBoardMinY);
        if (_keyBoardMinY < _editMaxY) {
            CGFloat moveDistance = _editMaxY - _keyBoardMinY;
            [UIView animateWithDuration:animationTime animations:^{
                self.view.transform = CGAffineTransformTranslate(self.view.transform, 0, -moveDistance);
            }];
            
        }
    }
    
    - (void)hideKeyboard:(NSNotification *)noti
    {
        //    NSLog(@"%@", noti);
        self.view.transform = CGAffineTransformIdentity;
    }

      初步试验:UITextFiled成功,然后到了UITextView,坑爹的问题粗线了=.=, UITextViewTextDidBeginEditingNotification 发送时间是在键盘弹出通知之后的,导致第一次点击TextView没有用,点击第二次才能产生效果。于是乎,我又开始尝试用TextView的Delegate来做,想当然的使用的代理方法

    - (void)textViewDidBeginEditing:(UITextView *)textView

    1 - (void)textViewDidBeginEditing:(UITextView *)textView
    2 {
    3     
    4 }

      令人失望的是textViewDidBeginEditing:方法调用依然是在键盘通知弹出后再调用,此时心中想的是:哔了狗了,让人怎么玩!还是看看其他方法吧。于是在代理方法中看到了

    - (BOOL)textViewShouldBeginEditing:(UITextView *)textView

      尝试之后,此方法的确在键盘弹出前调用,大功告成,接下来就是设置代理的问题了

      设置代理方法如下:

     1 - (void)searchTextViewWithView:(UIView *)view
     2 {
     3     for (UIView *subview in view.subviews)
     4     {
     5         if ([subview isKindOfClass:[UITextView class]]) {
     6             ((UITextView *)subview).delegate = self;
     7         }
     8         if ([subview isKindOfClass:[UITextField class]]) {
     9             ((UITextField *)subview).delegate = self;
    10         }
    11         [self searchTextViewWithView:subview];
    12     }
    13 }

      至此大功告成,使用方法:继承WKAvoidKeyboardViewController,如果是用故事版创建的文本控件,啥都不用做,如果是用代码创建的,则需要在ViewDidLoad中调用searchTextViewWithView方法

      完整代码下载地址:https://github.com/WuKongCoo1/AvoidKeyboardDemo.git

  • 相关阅读:
    懒加载与预加载
    Javascript之 Ajax 与 JSON
    Q&A:为什么prototype中的方法不能赋值给变量,再调用?
    Javascript之 浅克隆 与 深克隆
    Javascript之 __proto__ 与 prototype
    React入门(二)—— Props属性
    React入门(一)—— State属性
    Flask调用layer-iframe后,如何从服务器端关闭弹出窗
    Python从入门到项目实践(明日科技 吉林大学出版社)
    从实例到数理来解析感知机学习算法(PLA)
  • 原文地址:https://www.cnblogs.com/pretty-guy/p/4794002.html
Copyright © 2011-2022 走看看