转载

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

正文到此结束
Loading...