What is the animation speed of the keyboard appearing in iOS8?

30,417

Solution 1

You can get the animation duration and the animation curve from the userInfo dictionary on the keyboardWillShow: notifications.

First register for the notification

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];

Then get the values from the notifications userInfo keys.

- (void)keyboardWillShow:(NSNotification*)notification {
    NSNumber *duration = [notification.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey];
    NSNumber *curve = [notification.userInfo objectForKey: UIKeyboardAnimationCurveUserInfoKey];

   // Do stuff with these values.
}

There are a lot more of these keys, and you can also get them from the UIKeyboardWillDismiss notification.

This functionality is available all the way back to iOS 3.0 :D

Heres the docs:

https://developer.apple.com/library/ios/documentation/uikit/reference/UIWindow_Class/UIWindowClassReference/UIWindowClassReference.html#//apple_ref/doc/constant_group/Keyboard_Notification_User_Info_Keys

Swift Version

NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: UIResponder.keyboardWillShowNotification, object: nil)

@objc func keyboardWillShow(_ notification: Notification) {
    let duration = notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey]
    let curve = notification.userInfo?[UIResponder.keyboardAnimationCurveUserInfoKey]
}

Solution 2

The answer with the variable duration is right and work iOS 3 to 8, but with the new version of Swift, the answer's code is not working anymore. Maybe it is a mistake on my side, but I have to write:

let duration = aNotification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as Double
let curve = aNotification.userInfo![UIKeyboardAnimationCurveUserInfoKey] as UInt

self.view.setNeedsLayout()
//baseConstraint.constant = 211
self.view.setNeedsUpdateConstraints()

UIView.animateWithDuration(duration, delay: 0.0, options: UIViewAnimationOptions(curve), animations: { _ in
    //self.view.layoutIfNeeded()
}, completion: { aaa in
    //(value: Bool) in println()
})

Looks like objectForKey is not working anymore and conversion is more strict.

Solution 3

swift3

    let duration = noti.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber
    let curve = noti.userInfo?[UIKeyboardAnimationCurveUserInfoKey] as! NSNumber

    self.view.setNeedsLayout()

    UIView.animate(withDuration: TimeInterval(duration), delay: 0, options: [UIViewAnimationOptions(rawValue: UInt(curve))], animations: {
      self.view.layoutIfNeeded()
    }, completion: nil)

Solution 4

Swift 4 update, iOS 11+

Register for the notification first in a view's lifecycle method :

override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver(self, selector: #selector(keyBoardWillShow(notification:)), name: .UIKeyboardWillShow, object: nil)
}

Then in keyBoardWillShow method :

@objc func keyBoardWillShow(notification: NSNotification) {
    guard let duration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? Double else {return}
    print(duration) // you got animation's duration safely unwraped as a double
}

Finally, don't forget to remove observer in deinit method :

deinit {
    NotificationCenter.default.removeObserver(self)
}

Solution 5

Firstly, the selected answer is the right way to go.

More can be provided here is what the animation really is. If you print all CAAnimations in the UIViewAnimation block, you'll find that it's a CASpringAnimation when setting the animation curve to the one provided in keyboard notification. The duration is 0.5, and other parameters are:

let ani = CASpringAnimation(keyPath: someKey)
ani.damping = 500
ani.stiffness = 1000
ani.mass = 3
ani.duration = 0.5

The code above can reproduce the animation precisely.

Once animation curve is set to the keyboard one, UIView animation will ignore the duration in the parameter. (If you really want to change the duration, adjust the mass value.)

Share:
30,417
user3784622
Author by

user3784622

Updated on August 04, 2020

Comments

  • user3784622
    user3784622 over 3 years

    The following is an animation for a textField and toolBar which move upward when the keyboard appears.

        baseConstraint.constant = 211
        self.view.setNeedsUpdateConstraints()
    
        UIView.animateWithDuration(0.30, animations: {
            self.view.layoutIfNeeded()
            })
    

    It is close but not quite identical. How would you modify the above animation?

    Edit:

    Here is the final code using the answer below!

       func keyboardWillShow(aNotification: NSNotification)    {
    
            let duration = aNotification.userInfo.objectForKey(UIKeyboardAnimationDurationUserInfoKey) as Double
            let curve = aNotification.userInfo.objectForKey(UIKeyboardAnimationCurveUserInfoKey) as UInt
    
            self.view.setNeedsLayout()
            baseConstraint.constant = 211
            self.view.setNeedsUpdateConstraints()
    
            UIView.animateWithDuration(duration, delay: 0, options: UIViewAnimationOptions.fromMask(curve), animations: {
            self.view.layoutIfNeeded()
            }, completion: {
            (value: Bool) in println()
            })
    }
    
  • Steven Fisher
    Steven Fisher almost 10 years
    You might want to mention this works in iOS 7 (and earlier), too. :) I'm not sure if that's clear…
  • Joel Bell
    Joel Bell almost 10 years
    Just added it! Thanks :)
  • Joel Bell
    Joel Bell almost 10 years
    Make sure the notification your registering for is UIKeyboardWillShowNotification, not UIKeyboardDidShowNotification
  • pronebird
    pronebird over 9 years
    Note: You receive KeyboardWillShow event on "quicktype" view collapse/expand, curve and duration = 0 in that case. The size passed along with UIKeyboardFrameEndUserInfoKey key and is correct.
  • Thellimist
    Thellimist about 9 years
    I tried these but still the animation doesn't work proper. I'm using self.view.frame = CGRectOffset(self.view.frame, 0, movement) instead of self.view.setNeedsLayout() self.view.setNeedsUpdateConstraints() does it matter?
  • Thellimist
    Thellimist about 9 years
    I tried these but still the animation doesn't work proper. I'm using self.view.frame = CGRectOffset(self.view.frame, 0, movement) instead of self.view.setNeedsLayout() self.view.setNeedsUpdateConstraints() does it matter?
  • Dam
    Dam about 9 years
    I do not understand where is your problem, but as now Swift is a clean code, I use it this way: override func keyboardWillShow(note: NSNotification) { super.keyboardWillShow(note) UIView.animateWithDuration(note.animationDuration) { // Your changes } }
  • Rafael Sachetto
    Rafael Sachetto over 8 years
    Doesn't work in Swift 2 return the follow error: Value of type '[NSObject : AnyObject]?' has no member 'objectForKey'. The solution is (aNotification.userInfo?[UIKeyboardAnimationDurationUserInfo‌​Key] as? NSTimeInterval)
  • Lachtan
    Lachtan over 8 years
    @RafaelSachetto try "valueForKey(..."
  • Dominic K
    Dominic K almost 8 years
    For Swift 2.2, I had to make two changes: for casting, you as! instead of as; and use UIViewAnimationOptions(rawValue: curve) instead of UIViewAnimations(curve).
  • Shawn Baek
    Shawn Baek almost 7 years
    How to change the duration.?
  • Chris Conover
    Chris Conover over 6 years
    Did you query this from the existing animation?
  • Admin
    Admin almost 5 years
    The swift version works but should be: guard let duration = notification.userInfo?[UIResponder.keyboardAnimationDuration‌​UserInfoKey] as? Double else {return} print(duration) // you got animation's duration safely unwraped as a double let curve = notification.userInfo?[UIResponder.keyboardAnimationCurveUse‌​rInfoKey] as NSNumber //else do {return} print(curve)
  • PakitoV
    PakitoV over 2 years
    to save 2 minutes to people like my future self: double duration = [[aNotification.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]; UIViewAnimationOptions curve = [[aNotification.userInfo objectForKey: UIKeyboardAnimationCurveUserInfoKey] integerValue];