iOS常用

iOS键盘处理(第三方&键盘通知)

2020-06-25  本文已影响0人  苦笑男神

1.前言

关于键盘,很多时候都是用的IQKeyboardManager这个第三方库,但是有时候一些页面可能真需要自己特殊处理一下。

https://github.com/hackiftekhar/IQKeyboardManager

这里记录一下今天处理键盘的过程,遇到的问题有:

2.代码研究

首先.h所需的一个属性

/// 当是第三方键盘时,用于通知的计数 (第三方键盘在弹出时,会调用多次通知)
@property (nonatomic ,assign) NSInteger KeyboardIndex;
/// 输入控件
@property (nonatomic, weak) UITextView *textView;

注册键盘的通知

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardAction:) name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardAction:) name:UIKeyboardWillHideNotification object:nil];
}
- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

键盘的通知代码:

- (void)keyboardAction:(NSNotification *)notification {
    NSTimeInterval duration = [[notification.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    duration = duration == 0 ? 0.3 : duration;
    
    __weak __typeof(&*self)weakSelf = self;
    
    // 键盘将要弹出
    if ([notification.name isEqual:UIKeyboardWillShowNotification]) {
        
        CGRect frame = [[notification.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
        
        // 不是第三方键盘,第三方键盘第一次通知里面的frame里面的height是0
        if (frame.size.height > 0 && self.KeyboardIndex == 0) {
            [self keyboardWillShow:frame duration:duration];
            return;
        }
        
        self.KeyboardIndex++;
        
        NSInteger count = 3;  // 因为`KeyboardIndex`从0开始的,所以这里其实是 4 次通知
        if (self.textView.inputAccessoryView == nil) {
            count = 2;  // 因为`KeyboardIndex`从0开始的,所以这里其实是 3 次通知
        }
        
        // 第三方键盘,会有多次`UIKeyboardWillShowNotification`,只用最后一次
        if (self.KeyboardIndex <= count) return;
        
        [self keyboardWillShow:frame duration:duration];
        self.KeyboardIndex = 0;
    }
    
    if ([notification.name isEqual:UIKeyboardWillHideNotification]) {
        // 键盘将要收回,这想加不加判断都一样,因为Translation(0, 0) 本身就没有发生transform
        [UIView animateWithDuration:duration animations:^{
            weakSelf.contentView.transform = CGAffineTransformMakeTranslation(0, 0);
        }];
    }
}

上面调用了一个方法[self keyboardWillShow:duration:]代码是:

/// View在做`transform`动画,或者改变`transform`时,Frame值会跟着改变.
static CGRect staticFrame;

/// 键盘弹出
- (void)keyboardWillShow:(CGRect)keyboardFrame duration:(NSTimeInterval)duration {
 
    if (CGRectIsEmpty(staticFrame) || CGRectIsNaN(staticFrame) || CGRectIsNull(staticFrame)) {
        staticFrame = self.contentView.frame;
    }
    
    // 加10是为了有5.0个距离差,不想加也可以的。
    CGFloat maxY = CGRectGetMaxY(staticFrame) + 5.0;
    
    if (maxY < keyboardFrame.origin.y) return;
    
    CGFloat h = maxY - keyboardFrame.origin.y;
    [self.contentView.layer removeAllAnimations];  // 原生键盘也会有多次通知的情况,这里重置状态,方法可能会执行多次
    self.contentView.transform = CGAffineTransformIdentity;
    
    [UIView animateWithDuration:duration animations:^{
        self.contentView.transform = CGAffineTransformMakeTranslation(0, -h);
    }];
}

3.偷懒的可能性

上面的代码看着都有点头疼,那么多情况,不同的机型&键盘&iOS系统,谁知道会不会有特殊情况,所以,如果你不介意页面可能的跳动,直接copy下面这种方式就行:

键盘的通知代码:

- (void)keyboardAction:(NSNotification *)notification {
    NSTimeInterval duration = [[notification.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    duration = duration == 0 ? 0.3 : duration;
    
    __weak __typeof(&*self)weakSelf = self;
    
    if ([notification.name isEqual:UIKeyboardWillShowNotification]) {
        CGRect frame = [[notification.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
        [self keyboardWillShow:frame duration:duration];
        return;
    }
    
    if ([notification.name isEqual:UIKeyboardWillHideNotification]) {
        // 键盘将要收回,这想加不加判断都一样,因为Translation(0, 0) 本身就没有发生transform
        [UIView animateWithDuration:duration animations:^{
            weakSelf.contentView.transform = CGAffineTransformMakeTranslation(0, 0);
        }];
    }
}

/// View在做`transform`动画,或者改变`transform`时,Frame值会跟着改变.
static CGRect staticFrame;

/// 键盘弹出
- (void)keyboardWillShow:(CGRect)keyboardFrame duration:(NSTimeInterval)duration { 
    if (CGRectIsEmpty(staticFrame) || CGRectIsNaN(staticFrame) || CGRectIsNull(staticFrame)) {
        staticFrame = self.contentView.frame;
    }
    
    // 加10是为了有5.0个距离差,不想加也可以的。
    CGFloat maxY = CGRectGetMaxY(staticFrame) + 5.0;
    
    if (maxY < keyboardFrame.origin.y) return;
    
    CGFloat h = maxY - keyboardFrame.origin.y;
    [self.contentView.layer removeAllAnimations];  // 键盘有多次通知的情况,这里重置状态,方法可能会执行多次
    self.contentView.transform = CGAffineTransformIdentity;
    
    [UIView animateWithDuration:duration animations:^{
        self.contentView.transform = CGAffineTransformMakeTranslation(0, -h);
    }];
}

-- End ---

PS:最近我有跳槽的想法,有工作机会的老板,欢迎骚扰哦!北京呦!

END。
我是小侯爷。
在帝都艰苦奋斗,白天是上班族,晚上是知识服务工作者。
如果读完觉得有收获的话,记得关注和点赞哦。
非要打赏的话,我也是不会拒绝的。

上一篇下一篇

猜你喜欢

热点阅读