iOS 7 键盘动画

iOS 7 键盘弹出用了一个新的 UIViewAnimationOptionCurve。其值为 7,但不论头文件还是文档都没有提及这个新的 curve。

头文件中的 curve 一览:

UIViewAnimationOptionCurveEaseInOut            = 0 << 16, // default
UIViewAnimationOptionCurveEaseIn               = 1 << 16,
UIViewAnimationOptionCurveEaseOut              = 2 << 16,
UIViewAnimationOptionCurveLinear               = 3 << 16 

在 iOS 7 之前,键盘是使用的默认的 UIViewAnimationOptionCurveEaseInOut,如果你的 App 有控件跟随键盘移动(比如聊天界面下的输入框),并且使用这个 curve,则在 iOS 7 下会有类似这样的不正确的效果。

Header
注:为突出效果,此处用的 UIViewAnimationOptionCurveLinear。

可以参考 QQ,就有这个问题(微信没有)。

而正确的做法是从键盘的通知中取出 curve 来使用,比如:

- (void)viewDidLoad
{
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillShow:)
                                                 name:UIKeyboardWillShowNotification
                                               object:nil];
}

- (void)keyboardWillShow:(NSNotification*)aNotification
{
    NSDictionary* info = [aNotification userInfo];

    CGSize kbSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;

    NSTimeInterval animationDuration;
    UIViewAnimationCurve animationCurve;

    [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];
    [[info objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];

    UIViewAnimationOptions options = animationCurve << 16;

    [UIView animateWithDuration:animationDuration
                          delay:0.0f
                        options:options
                     animations:^
     {
         self.constraintInputView2Bottom.constant = kbSize.height;
         [self.view layoutIfNeeded];
     }
                     completion:nil];
}

Header

2014-04-12 12:262682
  • txx2014-04-12 12:22

    为什么注册的 keyboardWillShown notification,结果用keyboardWillHide 的 method 呢....

  • nonomori2014-04-12 12:26

    @txx fixed...

  • yangcaimu2014-04-12 18:58

    good,刚好做IM

  • dee2014-04-14 08:37

    用上了....

  • xiaogang2014-05-12 20:44

    赞!确实漂亮许多!

  • Rock2014-05-21 13:08

    你好,我想知道为什么 UIViewAnimationOptions options = animationCurve << 16;
    这里要左移16位

  • Rock2014-05-22 11:55

    你好 那个问题我明白了 一个是option一个是curve 但是现在有一个新问题 option貌似有一些默认的值 虽然你只传了个curveOption但是 并不是只有这个受影响 你切换不同高度的键盘时就能发现 截取到得userinfo得duration是0 但是还是会有时延

  • erer2014-05-22 22:55

    动画的时候 还是可以看到输入框跟键盘之间有空隙

  • nonomori2014-05-22 23:06

    @Rock 谢谢你的回复。这个我再看看,现在电脑不在身边。稍后回复你:)

  • Rock2014-05-22 23:13

    不客气 我粉你微博了 你没鸟我😳
    我的结论是即便duration为0 curve有值的话还是会有时延 因为没有找到系统表示键盘状态的字段 所以我目前的解决方法是自己建个flag表示键盘是否已弹出 若已出现将curve手动置0

  • nonomori2014-05-22 23:16

    @Rock 哪个是你?-_-
    理论上说当duration=0时是不会有动画的。等我明天看看哈。谢谢啦

  • Rock2014-05-22 23:20

    NJ惺忪成性 是啊我原来也是这么想的

  • nonomori2014-05-23 16:00

    @Rock
    我测试了下,按照文档,duration为0是没有动画,直接下一个runloop执行的。但正如你所说,此处有一个动画。似乎是这个不在文档上的curve 7造成的。(你可以尝试使用Linear之类的,是没动画的)。

    所以我改了下,这样写
    if (animationDuration <= FLT_EPSILON)
    {
    self.constraintInputView2Bottom.constant = (isHide)?0:endkbSize.height;
    [self.view layoutIfNeeded];
    }
    else
    {
    UIViewAnimationOptions options = animationCurve << 16;
    [UIView animateWithDuration:animationDuration
    delay:0.0f
    options:options
    animations:^
    {
    self.constraintInputView2Bottom.constant = (isHide)?0:endkbSize.height;
    [self.view layoutIfNeeded];
    }
    completion:nil];
    }

  • Rock2014-05-23 16:05

    :) min length of comment is 5! 原来有自带防灌水。。。

  • chivas2014-11-18 20:20

    constraintInputView2Bottom 这个是什么VIEW?

  • nonomori2014-11-19 09:54

    @chivas 是个约束(constraint)的outlet,用在动画上的

  • chivas2014-11-19 10:04

    能把这个DEMO发我邮箱学习下嘛?

  • nonomori2014-11-19 10:17

    @chivas 抱歉哦,这个没做 demo 呢。 这个 constraintInputView2Bottom 其实就是输入框到底部的约束。如果你不熟悉 Autolayout 的话,也可以改变输入框的 frame 的 y 值来做动画

  • chivas2014-11-19 10:18

    能把这个DEMO发我邮箱学习下嘛?

  • chivas2014-11-19 10:19

    好的 autolayout确实不熟 还是改变frame来做吧 谢谢