美文网首页IT部落程序员iOS Developer
永久解决UITextField键盘遮挡事件-JVTextFiel

永久解决UITextField键盘遮挡事件-JVTextFiel

作者: JarvanZhang | 来源:发表于2017-03-29 11:10 被阅读90次

    前言

    再iOS的开发中,很多时候我们都需要解决TextField的键盘遮挡事件,每次都需要花时间,我们可以使用第三方库来解决,但第三方库很多代码质量参差不齐,而且代码量庞大。本文来分享一个代码量比较小的,有关键注释并且使用简单的JVTextField,你也可以依葫芦画瓢写一个你自己的,后期可以维护的控件。希望本文能帮助到你
    代码在Github

    截屏.gif

    使用方法

    拷贝文件到你的工程 JVshowKeyboardManger JVTextField
    使用JVTextField 代替 UITextField
    指定要移动的moveView self.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的版本,限于篇幅,本文不在续写

    相关文章

      网友评论

        本文标题:永久解决UITextField键盘遮挡事件-JVTextFiel

        本文链接:https://www.haomeiwen.com/subject/tsceottx.html