永久解决UITextField键盘遮挡事件-JVTextFiel
2017-03-29 本文已影响90人
JarvanZhang
前言
再iOS的开发中,很多时候我们都需要解决TextField的键盘遮挡事件,每次都需要花时间,我们可以使用第三方库来解决,但第三方库很多代码质量参差不齐,而且代码量庞大。本文来分享一个代码量比较小的,有关键注释并且使用简单的JVTextField,你也可以依葫芦画瓢写一个你自己的,后期可以维护的控件。希望本文能帮助到你
代码在Github
使用方法
拷贝文件到你的工程 JVshowKeyboardManger JVTextField
使用JVTextField 代替 UITextField
指定要移动的moveViewself.textField.moveView=self.view;
跳转到下个页面之前要关闭键盘 重点
- (IBAction)pushNextViewController:(UIButton *)sender {
// 跳转到下一页之前 要关闭键盘,不然出现 keyboardToolBar不能隐藏的问题
[self.view endEditing:YES];
UIViewController *vc=[[UIViewController alloc]init];
vc.view.backgroundColor=[UIColor greenColor];
[self.navigationController pushViewController:vc animated:YES];
}
关键代码
主要由两个类组成
JVTextField : UITextField
JVshowKeyboardManger : NSObject
JVTextField.h
@interface JVTextField : UITextField
/**提供需要移动View层,本质上是可以移动main Window ,但为了个性化的需求,提供配置
*/
@property(nonatomic,weak)UIView* moveView;
@end
JVTextField.m
提供初始化方法
-(instancetype)initWithFrame:(CGRect)frame{
self=[super initWithFrame:frame];
[self Initialize];
return self;
}
-(instancetype)init{
self=[super init];
[self Initialize];
return self;
}
-(void)awakeFromNib{
[super awakeFromNib];
[self Initialize];
}
初始化添加通知
#pragma -mark 初始化
-(void)Initialize{
[self addTarget:self action:@selector(addKeyboardNotification) forControlEvents:UIControlEventEditingDidBegin];
[self addTarget:self action:@selector(removeKeyboardNotification) forControlEvents:UIControlEventEditingDidEnd];
}
#pragma -mark添加通知 由单独的一个类来完成
-(void)addKeyboardNotification{
[JVshowKeyboardManger addNotificationWithTextFiled:self];
}
#pragma -mark 移除通知
-(void)removeKeyboardNotification{
[JVshowKeyboardManger removeNotificationWithTextFiled:self];
}
JVshowKeyboardManger.h 提供接口
@interface JVshowKeyboardManger : NSObject
+(instancetype)shareClass;
/**添加通知*/
+(void)addNotificationWithTextFiled:(JVTextField*)textFiled;
/**移除通知*/
+(void)removeNotificationWithTextFiled:(JVTextField*)textFiled;
@end
JVshowKeyboardManger.m 提供实现
内部属性和宏定义
#define JVScreen_Width [UIScreen mainScreen].bounds.size.width
#define JVScreen_Height [UIScreen mainScreen].bounds.size.height
#define JVColor(R, G, B, A) [UIColor colorWithRed:R/255.0 green:G/255.0 blue:B/255.0 alpha:A]
static JVshowKeyboardManger *_sharedClass;
@interface JVshowKeyboardManger()
//为键盘添加一个完成按钮来关闭键盘
@property(strong,nonatomic)UIView* keyboardToolbar;
//moveView 在window中的 rect.origin.y
@property(assign,nonatomic) CGFloat viewY;
// 传递对象 for 遮挡键盘 处理
@property(nonatomic,weak)JVTextField* textFiled;
@end
keyboardToolbar懒加载
-(UIView *)keyboardToolbar{
if (!_keyboardToolbar) {
_keyboardToolbar=[[UIView alloc]initWithFrame:CGRectMake(0, JVScreen_Height, JVScreen_Width, 40)];
_keyboardToolbar.backgroundColor=JVColor(208, 213, 218, 1.0);
UIButton* complateBtn=[[UIButton alloc]initWithFrame:CGRectMake(JVScreen_Width-35-10, 0, 35, 40)];
[complateBtn setTitle:@"完成" forState:0];
[complateBtn setTitleColor:[UIColor blueColor] forState:0];
complateBtn.titleLabel.font=[UIFont systemFontOfSize:14.f];
[complateBtn addTarget:self action:@selector(closeTheKeyboard)forControlEvents:UIControlEventTouchUpInside];
[_keyboardToolbar addSubview:complateBtn];
NSEnumerator *frontToBackWindows = [UIApplication.sharedApplication.windows reverseObjectEnumerator];
for (UIWindow *window in frontToBackWindows){
BOOL windowOnMainScreen = window.screen == UIScreen.mainScreen;
BOOL windowIsVisible = !window.hidden && window.alpha > 0;
BOOL windowLevelNormal = window.windowLevel == UIWindowLevelNormal;
if (windowOnMainScreen && windowIsVisible && windowLevelNormal) {
[window addSubview:_keyboardToolbar];
break;
}
}
_keyboardToolbar.alpha=0;
}
return _keyboardToolbar;
}
创建单例
+(instancetype)shareClass{
static dispatch_once_t token;
dispatch_once(&token,^{
_sharedClass = [[JVshowKeyboardManger alloc] init];
});
return _sharedClass;
}
添加通知
//添加通知
+(void)addNotificationWithTextFiled:(JVTextField*)textFiled{
JVshowKeyboardManger* thisObject=[JVshowKeyboardManger shareClass];
thisObject.textFiled=textFiled;
//计算 moveView 在window中的 rect.origin.y
thisObject.viewY=[thisObject relativeFrameForScreenWithView:thisObject.textFiled].origin.y;
[thisObject addKeyboardNotification];
}
//移除通知
+(void)removeNotificationWithTextFiled:(JVTextField*)textFiled{
JVshowKeyboardManger* thisObject=[JVshowKeyboardManger shareClass];
[thisObject removeNotification];
}
辅助方法
#pragma -mark 计算moveview 在 window中的 rect
-(CGRect)relativeFrameForScreenWithView:(UIView *)v
{
UIView *view = v;
CGFloat x = .0;
CGFloat y = .0;
// root uiwindow superView ==nil
while ([view superview])
{
x += view.frame.origin.x;
y += view.frame.origin.y;
view = view.superview;
if ([view isKindOfClass:[UIScrollView class]]) {
x -= ((UIScrollView *) view).contentOffset.x;
y -= ((UIScrollView *) view).contentOffset.y;
}
}
return CGRectMake(x, y, v.frame.size.width, v.frame.size.height);
}
#pragma -mark添加通知
-(void)addKeyboardNotification{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
}
#pragma -mark 移除通知
-(void)removeNotification{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
处理键盘显示和隐藏
#pragma -mark 键盘显示时
- (void)keyboardWillShow:(NSNotification *)notif {
if (self.textFiled==nil||self.textFiled.moveView==nil) return;
CGSize kbSize = [[notif.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;//得到鍵盤的高度
CGFloat kbHeight = kbSize.height;
CGFloat viewY=self.viewY;
CGFloat viewMaxY=viewY+self.textFiled.frame.size.height;
CGFloat moveY=viewMaxY+kbHeight-[UIScreen mainScreen].bounds.size.height+40;
if (moveY>0) {
self.textFiled.moveView.bounds=CGRectMake(0, moveY, self.textFiled.moveView.frame.size.width, self.textFiled.moveView.frame.size.height);
}
self.keyboardToolbar.alpha=1;
self.keyboardToolbar.frame=CGRectMake(self.keyboardToolbar.frame.origin.x, JVScreen_Height-kbHeight-40, self.keyboardToolbar.frame.size.width, self.keyboardToolbar.frame.size.height);
}
#pragma -mark 键盘隐藏
- (void)keyboardWillHide:(NSNotification *)notif {
self.keyboardToolbar.alpha=0;
[UIView animateWithDuration:0.25 animations:^{
self.textFiled.moveView.bounds=CGRectMake(0, 0, self.textFiled.moveView.frame.size.width, self.textFiled.moveView.frame.size.height);
self.keyboardToolbar.frame=CGRectMake(self.keyboardToolbar.frame.origin.x, JVScreen_Height, self.keyboardToolbar.frame.size.width, self.keyboardToolbar.frame.size.height);
}completion:^(BOOL finished) {
}];
}
点击关闭事件
#pragma -mark 点击关闭键盘
-(void)closeTheKeyboard{
[[[UIApplication sharedApplication] keyWindow] endEditing:YES];
}
结束语
是不是很简单呢,你也可以实现一个textView的版本,限于篇幅,本文不在续写