ios --鍵盤監聽JYKeyBoardListener

 

沒有前言,就是一個簡單的鍵盤監聽,自動調整輸入框的位置不被鍵盤遮擋async

 


 

.hide

//
//  JYKeyBoardListener.h
//
//  Created by JianF.Sun on 17/9/26.
//  Copyright © 2017年 sjf. All rights reserved.
//
/*
 功能:
 一、輸入框被鍵盤遮擋時,整個view上移(此時輸入框在鍵盤上方)
 二、鍵盤彈出時,添加一個按鈕負責隱藏鍵盤
 三、禁止某控制器使用JYKeyBoardListener
 使用:
 一、引入JYKeyBoardListener.h
 二、程序啓動時:[JYKeyBoardListener useJYKeyboardListener];
 三、某些控制器不想使用時:[JYKeyBoardListener unUsedIn:vc];
 處理:
 一、監聽鍵盤 顯示,隱藏,退到後臺,進入前臺;
 二、獲取當前頂層控制器;
 三、獲取當前編輯的輸入框在self.view中的frame;
 四、鍵盤顯示隱藏時動畫;
 五、隱藏鍵盤的按鈕添加
 六、處理push、present時鍵盤的顯示隱藏問題(切記push以前,代碼endEditing,由於push操做系統不會自動退出鍵盤)
 七、處理self.view比屏幕小的問題(即self.view沒有伸縮到導航欄底部)
 八、處理輸入框顯示在屏幕中不完整的狀況
 
 */
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface JYKeyBoardListener : NSObject
//程序啓動時調用
+ (void)useJYKeyboardListener;
//在viewcontroller中禁止使用JYKeyBoardListener
+ (void)unUsedIn:(UIViewController*)viewController;
@end

.m動畫

//
//  JYKeyBoardListener.m
//
//  Created by JianF.Sun on 17/9/26.
//  Copyright © 2017年 sjf. All rights reserved.
//

#import "JYKeyBoardListener.h"

#define KBL_Screen_Height [UIScreen mainScreen].bounds.size.height

NSString * const JYKeyboard_Unused_Key= @"JYKeyboard_Unused_Key";

@interface JYKeyBoardListener ()
@property (nonatomic,strong) UIView *inputView;
@property (nonatomic,strong) UIButton *resignBtn;
@property (nonatomic,strong) UIView *lastView;//記錄以前一個須要處理的view,解決push,present操做時,鍵盤的隱藏問題
//@property (nonatomic,strong) UIViewController *unUsedVC;

@end
@implementation JYKeyBoardListener

#pragma mark - 接口方法,直接調用便可
+ (void)useJYKeyboardListener{
    
    [JYKeyBoardListener shareJYKeyBoardListener];
}
+ (void)unUsedIn:(UIViewController*)viewController{
    
    JYKeyBoardListener *manager = [JYKeyBoardListener shareJYKeyBoardListener];
    [[NSUserDefaults standardUserDefaults] setValue:[manager getMemory:viewController] forKey:JYKeyboard_Unused_Key];
}

#pragma mark - 單例

+ (instancetype)shareJYKeyBoardListener {
    
    static JYKeyBoardListener *jyKeyBoardListener = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        jyKeyBoardListener = [[JYKeyBoardListener alloc] init];
        // 監聽鍵盤

        [[NSNotificationCenter defaultCenter] addObserver:jyKeyBoardListener selector:@selector(keyboardWillShowAction:) name:UIKeyboardWillShowNotification object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:jyKeyBoardListener selector:@selector(keyboardWillHideAction:) name:UIKeyboardWillHideNotification object:nil];
        
        [[NSNotificationCenter defaultCenter] addObserver:jyKeyBoardListener selector:@selector(enterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil];
        [[NSNotificationCenter defaultCenter] addObserver:jyKeyBoardListener selector:@selector(enterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil];
    });
    
    return jyKeyBoardListener;
}


#pragma mark - 鍵盤顯示和隱藏的監聽方法
/**
 *  鍵盤即將彈出
 */
- (void)keyboardWillShowAction:(NSNotification *)note{
    
    if ([self currentMemory]!=nil&&[[self currentMemory] isEqualToString:[self getMemory:[self topViewController]]]) {
        [self addResignBtn:[self topViewController].view];
        return;
    }else{
        [[NSUserDefaults standardUserDefaults] setValue:nil forKey:JYKeyboard_Unused_Key];
    }
    
    //結束時鍵盤的frame
    CGRect endF = [note.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    //鍵盤高度
    CGFloat keyboardH = endF.size.height;
    //鍵盤彈出須要的時間
    CGFloat duration = [note.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    //當前的view
    UIView *firstRspView = [self findFirstResponsderView];
    
    if (firstRspView==nil) {
        //        NSLog(@"爲空");
        return ;
    }
    //找到輸入框
    [self findSubView:firstRspView];

    //獲取輸入框相對於當前展現的最底層的那個view的frame
    CGRect inputFrame = [self getAbsoluteFrame:self.inputView];
    //
    CGFloat difH = CGRectGetMaxY(inputFrame)-(KBL_Screen_Height-keyboardH);
    // 2.動畫
    [UIView animateWithDuration:duration animations:^{
        
        if (difH>0) {
            
            firstRspView.transform = CGAffineTransformMakeTranslation(0,-difH);
            
        }else{
            firstRspView.transform = CGAffineTransformIdentity;
            
        }
        _lastView = firstRspView;
    }completion:^(BOOL finished) {
        [self addResignBtn:firstRspView];

    } ];
}
/**
 *  鍵盤即將隱藏
 */
- (void)keyboardWillHideAction:(NSNotification *)note{
    
    //判斷當前控制器是否被禁用
    if ([self currentMemory]!=nil&&[[self currentMemory] isEqualToString:[self getMemory:[self topViewController]]]) {
        
        return;
    }else{
        [[NSUserDefaults standardUserDefaults] setValue:nil forKey:JYKeyboard_Unused_Key];
    }
    // 1.鍵盤彈出須要的時間
    CGFloat duration = [note.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    UIView *firstRspView = [self findFirstResponsderView];

    if(firstRspView==nil){
        return;
    }
    if (_lastView&&_lastView!=firstRspView) {//處理跳轉時恢復以前的,push以前必須

        _lastView.transform = CGAffineTransformIdentity;
        _lastView = nil;
        return;
    }
    // 2.動畫
    [UIView animateWithDuration:duration animations:^{
        firstRspView.transform = CGAffineTransformIdentity;
        
    }completion:^(BOOL finished) {

    }];

}


#pragma mark - 前臺後臺切換處理
- (void)enterBackground:(NSNotification*)note{
    [[self findFirstResponsderView] endEditing:YES];
}
- (void)enterForeground:(NSNotification*)note{
    
}
#pragma mark - 隱藏鍵盤按鈕
- (void)addResignBtn:(UIView*)firstRspView{
    if (self.resignBtn) {
        [self.resignBtn removeFromSuperview];
    }
    self.resignBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    self.resignBtn.backgroundColor = [UIColor clearColor];
    [self.resignBtn addTarget:self action:@selector(hideKeyboard) forControlEvents:UIControlEventTouchUpInside];
    self.resignBtn.frame = firstRspView.bounds;
    [firstRspView addSubview:self.resignBtn];
    [firstRspView sendSubviewToBack:self.resignBtn];
}
- (void)hideKeyboard{
    [[self findFirstResponsderView] endEditing:YES];
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.resignBtn removeFromSuperview];

    });
}
#pragma mark - 其餘輔助性方法
/**
 查找根控制器的view

 @return return FirstResponsderView
 */
- (UIView*)findFirstResponsderView{
    
    UIViewController *returnVC;
    
    //查找當前的根控制器
    returnVC = [self topViewController];
    if (returnVC) {
        return returnVC.view;
    }else{
        return nil;
    }
}
// 獲取當前屏幕顯示的ViewController
- (UIViewController *)topViewController {
    UIViewController *resultVC;
    resultVC = [self _topViewController:[[UIApplication sharedApplication].keyWindow rootViewController]];
    while (resultVC.presentedViewController) {
        resultVC = [self _topViewController:resultVC.presentedViewController];
    }
    return resultVC;
}

- (UIViewController *)_topViewController:(UIViewController *)vc {
    if ([vc isKindOfClass:[UINavigationController class]]) {
        return [self _topViewController:[(UINavigationController *)vc topViewController]];
    } else if ([vc isKindOfClass:[UITabBarController class]]) {
        return [self _topViewController:[(UITabBarController *)vc selectedViewController]];
    } else {
        return vc;
    }
    return nil;
}


/*
 獲取輸入框的相對於根控制器view的frame
 */
- (CGRect)getAbsoluteFrame:(UIView*)view{
    
    UIView *mainView = [self findFirstResponsderView];
    UIWindow *window = [UIApplication sharedApplication].keyWindow;
    CGRect rect=[view convertRect: view.bounds toView:mainView];
    //處理導航欄問題
    if (CGRectGetHeight(mainView.bounds)<CGRectGetHeight(window.bounds)) {
        rect.origin.y += CGRectGetHeight(window.bounds)-CGRectGetHeight(mainView.bounds);
    }
    //滾動視圖返回的frame去掉scrollView.contentOffset.y
    if ([mainView isKindOfClass:[UIScrollView class]]||[mainView isKindOfClass:[UITableView class]]||[mainView isKindOfClass:[UIWebView class]]) {
        UIScrollView *scrollView = (UIScrollView*)mainView;
        rect.origin.y -=scrollView.contentOffset.y;
        if (CGRectGetMaxY(rect)>KBL_Screen_Height) {//輸入框沒有徹底顯示出來
            
            //去掉屏幕外的高度值
            rect.origin.y-=CGRectGetMaxY(rect)-KBL_Screen_Height;
        }
    }
    
    return rect;
}

/*
 遞歸法
 找到輸入框
 */
- (void)findSubView:(UIView*)view{
    
    for (UIView *subView in view.subviews){

        if ([subView isFirstResponder]) {
//            NSLog(@"找到輸入框");
            self.inputView = subView;
        }else{
            [self findSubView:subView];
        }
    }
}


- (NSString*)getMemory:(UIViewController*)vc{
    //控制器名稱+內容的內存地址+view的內容地址
    return [NSString stringWithFormat:@"jykeyboard%@%p%p",NSStringFromClass([vc class]),vc,vc.view];
}
- (NSString*)currentMemory{
    return [[NSUserDefaults standardUserDefaults] valueForKey:JYKeyboard_Unused_Key];
}
@end
相關文章
相關標籤/搜索