iOS键盘弹出时动画时长失效问题

2,597 阅读2分钟

iOS键盘弹出动画问题

今天在写键盘弹出时遇见一个问题。监听UIKeyboardWillShowNotification通知让Label做一个移动的动画,指定duration为15,但动画实际完成时间却与键盘弹出时间一致。

- (void)keyboardWillShow:(NSNotification *)notification {
    [UIView animateWithDuration:15 animations:^{
        CGRect frame = self.moveLabel.frame;
        frame.origin.y = 300;
        self.moveLabel.frame = frame;
    }];
}

如果是在UIKeyboardDidShowNotification中做动画,动画完成时间则为指定时间。

- (void)keyboardDidShow:(NSNotification *)notification {
    [UIView animateWithDuration:5 animations:^{
        CGRect frame = self.moveLabel.frame;
        frame.origin.y = 300;
        self.moveLabel.frame = frame;
    }];
}

这两者的区别一个是键盘将要弹出,一个是键盘已经弹出。这跟我的动画有什么关系呀?

把UIKeyboardWillShowNotification通知方法中的动画去掉,发现依旧有动画效果。诶~好神奇~肿么回事,难道keyboardWillShow调用时就处于一个Animation里(我猜的)?

- (void)keyboardWillShow:(NSNotification *)notification {
//    [UIView animateWithDuration:15 animations:^{
        CGRect frame = self.moveLabel.frame;
        frame.origin.y = 300;
        self.moveLabel.frame = frame;
//    }];
}

搜了好多地方都没有找到keyboardWillShow的原理,好尴尬~ 为了验证自己的猜测,写了一个嵌套动画,用来验证嵌套的动画执行时间为多少。

- (IBAction)moveAction:(id)sender {
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(changeText) userInfo:nil repeats:YES];

    [UIView animateWithDuration:2 animations:^{ // 外层动画时间
        CGRect frame = self.moveLabel.frame;
        frame.origin.y = 100;                   // 外层动画坐标
        self.moveLabel.frame = frame;
        
        [UIView animateWithDuration:10 animations:^{    // 内层动画时间
            CGRect frame = self.moveLabel.frame;
            frame.origin.y = 400;                       // 内层动画坐标
            self.moveLabel.frame = frame;
        }];
    }];
}

- (void)changeText {
    self.timeCount++;
    self.moveLabel.text = [NSString stringWithFormat:@"Time = %ld,\nFrame.origin.y = %.0f", (long)self.timeCount, self.moveLabel.frame.origin.y];
    
    if (self.timeCount > 12) {
        [self.timer invalidate];
        self.timer = nil;
    }
}

最终效果为:动画时间取外层动画时间值,结果取内层动画坐标值。 所以我那个猜测还是有道理的… 希望有大神指点下keyboardWillShow的原理

更新

受到大神评论的指点,又多get到了一个知识点。
通过设置动画的options使动画忽略外层动画嵌套效果,只关心自己的动画参数。options参照www.jianshu.com/p/3723c403a…

- (void)keyboardWillShow:(NSNotification *)notification {
    [UIView animateWithDuration:15 delay:0 options:UIViewAnimationOptionOverrideInheritedDuration | UIViewAnimationOptionOverrideInheritedCurve animations:^{
        CGRect frame = self.moveLabel.frame;
        frame.origin.y = 300;
        self.moveLabel.frame = frame;
    } completion:nil];
}