如何在iOS 7上模仿键盘动画,将“完成”按钮添加到数字键盘?

时间:2013-09-16 20:56:06

标签: ios objective-c animation uiview keyboard

我一直在做这样的事情来模仿旧版iOS上的键盘动画。

CGRect keyboardBeginFrame;
[[note.userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] getValue:&keyboardBeginFrame];
self.doneKeyboardButton.frame = CGRectMake(0, (keyboardBeginFrame.origin.y + keyboardBeginFrame.size.height) - 53, 106, 53);
[[[[UIApplication sharedApplication] windows] lastObject] addSubview:self.doneKeyboardButton];

CGPoint newCenter = CGPointMake(self.doneKeyboardButton.superview.frame.origin.x + self.doneKeyboardButton.frame.size.width/2,
                                self.doneKeyboardButton.superview.frame.size.height - self.doneKeyboardButton.frame.size.height/2);

[UIView animateWithDuration:[[note.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue]-.02
                      delay:.0
                    options:[[note.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]
                 animations:^{
                     self.contentView.frame = CGRectOffset(self.contentView.frame, 0, -TextFieldViewMovement);
                     self.doneKeyboardButton.center = newCenter;
                 }
                 completion:nil];

但是,这已停止在iOS7上运行。看起来返回的值不再完全正确,完成按钮不再完全模仿键盘显示动画。

7 个答案:

答案 0 :(得分:84)

在iOS 7中,键盘使用新的未记录的动画曲线。虽然有些人注意到使用动态选项的未记录值有效,但我更喜欢使用以下内容:

[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:[notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
[UIView setAnimationCurve:[notification.userInfo[UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue]];
[UIView setAnimationBeginsFromCurrentState:YES];

// work

[UIView commitAnimations];

虽然建议使用基于块的动画,但键盘通知返回的动画曲线为UIViewAnimationCurve,而您需要传递给基于块的动画的选项为UIViewAnimationOptions。使用传统的UIView动画方法,您可以直接输入值。最重要的是,这将使用新的未记录的动画曲线(整数值为7)并使动画与键盘匹配。并且,它在iOS 6和7上也能正常工作。

答案 1 :(得分:23)

我遇到了同样的问题,并设法让动画使用iOS 7的以下参数:

    [UIView animateWithDuration:0.5
                          delay:0
         usingSpringWithDamping:500.0f
          initialSpringVelocity:0.0f
                        options:UIViewAnimationOptionCurveLinear
                     animations:animBlock
                     completion:completionBlock];

编辑:这些值是通过调试获得的, 可以 更改为新的iOS版本。 @DavidBeck's answer在iOS 7中也适用于我,所以我在这里链接它。

答案 2 :(得分:10)

Apple正在使用iOS 7中值为7的一些未记录的动画。

然而,UIViewAnimationCurve的声明定义了0到3的值

typedef enum {
   UIViewAnimationCurveEaseInOut, // 0
   UIViewAnimationCurveEaseIn,
   UIViewAnimationCurveEaseOut,
   UIViewAnimationCurveLinear // 3
} UIViewAnimationCurve;

基于块的动画所需的UIViewAnimationOptions定义为

enum {
   // ...
   UIViewAnimationOptionCurveEaseInOut            = 0 << 16,
   UIViewAnimationOptionCurveEaseIn               = 1 << 16,
   UIViewAnimationOptionCurveEaseOut              = 2 << 16,
   UIViewAnimationOptionCurveLinear               = 3 << 16,

   UIViewAnimationOptionTransitionNone            = 0 << 20,
   // ...
};

似乎Apple为动画曲线保留4位(20 - 16 = 4),允许从0到15的值(因此可能有更多未记录的值)。

有了这些知识,您只需将UIViewAnimationCurve转换为UIViewAnimationOptions即可将其转换为大约16位。在您的示例中,这意味着:

options:[[note.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue] << 16

答案 3 :(得分:7)

您可以使用animateWithDuration阻止并在其中设置曲线。它干净而且运作良好。

UIViewAnimationCurve curve = [[notification.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue];
double duration = [[notification.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];

[UIView animateWithDuration:duration
                    delay:0
                  options:UIViewAnimationOptionBeginFromCurrentState 
               animations:^{
                 [UIView setAnimationCurve:curve];
                 /* ANIMATION HERE */
                 // don't forget layoutIfNeeded if you use autolayout
               }
               completion:nil];

快乐的编码!

<强>更新

您可以使用我编写的简单UIViewController类别https://github.com/Just-/UIViewController-KeyboardAnimation

答案 4 :(得分:0)

如果您想在工具栏中添加按钮(类似于移动版Safari所做的那样),您只需使用属性inputAccessoryViewUITextFieldUITextView都有)并为自己省去所有麻烦。这个隐藏的宝石鲜为人知,我很高兴我偶然发现它。

适用于iOS 6和iOS 7,我在我的应用Routie中使用它。

答案 5 :(得分:0)

这对我来说很合适......显示键盘时会捕获持续时间。我知道对这些选项进行硬编码意味着它可以在未来中断,但它适用于7和8.这对我们来说已经足够了......

[UIView animateWithDuration:self.animationDuration
                      delay:0.0
                    options:UIViewAnimationOptionCurveEaseInOut
                 animations:^{
                     [self.view layoutIfNeeded]; completion:^(BOOL finished) {
                     if (finished)
                     {
                         if (completion)
                             completion();
                     }
                 }];

答案 6 :(得分:0)

iOS 10 +
雨燕5

更现代的替代方法(iOS 10+和Swift)是使用UIViewPropertyAnimator,它不仅接受UIView.AnimationCurve,而且是更现代的动画师。

您很有可能会使用UIResponder.keyboardAnimationCurveUserInfoKey,我们将其视为NSNumber。该密钥的文档是(Apple自己的符号,不是我的):

public class let keyboardAnimationCurveUserInfoKey: String // NSNumber of NSUInteger (UIViewAnimationCurve)

使用这种方法,我们可以消除任何猜测,只需即插即用:

if let kbDuration = notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber,
    let kbTiming = notification.userInfo?[UIResponder.keyboardAnimationCurveUserInfoKey] as? NSNumber, // doc says to treat as NSNumber
    let timing = UIView.AnimationCurve.RawValue(exactly: kbTiming), // takes an NSNumber
    let curve = UIView.AnimationCurve(rawValue: timing) // takes a raw value {
    let duration = kbDuration.doubleValue
    let animator = UIViewPropertyAnimator(duration: duration, curve: curve) {
        // add animations
    }
    animator.startAnimation()
}