引入类别解决所有键盘遮挡输入框的问题(iOS Object-C)
实现过程解析:
1.在ios中输入控件是UITextView和UITextField,那么要如何解决输入控件被被键盘遮挡呢?
答:那当然是要监听键盘的弹出和隐藏(用通知),然后改变输入框的位置。
2.第一个问题的答案可知,在不viewController或者view里都要做键盘的监听和计算输入框的位置好麻烦有没有统一的解决方法呢?
答:当然是有的;通过查看UITextView和UITextField的相关信息可以发现UIResponder是他们的superClass,同时UIResponder没有实现init方法(实现继承时要注意不能破坏UIResponder与其他类的继承关系),我们可以创建一个UIResponder的类别文件实现他的init方法在里面加入监听(当你初始化UITextView和UITextField对象时程序会调用UIResponder类别文件的init方法),从而可以在类别里统一处理键盘弹出和隐藏时输入框的位置。代码如下:
3.在一个界面上输入框有可能是在tableView上也有可能是在其他view上能不能有统一的方法计算输入框的位置?
答:解决方法是有的,那就是吧所有的输入框的位置都转移到一个统一的参考对象来处理。
4.参考对象选谁呢?
答:我们都知道没每一个app都有一个mianWindow,你的view要能显示给用户必须是直接或间接的加在mianWindow上,所以参考系当然是选mianWindow;如下代码
只要引入该类别就可以实现防止键盘遮挡。
项目链接:https://files.cnblogs.com/files/3yangyue3/引入类别解决所有键盘遮挡输入框问题%28UIResponder加YYResponder%29.zip
完整代码如下:
头文件:
#import <UIKit/UIKit.h>
@interface UIResponder (YYResponder)
@end
实现文件:
#import "UIResponder+YYResponder.h"
#import <objc/runtime.h>
static CGRect initFrame;
static UIButton *endButton=nil;
#define MainWindow [[UIApplication sharedApplication].delegate window]
#define IsEvent [self isMemberOfClass:[UITextField class]]||[self isMemberOfClass:[UITextView class]]
@implementation UIResponder (YYResponder)
/**
实现UIResponder
**/
-(instancetype)init
{
if (self=[super init])
{
[self registerKeyboardManagement];//注册键盘的监听
}
return self;
}
#pragma mark - ============ 其他 ============
/**
注册键盘的监听
**/
-(void)registerKeyboardManagement
{
if (IsEvent)
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardNotificationAction:) name:UIKeyboardWillHideNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardNotificationAction:) name:UIKeyboardWillShowNotification object:nil];
}
}
-(void)dealloc
{
if (IsEvent)
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
}
}
#pragma mark - ============ 给类触发事件 ============
#pragma mark - 键盘通知
- (void)keyboardNotificationAction:(NSNotification *)notification
{
if (!self.isFirstResponder)
{
}
else
{
if ([notification.name isEqualToString:UIKeyboardWillHideNotification])
{
UIView *view =[MainWindow.subviews objectAtIndex:0];
NSValue *value =[NSValue valueWithCGRect:initFrame];
if (!([value isEqualToValue:[NSValue valueWithCGRect:CGRectNull]]||[value isEqualToValue:[NSValue valueWithCGRect:CGRectZero]]))
{
view.frame=initFrame;
initFrame=CGRectZero;
}
[endButton removeFromSuperview];
MainWindow.backgroundColor=[UIColor clearColor];
}
else if ([notification.name isEqualToString:UIKeyboardWillShowNotification])
{
CGRect keyboardFrame = ((NSValue *) notification.userInfo[UIKeyboardFrameEndUserInfoKey]).CGRectValue;
UIView *sfView=(UIView*)self;
/**
计算输入框相对于MainWindow的位置
**/
CGRect rect =[MainWindow convertRect:sfView.frame fromView:sfView.superview];
CGFloat y=rect.origin.y+rect.size.height-keyboardFrame.origin.y;
UIView *view =[MainWindow.subviews objectAtIndex:0];
NSValue *value =[NSValue valueWithCGRect:initFrame];
if ([value isEqualToValue:[NSValue valueWithCGRect:CGRectNull]]||[value isEqualToValue:[NSValue valueWithCGRect:CGRectZero]])
{
initFrame=view.frame;
}
if (!endButton)
{
endButton=[UIButton buttonWithType:UIButtonTypeSystem];
endButton.frame=CGRectMake(keyboardFrame.size.width-69, keyboardFrame.origin.y-22, 64, 22);
endButton.contentHorizontalAlignment=UIControlContentHorizontalAlignmentRight;
[endButton setTitle:@"结束编辑" forState:UIControlStateNormal];
endButton.titleLabel.font=[UIFont systemFontOfSize:15.0f];
[endButton addTarget:MainWindow action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];
}
[MainWindow addSubview:endButton];
MainWindow.backgroundColor=[UIColor whiteColor];
if (y>0)
{
view.frame=CGRectMake(view.frame.origin.x, view.frame.origin.y-y-endButton.frame.size.height, view.frame.size.width, view.frame.size.height);
}
}
}
}
#pragma mark - buttonAction
-(void)buttonAction:(UIButton *)sender
{
[MainWindow endEditing:YES];
}
@end